{"version":3,"sources":["/Users/shyun/comcom/ain-enterprise/ain-adk/dist/cjs/chunk-2MLDWKUE.cjs","../../src/services/query.service.ts"],"names":[],"mappings":"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","file":"/Users/shyun/comcom/ain-enterprise/ain-adk/dist/cjs/chunk-2MLDWKUE.cjs","sourcesContent":[null,"import { randomUUID } from \"node:crypto\";\nimport { StatusCodes } from \"http-status-codes\";\nimport type {\n\tMemoryModule,\n\tModelFetchOptions,\n\tModelModule,\n} from \"@/modules/index.js\";\nimport { AinHttpError } from \"@/types/agent.js\";\nimport {\n\tMessageRole,\n\ttype ThreadMetadata,\n\ttype ThreadObject,\n\tThreadType,\n} from \"@/types/memory.js\";\nimport type { StreamEvent } from \"@/types/stream\";\nimport { injectAttachedDocuments } from \"@/utils/attached-documents.js\";\nimport { loggers } from \"@/utils/logger.js\";\nimport { updateRequestContext } from \"@/utils/request-context.js\";\nimport { persistTextMessage } from \"@/utils/thread-messages.js\";\nimport { sanitizeThinkingData } from \"@/utils/tool-args.js\";\nimport type { IntentFulfillService } from \"./intents/fulfill.service\";\nimport type { IntentTriggerService } from \"./intents/trigger.service\";\nimport { PIIFilterMode, type PIIService } from \"./pii.service\";\nimport generateTitlePrompt from \"./prompts/generate-title\";\n\n/**\n * Service for processing user queries through the agent's AI pipeline.\n *\n * Orchestrates the query processing workflow including intent detection,\n * model inference, tool execution, and response generation. Manages\n * conversation context and coordinates between different modules.\n */\nexport class QueryService {\n\tprivate modelModule: ModelModule;\n\tprivate memoryModule: MemoryModule;\n\tprivate intentTriggerService: IntentTriggerService;\n\tprivate intentFulfillService: IntentFulfillService;\n\tprivate piiService?: PIIService;\n\n\tconstructor(\n\t\tmodelModule: ModelModule,\n\t\tmemoryModule: MemoryModule,\n\t\tintentTriggerService: IntentTriggerService,\n\t\tintentFulfillService: IntentFulfillService,\n\t\tpiiService?: PIIService,\n\t) {\n\t\tthis.modelModule = modelModule;\n\t\tthis.memoryModule = memoryModule;\n\t\tthis.intentTriggerService = intentTriggerService;\n\t\tthis.intentFulfillService = intentFulfillService;\n\t\tthis.piiService = piiService;\n\t}\n\n\tpublic async addTextMessage(\n\t\tuserId: string,\n\t\tthreadId: string,\n\t\trole: MessageRole,\n\t\tcontent: string,\n\t\tmetadata?: Record<string, unknown>,\n\t): Promise<void> {\n\t\tawait persistTextMessage(\n\t\t\tthis.memoryModule,\n\t\t\tuserId,\n\t\t\tthreadId,\n\t\t\trole,\n\t\t\tcontent,\n\t\t\tmetadata,\n\t\t);\n\t}\n\n\tpublic async generateTitle(\n\t\tquery: string,\n\t\toptions?: ModelFetchOptions,\n\t): Promise<string> {\n\t\tconst DEFAULT_TITLE = \"New Chat\";\n\t\ttry {\n\t\t\tconst modelInstance = this.modelModule.getModel();\n\t\t\tconst modelOptions = this.modelModule.getModelOptions();\n\t\t\tconst messages = modelInstance.generateMessages({\n\t\t\t\tquery,\n\t\t\t\tsystemPrompt: await generateTitlePrompt(this.memoryModule),\n\t\t\t});\n\t\t\tconst response = await modelInstance.fetch(\n\t\t\t\tmessages,\n\t\t\t\toptions ?? modelOptions,\n\t\t\t);\n\t\t\treturn response.content || DEFAULT_TITLE;\n\t\t} catch (error) {\n\t\t\tloggers.intent.error(\"Error generating title\", {\n\t\t\t\terror,\n\t\t\t\tquery,\n\t\t\t});\n\t\t\treturn DEFAULT_TITLE;\n\t\t}\n\t}\n\n\tpublic async filterThinkingDataForStorage(\n\t\tdata: Extract<StreamEvent, { event: \"thinking_process\" }>[\"data\"],\n\t): Promise<Extract<StreamEvent, { event: \"thinking_process\" }>[\"data\"]> {\n\t\tconst sanitized = sanitizeThinkingData(data);\n\t\tif (this.piiService?.getMode() !== PIIFilterMode.MASK) {\n\t\t\treturn sanitized;\n\t\t}\n\n\t\treturn {\n\t\t\t...sanitized,\n\t\t\ttitle: await this.piiService.filterText(sanitized.title),\n\t\t\tdescription: await this.piiService.filterText(sanitized.description),\n\t\t};\n\t}\n\n\t/**\n\t * Main entry point for processing streaming user queries.\n\t *\n\t * Handles the complete query lifecycle:\n\t * 1. Loads or creates thread from memory\n\t * 2. Detects intent from the query\n\t * 3. Fulfills the intent with streaming AI response\n\t * 4. Updates conversation history in real-time\n\t *\n\t * @param threadMetadata - Metadata containing type, userId, and optional threadId\n\t * @param threadMetadata.type - The type of thread (e.g., chat, workflow)\n\t * @param threadMetadata.userId - The user's unique identifier\n\t * @param threadMetadata.threadId - Optional thread identifier\n\t * @param query - The user's input query\n\t * @returns AsyncGenerator yielding StreamEvent objects for SSE\n\t */\n\tpublic async *handleQuery(\n\t\tthreadMetadata: {\n\t\t\ttype: ThreadType;\n\t\t\tuserId: string;\n\t\t\tthreadId?: string;\n\t\t\tworkflowId?: string;\n\t\t\ttitle?: string;\n\t\t\toptions?: ModelFetchOptions;\n\t\t},\n\t\tqueryData: {\n\t\t\tquery: string;\n\t\t\tdisplayQuery?: string;\n\t\t\tdocumentIds?: string[];\n\t\t},\n\t\tisA2A?: boolean,\n\t): AsyncGenerator<StreamEvent> {\n\t\tconst {\n\t\t\ttype,\n\t\t\tuserId,\n\t\t\tworkflowId,\n\t\t\ttitle: inputTitle,\n\t\t\toptions,\n\t\t} = threadMetadata;\n\t\tconst { displayQuery } = queryData;\n\t\t// Request bodies are untyped; accept only a real array of non-empty strings.\n\t\tconst documentIds = Array.isArray(queryData.documentIds)\n\t\t\t? queryData.documentIds.filter(\n\t\t\t\t\t(id): id is string => typeof id === \"string\" && id.length > 0,\n\t\t\t\t)\n\t\t\t: undefined;\n\t\tlet { query } = queryData;\n\t\tconst threadMemory = this.memoryModule.getThreadMemory();\n\n\t\t// PII filtering on input\n\t\tconst piiMode = this.piiService?.getMode() ?? PIIFilterMode.DISABLED;\n\t\tif (piiMode === PIIFilterMode.REJECT && this.piiService) {\n\t\t\tconst hasPII = await this.piiService.containsPII(query);\n\t\t\tif (hasPII) {\n\t\t\t\tyield {\n\t\t\t\t\tevent: \"text_chunk\",\n\t\t\t\t\tdata: { delta: \"개인정보 내역은 처리할 수 없습니다.\" },\n\t\t\t\t};\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else if (piiMode === PIIFilterMode.MASK && this.piiService) {\n\t\t\tquery = await this.piiService.filterText(query);\n\t\t}\n\n\t\t// 1. Load or create thread\n\t\tlet threadId = threadMetadata.threadId;\n\t\tlet thread: ThreadObject | undefined;\n\t\tif (threadId) {\n\t\t\tthread = await threadMemory?.getThread(userId, threadId);\n\t\t\tif (!thread && !isA2A) {\n\t\t\t\tthrow new AinHttpError(StatusCodes.NOT_FOUND, \"Thread not found\");\n\t\t\t}\n\t\t}\n\n\t\tthreadId ??= randomUUID();\n\t\t// From here on every log line in this request carries the threadId.\n\t\tupdateRequestContext({ threadId });\n\t\tif (!thread) {\n\t\t\tconst title =\n\t\t\t\ttype === ThreadType.WORKFLOW && inputTitle\n\t\t\t\t\t? inputTitle\n\t\t\t\t\t: await this.generateTitle(query, options);\n\t\t\tconst metadata: ThreadMetadata = (await threadMemory?.createThread(\n\t\t\t\ttype,\n\t\t\t\tuserId,\n\t\t\t\tthreadId,\n\t\t\t\ttitle,\n\t\t\t\tworkflowId,\n\t\t\t)) || { type, userId, threadId, title, workflowId };\n\t\t\tthread = { ...metadata, messages: [] };\n\t\t\tloggers.intent.info(`Create new thread: ${threadId}`);\n\t\t\tyield {\n\t\t\t\tevent: \"thread_id\",\n\t\t\t\tdata: { type, userId, threadId, title, workflowId },\n\t\t\t};\n\t\t}\n\n\t\t// 2. intent triggering\n\t\tconst triggerResult = await this.intentTriggerService.intentTriggering(\n\t\t\tquery,\n\t\t\tthread,\n\t\t);\n\t\tconst { intents: triggeredIntents, needsAggregation } = triggerResult;\n\t\tloggers.intent.debug(\"Triggered intents\", {\n\t\t\ttriggeredIntents,\n\t\t\tneedsAggregation,\n\t\t});\n\n\t\t// only add for storage, not for inference\n\t\t// use displayQuery for better UX in enterprise application\n\t\tawait this.addTextMessage(\n\t\t\tuserId,\n\t\t\tthreadId,\n\t\t\tMessageRole.USER,\n\t\t\tdisplayQuery || query,\n\t\t\t{\n\t\t\t\tintents: triggeredIntents\n\t\t\t\t\t.filter((intent) => !!intent.intent)\n\t\t\t\t\t.map((intent) => ({\n\t\t\t\t\t\tid: intent.intent?.id,\n\t\t\t\t\t\tsubquery: intent.subquery,\n\t\t\t\t\t})),\n\t\t\t\tquery: !displayQuery ? undefined : query,\n\t\t\t\tdocumentIds: documentIds?.length ? documentIds : undefined,\n\t\t\t},\n\t\t);\n\n\t\t// Attached documents: resolve fresh content and expose it to fulfillment\n\t\t// only. Injected in-memory (never persisted); triggering above ran on the\n\t\t// short query so the body is immune to subquery rewriting.\n\t\tconst piiService = this.piiService;\n\t\tconst maskFilter =\n\t\t\tpiiService && piiService.getMode() === PIIFilterMode.MASK\n\t\t\t\t? (text: string) => piiService.filterText(text)\n\t\t\t\t: undefined;\n\t\tawait injectAttachedDocuments(\n\t\t\tthis.memoryModule,\n\t\t\tthread,\n\t\t\tdocumentIds,\n\t\t\tmaskFilter,\n\t\t);\n\n\t\t// 3. intent fulfillment (with rewrite step)\n\t\tconst stream = this.intentFulfillService.intentFulfill(\n\t\t\ttriggeredIntents,\n\t\t\tthread,\n\t\t\tquery,\n\t\t\tneedsAggregation,\n\t\t);\n\n\t\tfor await (const event of stream) {\n\t\t\tyield event;\n\t\t}\n\t}\n}\n"]}