UNPKG

@cognigy/rest-api-client

Version:

Cognigy REST-Client

375 lines 18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.KNOWLEDGE_TOOL = void 0; /* Custom modules */ const createNodeDescriptor_1 = require("../../../createNodeDescriptor"); const transcripts_1 = require("../../../../interfaces/transcripts/transcripts"); exports.KNOWLEDGE_TOOL = (0, createNodeDescriptor_1.createNodeDescriptor)({ type: "knowledgeTool", defaultLabel: "Knowledge Tool", parentType: ["aiAgentJob", "llmPromptV2"], constraints: { editable: true, deletable: true, collapsable: true, creatable: true, movable: true, placement: { predecessor: { whitelist: [] } }, childFlowCreatable: false }, behavior: { stopping: true }, preview: { type: "text", key: "toolId" }, fields: [ { key: "knowledgeStoreId", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_KNOWLEDGE_TOOL__FIELDS__KNOWLEDGE_STORE__LABEL", type: "knowledgeStoreSelect", }, { key: "toolId", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__TOOL_ID__LABEL", description: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__TOOL_ID__DESCRIPTION", type: "cognigyLLMText", defaultValue: "retrieve_knowledge_and_data", params: { required: true, rows: 1, multiline: false, maxLength: 64, } }, { key: "description", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__DESCRIPTION__LABEL", description: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__DESCRIPTION__DESCRIPTION", type: "cognigyLLMText", defaultValue: "Find the answer to general prompts or questions searching the attached data sources. It focuses exclusively on a knowledge search and does not execute tasks like small talk, calculations, or script running.", params: { required: true, rows: 5, multiline: true } }, { key: "parameters", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__PARAMETERS__LABEL", description: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__PARAMETERS__DESCRIPTION", type: "toolParameters", defaultValue: `{ "type": "object", "properties": { "generated_prompt": { "type": "string", "description": "Generated question including the context of the conversation (I want to know...)." }, "generated_buffer_phrase": { "type": "string", "description": "A generated delay or stalling phrase. Consider the context. Adapt to your speech style and language." } }, "required": ["generated_prompt", "generated_buffer_phrase"], "additionalProperties": false }`, params: { required: false, }, }, { key: "debugMessage", type: "toggle", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__DEBUG_MESSAGE__LABEL", description: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__DEBUG_MESSAGE__DESCRIPTION", defaultValue: true, }, { key: "condition", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__CONDITION__LABEL", description: "UI__NODE_EDITOR__SERVICE__AI_AGENT_TOOL__FIELDS__CONDITION__DESCRIPTION", type: "cognigyText", defaultValue: "", }, { key: "topK", type: "slider", label: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__TOP_K__LABEL", description: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__TOP_K__DESCRIPTION", defaultValue: 5, params: { min: 1, max: 10 } }, { key: "storeLocation", type: "select", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_KNOWLEDGE_TOOL__FIELDS__STORE_LOCATION__LABEL", params: { options: [ { label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_KNOWLEDGE_TOOL__FIELDS__STORE_LOCATION__OPTIONS__NONE__LABEL", value: "none" }, { label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_KNOWLEDGE_TOOL__FIELDS__STORE_LOCATION__OPTIONS__INPUT__LABEL", value: "input" }, { label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_KNOWLEDGE_TOOL__FIELDS__STORE_LOCATION__OPTIONS__CONTEXT__LABEL", value: "context" } ], }, defaultValue: "none" }, { key: "storeLocationInputKey", type: "cognigyText", label: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__INPUT_KEY__LABEL", description: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__INPUT_KEY__DESCRIPTION", defaultValue: "knowledgeSearch", condition: { key: "storeLocation", value: "input" } }, { key: "storeLocationContextKey", type: "cognigyText", label: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__CONTEXT_KEY__LABEL", description: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__CONTEXT_KEY__DESCRIPTION", defaultValue: "knowledgeSearch", condition: { key: "storeLocation", value: "context" } }, { key: "sourceTags", type: "knowledgeSourceTags", label: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__SOURCE_TAGS__LABEL", description: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__SOURCE_TAGS__DESCRIPTION", params: { tagLimit: 5 } }, { key: "sourceTagsFilterOp", type: "select", label: "UI__NODE_EDITOR__KNOWLEDGE_SEARCH__SOURCE_TAGS_FILTER_OP__LABEL", description: "UI__NODE_EDITOR__SEARCH_EXTRACT_OUTPUT__FIELDS__SOURCE_TAGS_FILTER_OP__DESCRIPTION", defaultValue: "and", params: { options: [ { label: "UI__NODE_EDITOR__SEARCH_EXTRACT_OUTPUT__FIELDS__SOURCE_TAGS_FILTER_OP__OPTIONS__AND__LABEL", value: "and" }, { label: "UI__NODE_EDITOR__SEARCH_EXTRACT_OUTPUT__FIELDS__SOURCE_TAGS_FILTER_OP__OPTIONS__OR__LABEL", value: "or" }, ] } }, ], sections: [ { key: "debugging", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_JOB__SECTIONS__DEBUG_SETTINGS__LABEL", defaultCollapsed: true, fields: [ "debugMessage", ], }, { key: "advanced", label: "UI__NODE_EDITOR__SERVICE__AI_AGENT_JOB__SECTIONS__ADVANCED__LABEL", defaultCollapsed: true, fields: [ "topK", "storeLocation", "storeLocationInputKey", "storeLocationContextKey", "sourceTags", "sourceTagsFilterOp", "condition", ], }, ], form: [ { type: "field", key: "knowledgeStoreId" }, { type: "field", key: "toolId" }, { type: "field", key: "description" }, { type: "section", key: "debugging" }, { type: "section", key: "advanced" }, ], appearance: { color: "white", textColor: "#252525", variant: "mini", }, function: async ({ cognigy, config, nodeId: thisNodeId }) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; const { api, context, input } = cognigy; const { knowledgeStoreId, debugMessage, topK, storeLocation, storeLocationInputKey, storeLocationContextKey, sourceTags, sourceTagsFilterOp, toolId, } = config; const sessionState = await api.loadSessionState(); // Check if this is an MCP direct tool call const mcpData = (_a = input.data) === null || _a === void 0 ? void 0 : _a._mcp; const isMcpToolCall = (mcpData === null || mcpData === void 0 ? void 0 : mcpData.method) === "tools/call" && ((_b = mcpData === null || mcpData === void 0 ? void 0 : mcpData.params) === null || _b === void 0 ? void 0 : _b.name); // For MCP calls, synthesize a toolCall object from input.data._mcp // For regular AI Agent calls, use sessionState.lastToolCall let toolCall; let aiAgentJobNode; if (isMcpToolCall) { // MCP tool call - create synthetic toolCall from MCP data toolCall = { id: String(mcpData.id), type: "function", index: 0, function: { name: ((_c = mcpData.params) === null || _c === void 0 ? void 0 : _c.name) || toolId, arguments: ((_d = mcpData.params) === null || _d === void 0 ? void 0 : _d.arguments) || {} } }; aiAgentJobNode = mcpData.aiAgentJobNode; } else { // Regular AI Agent tool call toolCall = (_e = sessionState.lastToolCall) === null || _e === void 0 ? void 0 : _e.toolCall; aiAgentJobNode = (_f = sessionState.lastToolCall) === null || _f === void 0 ? void 0 : _f.aiAgentJobNode; } if (!(toolCall === null || toolCall === void 0 ? void 0 : toolCall.id) && !isMcpToolCall) { (_g = api.logDebugError) === null || _g === void 0 ? void 0 : _g.call(api, "UI__DEBUG_MODE__AI_AGENT_ANSWER__ERROR__MESSAGE"); } if (toolCall && (aiAgentJobNode || isMcpToolCall) && knowledgeStoreId && (input.text || ((_j = (_h = toolCall === null || toolCall === void 0 ? void 0 : toolCall.function) === null || _h === void 0 ? void 0 : _h.arguments) === null || _j === void 0 ? void 0 : _j.generated_prompt))) { if (!((_k = api.checkThink) === null || _k === void 0 ? void 0 : _k.call(api, thisNodeId))) { let query = ((_m = (_l = toolCall === null || toolCall === void 0 ? void 0 : toolCall.function) === null || _l === void 0 ? void 0 : _l.arguments) === null || _m === void 0 ? void 0 : _m.generated_prompt) || input.text; const data = { language: input.language, query, topK, traceId: input.traceId, disableSensitiveLogging: false, knowledgeStoreIds: [knowledgeStoreId], }; const generated_buffer_phrase = (_p = (_o = toolCall === null || toolCall === void 0 ? void 0 : toolCall.function) === null || _o === void 0 ? void 0 : _o.arguments) === null || _p === void 0 ? void 0 : _p.generated_buffer_phrase; if (generated_buffer_phrase) { // output the generated buffer phrase. Don't add it to the transcript, else the LLM will repeat it next time. await ((_q = api.output) === null || _q === void 0 ? void 0 : _q.call(api, generated_buffer_phrase, { _cognigy: { _preventTranscript: true } })); } if (sourceTags && sourceTags.length > 0) { // convert each knowledgeSourceTag to a string sourceTags.forEach((tag, index) => { sourceTags[index] = tag.toString(); }); data.tagsData = { tags: sourceTags, op: sourceTagsFilterOp }; } const knowledgeSearchResponse = await api.knowledgeSearch(data); // Handle possible response errors if ((knowledgeSearchResponse === null || knowledgeSearchResponse === void 0 ? void 0 : knowledgeSearchResponse.status) !== "success") { const errorMessage = (knowledgeSearchResponse === null || knowledgeSearchResponse === void 0 ? void 0 : knowledgeSearchResponse.error) || "empty"; throw new Error(`Error while performing knowledge search. Remote returned error: ${errorMessage}`); } // Store full response data in input or context if (storeLocation === "input" && storeLocationInputKey) { input[storeLocationInputKey] = knowledgeSearchResponse; } else if (storeLocation === "context" && storeLocationContextKey) { context[storeLocationContextKey] = knowledgeSearchResponse; } const knowledgeSearchResponseData = knowledgeSearchResponse.data; // Optional Debug Message of Knowledge Search Results if (debugMessage) { const messageLines = []; if (query) { messageLines.push(`\n<b>UI__DEBUG_MODE__AI_AGENT_JOB__KNOWLEDGE_SEARCH__SEARCH_PROMPT</b> ${query}`); } if ((_r = knowledgeSearchResponseData === null || knowledgeSearchResponseData === void 0 ? void 0 : knowledgeSearchResponseData.topK) === null || _r === void 0 ? void 0 : _r.length) { knowledgeSearchResponseData === null || knowledgeSearchResponseData === void 0 ? void 0 : knowledgeSearchResponseData.topK.forEach((result, index) => { var _a; messageLines.push(`\nTop ${index + 1}:`); messageLines.push(`Distance: ${result.distance}`); messageLines.push(`Source Name: ${(_a = result.sourceMetaData) === null || _a === void 0 ? void 0 : _a.sourceName}`); messageLines.push(`Text: ${result.text}`); }); } else { messageLines.push("UI__DEBUG_MODE__AI_AGENT_JOB__KNOWLEDGE_SEARCH__NO_RESULTS"); } (_s = api.logDebugMessage) === null || _s === void 0 ? void 0 : _s.call(api, messageLines.join("\n"), "UI__DEBUG_MODE__AI_AGENT_JOB__KNOWLEDGE_SEARCH__HEADER"); } // For MCP tool calls, output the result directly - it will be captured by handleFinalPing // For regular AI Agent calls, we need to return to the parent AI Agent node if (isMcpToolCall) { // Clear the execution stack so the flow doesn't continue to other nodes // (e.g. the flow's first node) after outputting the MCP result api.resetNextNodes(); // Output the knowledge search result as the tool response // This will be captured by handleFinalPing and sent back to the MCP client await ((_t = api.output) === null || _t === void 0 ? void 0 : _t.call(api, JSON.stringify(knowledgeSearchResponseData), { _cognigy: { _preventTranscript: true } })); } else if (aiAgentJobNode) { const { flow, node } = aiAgentJobNode; if (flow && node) { // Add Tool Call Message to Transcript const toolCallTranscriptStep = { role: transcripts_1.TranscriptRole.ASSISTANT, type: transcripts_1.TranscriptEntryType.TOOL_CALL, source: "system", payload: Object.assign({ name: toolCall.function.name, id: toolCall.id, input: toolCall.function.arguments }, (toolCall.thoughtSignature && { thoughtSignature: toolCall.thoughtSignature })) }; await api.addTranscriptStep(toolCallTranscriptStep); // Add Tool Answer Message to Transcript const toolAnswer = { role: transcripts_1.TranscriptRole.TOOL, type: transcripts_1.TranscriptEntryType.TOOL_ANSWER, source: "system", payload: { toolCallId: toolCall.id, name: toolCall.function.name, content: `We have this context as answer from the knowledge source:\n${JSON.stringify(knowledgeSearchResponseData)}`, } }; await api.addTranscriptStep(toolAnswer); api.resetNextNodes(); // remove the call from the session state, because the call has been answered api.updateSessionStateValues({ lastToolCall: undefined }); await api.executeFlow({ flowNode: { flow, node, }, absorbContext: true, }); } } } else { throw new Error("Infinite Loop Detected"); } } } }); //# sourceMappingURL=knowledgeTool.js.map