{"version":3,"file":"ActionMenuService.mjs","names":[],"sources":["../../src/services/ActionMenuService.ts"],"sourcesContent":["import type { AgentContext, Logger, Query, QueryOptions } from '@credo-ts/core'\nimport { AgentConfig, CredoError, EventEmitter, injectable } from '@credo-ts/core'\nimport type { DidCommInboundMessageContext } from '@credo-ts/didcomm'\nimport type { ActionMenuStateChangedEvent } from '../ActionMenuEvents'\nimport { ActionMenuEventTypes } from '../ActionMenuEvents'\nimport { ActionMenuModuleConfig } from '../ActionMenuModuleConfig'\nimport { ActionMenuRole } from '../ActionMenuRole'\nimport { ActionMenuState } from '../ActionMenuState'\nimport { ActionMenuProblemReportError } from '../errors/ActionMenuProblemReportError'\nimport { ActionMenuProblemReportReason } from '../errors/ActionMenuProblemReportReason'\nimport type { ActionMenuProblemReportMessage } from '../messages'\nimport { MenuMessage, MenuRequestMessage, PerformMessage } from '../messages'\nimport { ActionMenu, ActionMenuSelection } from '../models'\nimport { ActionMenuRecord, ActionMenuRepository } from '../repository'\nimport type {\n  ClearMenuOptions,\n  CreateMenuOptions,\n  CreatePerformOptions,\n  CreateRequestOptions,\n  FindMenuOptions,\n} from './ActionMenuServiceOptions'\n\n/**\n * @internal\n */\n@injectable()\nexport class ActionMenuService {\n  private actionMenuRepository: ActionMenuRepository\n  private eventEmitter: EventEmitter\n  private logger: Logger\n  private config: ActionMenuModuleConfig\n\n  public constructor(\n    actionMenuRepository: ActionMenuRepository,\n    agentConfig: AgentConfig,\n    eventEmitter: EventEmitter,\n    config: ActionMenuModuleConfig\n  ) {\n    this.actionMenuRepository = actionMenuRepository\n    this.eventEmitter = eventEmitter\n    this.logger = agentConfig.logger\n    this.config = config\n  }\n\n  public async createRequest(agentContext: AgentContext, options: CreateRequestOptions) {\n    // Assert\n    options.connection.assertReady()\n\n    // Create message\n    const menuRequestMessage = new MenuRequestMessage({})\n\n    // Create record if not existent for connection/role\n    let actionMenuRecord = await this.find(agentContext, {\n      connectionId: options.connection.id,\n      role: ActionMenuRole.Requester,\n    })\n\n    if (actionMenuRecord) {\n      // Protocol will be restarted and menu cleared\n      const previousState = actionMenuRecord.state\n      actionMenuRecord.state = ActionMenuState.AwaitingRootMenu\n      actionMenuRecord.threadId = menuRequestMessage.id\n      actionMenuRecord.menu = undefined\n      actionMenuRecord.performedAction = undefined\n\n      await this.actionMenuRepository.update(agentContext, actionMenuRecord)\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, previousState)\n    } else {\n      actionMenuRecord = new ActionMenuRecord({\n        connectionId: options.connection.id,\n        role: ActionMenuRole.Requester,\n        state: ActionMenuState.AwaitingRootMenu,\n        threadId: menuRequestMessage.threadId,\n      })\n\n      await this.actionMenuRepository.save(agentContext, actionMenuRecord)\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, null)\n    }\n\n    return { message: menuRequestMessage, record: actionMenuRecord }\n  }\n\n  public async processRequest(messageContext: DidCommInboundMessageContext<MenuRequestMessage>) {\n    const { message: menuRequestMessage, agentContext } = messageContext\n\n    this.logger.debug(`Processing menu request with id ${menuRequestMessage.id}`)\n\n    // Assert\n    const connection = messageContext.assertReadyConnection()\n\n    let actionMenuRecord = await this.find(agentContext, {\n      connectionId: connection.id,\n      role: ActionMenuRole.Responder,\n    })\n\n    if (actionMenuRecord) {\n      // Protocol will be restarted and menu cleared\n      const previousState = actionMenuRecord.state\n      actionMenuRecord.state = ActionMenuState.PreparingRootMenu\n      actionMenuRecord.threadId = menuRequestMessage.id\n      actionMenuRecord.menu = undefined\n      actionMenuRecord.performedAction = undefined\n\n      await this.actionMenuRepository.update(agentContext, actionMenuRecord)\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, previousState)\n    } else {\n      // Create record\n      actionMenuRecord = new ActionMenuRecord({\n        connectionId: connection.id,\n        role: ActionMenuRole.Responder,\n        state: ActionMenuState.PreparingRootMenu,\n        threadId: menuRequestMessage.threadId,\n      })\n\n      await this.actionMenuRepository.save(agentContext, actionMenuRecord)\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, null)\n    }\n\n    return actionMenuRecord\n  }\n\n  public async createMenu(agentContext: AgentContext, options: CreateMenuOptions) {\n    // Assert connection ready\n    options.connection.assertReady()\n\n    const uniqueNames = new Set(options.menu.options.map((v) => v.name))\n    if (uniqueNames.size < options.menu.options.length) {\n      throw new CredoError('Action Menu contains duplicated options')\n    }\n\n    // Create message\n    const menuMessage = new MenuMessage({\n      title: options.menu.title,\n      description: options.menu.description,\n      options: options.menu.options,\n    })\n\n    // Check if there is an existing menu for this connection and role\n    let actionMenuRecord = await this.find(agentContext, {\n      connectionId: options.connection.id,\n      role: ActionMenuRole.Responder,\n    })\n\n    // If so, continue existing flow\n    if (actionMenuRecord) {\n      if (this.config.strictStateChecking) {\n        actionMenuRecord.assertState([ActionMenuState.Null, ActionMenuState.PreparingRootMenu, ActionMenuState.Done])\n      }\n\n      // The new menu will be bound to the existing thread\n      // unless it is in null state (protocol reset)\n      if (actionMenuRecord.state !== ActionMenuState.Null) {\n        menuMessage.setThread({ threadId: actionMenuRecord.threadId })\n      }\n\n      const previousState = actionMenuRecord.state\n      actionMenuRecord.menu = options.menu\n      actionMenuRecord.state = ActionMenuState.AwaitingSelection\n      actionMenuRecord.threadId = menuMessage.threadId\n\n      await this.actionMenuRepository.update(agentContext, actionMenuRecord)\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, previousState)\n    } else {\n      // Create record\n      actionMenuRecord = new ActionMenuRecord({\n        connectionId: options.connection.id,\n        role: ActionMenuRole.Responder,\n        state: ActionMenuState.AwaitingSelection,\n        menu: options.menu,\n        threadId: menuMessage.threadId,\n      })\n\n      await this.actionMenuRepository.save(agentContext, actionMenuRecord)\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, null)\n    }\n\n    return { message: menuMessage, record: actionMenuRecord }\n  }\n\n  public async processMenu(messageContext: DidCommInboundMessageContext<MenuMessage>) {\n    const { message: menuMessage, agentContext } = messageContext\n\n    this.logger.debug(`Processing action menu with id ${menuMessage.id}`)\n\n    // Assert\n    const connection = messageContext.assertReadyConnection()\n\n    // Check if there is an existing menu for this connection and role\n    const record = await this.find(agentContext, {\n      connectionId: connection.id,\n      role: ActionMenuRole.Requester,\n    })\n\n    if (record) {\n      // Record found: update with menu details\n      const previousState = record.state\n\n      record.state = ActionMenuState.PreparingSelection\n      record.menu = new ActionMenu({\n        title: menuMessage.title,\n        description: menuMessage.description,\n        options: menuMessage.options,\n      })\n      record.threadId = menuMessage.threadId\n      record.performedAction = undefined\n\n      await this.actionMenuRepository.update(agentContext, record)\n\n      this.emitStateChangedEvent(agentContext, record, previousState)\n    } else {\n      // Record not found: create it\n      const actionMenuRecord = new ActionMenuRecord({\n        connectionId: connection.id,\n        role: ActionMenuRole.Requester,\n        state: ActionMenuState.PreparingSelection,\n        threadId: menuMessage.threadId,\n        menu: new ActionMenu({\n          title: menuMessage.title,\n          description: menuMessage.description,\n          options: menuMessage.options,\n        }),\n      })\n\n      await this.actionMenuRepository.save(agentContext, actionMenuRecord)\n\n      this.emitStateChangedEvent(agentContext, actionMenuRecord, null)\n    }\n  }\n\n  public async createPerform(agentContext: AgentContext, options: CreatePerformOptions) {\n    const { actionMenuRecord: record, performedAction: performedSelection } = options\n\n    // Assert\n    record.assertRole(ActionMenuRole.Requester)\n    if (this.config.strictStateChecking) {\n      record.assertState([ActionMenuState.PreparingSelection])\n    }\n\n    const validSelection = record.menu?.options.some((item) => item.name === performedSelection.name)\n    if (!validSelection) {\n      throw new CredoError('Selection does not match valid actions')\n    }\n\n    const previousState = record.state\n\n    // Create message\n    const menuMessage = new PerformMessage({\n      name: performedSelection.name,\n      params: performedSelection.params,\n      threadId: record.threadId,\n    })\n\n    // Update record\n    record.performedAction = options.performedAction\n    record.state = ActionMenuState.Done\n\n    await this.actionMenuRepository.update(agentContext, record)\n\n    this.emitStateChangedEvent(agentContext, record, previousState)\n\n    return { message: menuMessage, record }\n  }\n\n  public async processPerform(messageContext: DidCommInboundMessageContext<PerformMessage>) {\n    const { message: performMessage, agentContext } = messageContext\n\n    this.logger.debug(`Processing action menu perform with id ${performMessage.id}`)\n\n    const connection = messageContext.assertReadyConnection()\n\n    // Check if there is an existing menu for this connection and role\n    const record = await this.find(agentContext, {\n      connectionId: connection.id,\n      role: ActionMenuRole.Responder,\n      threadId: performMessage.threadId,\n    })\n\n    if (record) {\n      // Record found: check state and update with menu details\n\n      // A Null state means that menu has been cleared by the responder.\n      // Requester should be informed in order to request another menu\n      if (record.state === ActionMenuState.Null) {\n        throw new ActionMenuProblemReportError('Action Menu has been cleared by the responder', {\n          problemCode: ActionMenuProblemReportReason.Timeout,\n        })\n      }\n      if (this.config.strictStateChecking) {\n        record.assertState([ActionMenuState.AwaitingSelection])\n      }\n\n      const validSelection = record.menu?.options.some((item) => item.name === performMessage.name)\n      if (!validSelection) {\n        throw new CredoError('Selection does not match valid actions')\n      }\n\n      const previousState = record.state\n\n      record.state = ActionMenuState.Done\n      record.performedAction = new ActionMenuSelection({ name: performMessage.name, params: performMessage.params })\n\n      await this.actionMenuRepository.update(agentContext, record)\n\n      this.emitStateChangedEvent(agentContext, record, previousState)\n    } else {\n      throw new CredoError(`No Action Menu found with thread id ${messageContext.message.threadId}`)\n    }\n  }\n\n  public async clearMenu(agentContext: AgentContext, options: ClearMenuOptions) {\n    const { actionMenuRecord: record } = options\n\n    const previousState = record.state\n\n    // Update record\n    record.state = ActionMenuState.Null\n    record.menu = undefined\n    record.performedAction = undefined\n\n    await this.actionMenuRepository.update(agentContext, record)\n\n    this.emitStateChangedEvent(agentContext, record, previousState)\n\n    return record\n  }\n\n  public async processProblemReport(\n    messageContext: DidCommInboundMessageContext<ActionMenuProblemReportMessage>\n  ): Promise<ActionMenuRecord> {\n    const { message: actionMenuProblemReportMessage, agentContext } = messageContext\n\n    const connection = messageContext.assertReadyConnection()\n\n    this.logger.debug(`Processing problem report with id ${actionMenuProblemReportMessage.id}`)\n\n    const actionMenuRecord = await this.find(agentContext, {\n      role: ActionMenuRole.Requester,\n      connectionId: connection.id,\n    })\n\n    if (!actionMenuRecord) {\n      throw new CredoError(`Unable to process action menu problem: record not found for connection id ${connection.id}`)\n    }\n    // Clear menu to restart flow\n    return await this.clearMenu(agentContext, { actionMenuRecord })\n  }\n\n  public async findById(agentContext: AgentContext, actionMenuRecordId: string) {\n    return await this.actionMenuRepository.findById(agentContext, actionMenuRecordId)\n  }\n\n  public async find(agentContext: AgentContext, options: FindMenuOptions) {\n    return await this.actionMenuRepository.findSingleByQuery(agentContext, {\n      connectionId: options.connectionId,\n      role: options.role,\n      threadId: options.threadId,\n    })\n  }\n\n  public async findAllByQuery(\n    agentContext: AgentContext,\n    options: Query<ActionMenuRecord>,\n    queryOptions?: QueryOptions\n  ) {\n    return await this.actionMenuRepository.findByQuery(agentContext, options, queryOptions)\n  }\n\n  private emitStateChangedEvent(\n    agentContext: AgentContext,\n    actionMenuRecord: ActionMenuRecord,\n    previousState: ActionMenuState | null\n  ) {\n    this.eventEmitter.emit<ActionMenuStateChangedEvent>(agentContext, {\n      type: ActionMenuEventTypes.ActionMenuStateChanged,\n      payload: {\n        actionMenuRecord: actionMenuRecord.clone(),\n        previousState: previousState,\n      },\n    })\n  }\n}\n"],"mappings":"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"}