@cognigy/rest-api-client
Version:
Cognigy REST-Client
375 lines • 18 kB
JavaScript
"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