@nocobase/plugin-ai 2.1.0-alpha.13 → 2.1.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/ai-employees/atlas/index.d.ts +10 -0
- package/dist/ai/ai-employees/atlas/index.js +56 -0
- package/dist/ai/ai-employees/atlas/prompt.md +84 -0
- package/dist/ai/ai-employees/vera.js +1 -1
- package/dist/ai/tools/chartGenerator.js +1 -0
- package/dist/ai/tools/getSkill.js +1 -1
- package/dist/ai/tools/sub-agents/dispatch-sub-agent-task.d.ts +10 -0
- package/dist/ai/tools/sub-agents/dispatch-sub-agent-task.js +108 -0
- package/dist/ai/tools/sub-agents/get-ai-employee.d.ts +10 -0
- package/dist/ai/tools/sub-agents/get-ai-employee.js +67 -0
- package/dist/ai/tools/sub-agents/list-ai-employees.d.ts +10 -0
- package/dist/ai/tools/sub-agents/list-ai-employees.js +64 -0
- package/dist/ai/tools/sub-agents/shared.d.ts +33 -0
- package/dist/ai/tools/sub-agents/shared.js +169 -0
- package/dist/ai/tools/suggestions.js +2 -2
- package/dist/client/7237366e104efa7a.js +10 -0
- package/dist/client/748fbb87c1013c6e.js +10 -0
- package/dist/client/ai-employees/built-in/utils.d.ts +1 -0
- package/dist/client/ai-employees/chatbox/AIEmployeeSwitch.d.ts +0 -1
- package/dist/client/ai-employees/chatbox/hooks/useChatBoxActions.d.ts +5 -3
- package/dist/client/ai-employees/chatbox/roles.d.ts +1 -0
- package/dist/client/ai-employees/chatbox/stores/chat-messages.d.ts +8 -0
- package/dist/client/ai-employees/chatbox/utils.d.ts +15 -1
- package/dist/client/ai-employees/sub-agents/tools/index.d.ts +10 -0
- package/dist/client/ai-employees/sub-agents/ui/SubAgentDispatchCard.d.ts +21 -0
- package/dist/client/ai-employees/types.d.ts +19 -0
- package/dist/client/index.js +7 -7
- package/dist/externalVersion.js +16 -15
- package/dist/locale/en-US.json +10 -1
- package/dist/locale/zh-CN.json +10 -1
- package/dist/node_modules/fast-glob/package.json +1 -1
- package/dist/node_modules/flexsearch/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/node_modules/openai/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/ai-employees/ai-conversations.d.ts +64 -0
- package/dist/server/ai-employees/ai-conversations.js +285 -0
- package/dist/server/ai-employees/ai-employee.d.ts +85 -9
- package/dist/server/ai-employees/ai-employee.js +264 -149
- package/dist/server/ai-employees/middleware/conversation.d.ts +2 -0
- package/dist/server/ai-employees/middleware/conversation.js +38 -5
- package/dist/server/ai-employees/middleware/tools.js +37 -10
- package/dist/server/ai-employees/prompts.d.ts +9 -1
- package/dist/server/ai-employees/prompts.js +24 -2
- package/dist/server/ai-employees/sub-agents/dispatcher.d.ts +36 -0
- package/dist/server/ai-employees/sub-agents/dispatcher.js +225 -0
- package/dist/server/ai-employees/sub-agents/index.d.ts +9 -0
- package/dist/server/ai-employees/sub-agents/index.js +36 -0
- package/dist/server/collections/ai-conversations.js +6 -0
- package/dist/server/llm-providers/anthropic.d.ts +1 -0
- package/dist/server/llm-providers/anthropic.js +2 -1
- package/dist/server/llm-providers/dashscope.d.ts +3 -0
- package/dist/server/llm-providers/dashscope.js +16 -2
- package/dist/server/llm-providers/deepseek.d.ts +1 -0
- package/dist/server/llm-providers/deepseek.js +5 -2
- package/dist/server/llm-providers/google-genai.d.ts +1 -0
- package/dist/server/llm-providers/google-genai.js +2 -1
- package/dist/server/llm-providers/kimi/provider.d.ts +1 -0
- package/dist/server/llm-providers/openai/responses.d.ts +1 -0
- package/dist/server/llm-providers/openai/responses.js +2 -1
- package/dist/server/llm-providers/provider.d.ts +1 -10
- package/dist/server/llm-providers/provider.js +3 -34
- package/dist/server/migrations/20260319000000-add-ai-conversations-from.d.ts +14 -0
- package/dist/server/migrations/20260319000000-add-ai-conversations-from.js +63 -0
- package/dist/server/plugin.d.ts +4 -0
- package/dist/server/plugin.js +4 -0
- package/dist/server/resource/aiConversations.d.ts +3 -3
- package/dist/server/resource/aiConversations.js +125 -159
- package/dist/server/types/ai-chat-conversation.type.d.ts +8 -2
- package/dist/server/types/ai-message.type.d.ts +7 -0
- package/dist/server/utils.d.ts +3 -0
- package/dist/server/utils.js +25 -1
- package/package.json +4 -2
- package/dist/client/27539a4356faebb1.js +0 -10
|
@@ -36,11 +36,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
var ai_employee_exports = {};
|
|
38
38
|
__export(ai_employee_exports, {
|
|
39
|
-
AIEmployee: () => AIEmployee
|
|
39
|
+
AIEmployee: () => AIEmployee,
|
|
40
|
+
ChatStreamProtocol: () => ChatStreamProtocol
|
|
40
41
|
});
|
|
41
42
|
module.exports = __toCommonJS(ai_employee_exports);
|
|
42
43
|
var import_database = require("@nocobase/database");
|
|
43
|
-
var import_provider = require("../llm-providers/provider");
|
|
44
44
|
var import_utils = require("../utils");
|
|
45
45
|
var import_prompts = require("./prompts");
|
|
46
46
|
var import_lodash = __toESM(require("lodash"));
|
|
@@ -54,20 +54,32 @@ var import_langgraph = require("@langchain/langgraph");
|
|
|
54
54
|
var import_stream = require("@langchain/core/utils/stream");
|
|
55
55
|
var import_utils2 = require("./utils");
|
|
56
56
|
var import_base = require("@langchain/core/callbacks/base");
|
|
57
|
+
var import_shared = require("../../ai/tools/sub-agents/shared");
|
|
57
58
|
class AIEmployee {
|
|
59
|
+
sessionId;
|
|
60
|
+
from = "main-agent";
|
|
58
61
|
employee;
|
|
59
62
|
aiChatConversation;
|
|
60
63
|
skillSettings;
|
|
61
64
|
plugin;
|
|
62
65
|
db;
|
|
63
|
-
sessionId;
|
|
64
66
|
ctx;
|
|
65
67
|
systemMessage;
|
|
68
|
+
protocol;
|
|
66
69
|
webSearch;
|
|
67
70
|
model;
|
|
68
71
|
legacy;
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
constructor({
|
|
73
|
+
ctx,
|
|
74
|
+
employee,
|
|
75
|
+
sessionId,
|
|
76
|
+
systemMessage,
|
|
77
|
+
skillSettings,
|
|
78
|
+
webSearch,
|
|
79
|
+
model,
|
|
80
|
+
legacy,
|
|
81
|
+
from = "main-agent"
|
|
82
|
+
}) {
|
|
71
83
|
this.employee = employee;
|
|
72
84
|
this.ctx = ctx;
|
|
73
85
|
this.plugin = ctx.app.pm.get("ai");
|
|
@@ -78,10 +90,19 @@ class AIEmployee {
|
|
|
78
90
|
this.skillSettings = skillSettings;
|
|
79
91
|
this.model = model;
|
|
80
92
|
this.legacy = legacy;
|
|
93
|
+
this.from = from;
|
|
81
94
|
const builtInManager = this.plugin.builtInManager;
|
|
82
95
|
builtInManager.setupBuiltInInfo(ctx, this.employee);
|
|
83
96
|
this.webSearch = webSearch;
|
|
84
|
-
this.protocol = ChatStreamProtocol.
|
|
97
|
+
this.protocol = ChatStreamProtocol.fromContext(ctx);
|
|
98
|
+
}
|
|
99
|
+
async getFormatMessages(userMessages) {
|
|
100
|
+
const { provider } = await this.getLLMService();
|
|
101
|
+
const { messages } = await this.aiChatConversation.getChatContext({
|
|
102
|
+
userMessages,
|
|
103
|
+
formatMessages: (messages2) => this.formatMessages({ messages: messages2, provider })
|
|
104
|
+
});
|
|
105
|
+
return messages;
|
|
85
106
|
}
|
|
86
107
|
// === Chat flow ===
|
|
87
108
|
buildState(messages) {
|
|
@@ -186,7 +207,9 @@ class AIEmployee {
|
|
|
186
207
|
async invoke({
|
|
187
208
|
messageId,
|
|
188
209
|
userMessages = [],
|
|
189
|
-
userDecisions
|
|
210
|
+
userDecisions,
|
|
211
|
+
writer,
|
|
212
|
+
context
|
|
190
213
|
}) {
|
|
191
214
|
try {
|
|
192
215
|
const { provider, chatContext, config, state } = await this.buildChatContext({
|
|
@@ -194,15 +217,21 @@ class AIEmployee {
|
|
|
194
217
|
userMessages,
|
|
195
218
|
userDecisions
|
|
196
219
|
});
|
|
197
|
-
const { threadId } = await this.getCurrentThread();
|
|
198
220
|
const invokeConfig = {
|
|
199
|
-
|
|
200
|
-
context: { ctx: this.ctx },
|
|
221
|
+
context: { ctx: this.ctx, decisions: chatContext.decisions, ...context },
|
|
201
222
|
recursionLimit: 100,
|
|
223
|
+
writer,
|
|
202
224
|
...config
|
|
203
225
|
};
|
|
226
|
+
if (this.from === "main-agent") {
|
|
227
|
+
const { threadId } = await this.getCurrentThread();
|
|
228
|
+
invokeConfig.configurable = { thread_id: threadId };
|
|
229
|
+
}
|
|
204
230
|
return await this.agentInvoke(provider, chatContext, invokeConfig, state);
|
|
205
231
|
} catch (err) {
|
|
232
|
+
if (err.name === "GraphInterrupt") {
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
206
235
|
this.ctx.log.error(err);
|
|
207
236
|
throw err;
|
|
208
237
|
}
|
|
@@ -250,17 +279,24 @@ class AIEmployee {
|
|
|
250
279
|
middleware
|
|
251
280
|
}) {
|
|
252
281
|
const model = provider.createModel();
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
282
|
+
const allTools = provider.resolveTools((tools == null ? void 0 : tools.map(import_utils.buildTool)) ?? []);
|
|
283
|
+
if (this.from === "main-agent") {
|
|
284
|
+
const checkpointer = new import_checkpoints.SequelizeCollectionSaver(() => this.ctx.app.mainDataSource);
|
|
285
|
+
return (0, import_langchain.createAgent)({ model, tools: allTools, middleware, systemPrompt, checkpointer });
|
|
286
|
+
} else {
|
|
287
|
+
return (0, import_langchain.createAgent)({ model, tools: allTools, middleware, systemPrompt });
|
|
288
|
+
}
|
|
257
289
|
}
|
|
258
290
|
getAgentInput(context, state) {
|
|
259
|
-
var _a;
|
|
260
|
-
if ((_a = context.decisions) == null ? void 0 : _a.length) {
|
|
291
|
+
var _a, _b;
|
|
292
|
+
if ((_b = (_a = context.decisions) == null ? void 0 : _a.decisions) == null ? void 0 : _b.length) {
|
|
261
293
|
return new import_langgraph.Command({
|
|
262
|
-
resume: {
|
|
263
|
-
decisions:
|
|
294
|
+
resume: context.decisions.interruptId ? {
|
|
295
|
+
[context.decisions.interruptId]: {
|
|
296
|
+
decisions: context.decisions.decisions
|
|
297
|
+
}
|
|
298
|
+
} : {
|
|
299
|
+
decisions: context.decisions.decisions
|
|
264
300
|
}
|
|
265
301
|
});
|
|
266
302
|
}
|
|
@@ -273,13 +309,16 @@ class AIEmployee {
|
|
|
273
309
|
const { systemPrompt, tools, middleware } = context;
|
|
274
310
|
const agent = await this.createAgent({ provider, systemPrompt, tools, middleware });
|
|
275
311
|
const input = this.getAgentInput(context, state);
|
|
276
|
-
|
|
312
|
+
if (this.from === "sub-agent") {
|
|
313
|
+
delete config.configurable;
|
|
314
|
+
}
|
|
315
|
+
return agent.stream(input, this.withRunMetadata(config));
|
|
277
316
|
}
|
|
278
317
|
async agentInvoke(provider, context, config, state) {
|
|
279
318
|
const { systemPrompt, tools, middleware } = context;
|
|
280
319
|
const agent = await this.createAgent({ provider, systemPrompt, tools, middleware });
|
|
281
320
|
const input = this.getAgentInput(context, state);
|
|
282
|
-
return agent.invoke(input, config);
|
|
321
|
+
return agent.invoke(input, this.withRunMetadata(config));
|
|
283
322
|
}
|
|
284
323
|
async prepareChatStream({
|
|
285
324
|
chatContext,
|
|
@@ -297,8 +336,8 @@ class AIEmployee {
|
|
|
297
336
|
{
|
|
298
337
|
signal,
|
|
299
338
|
streamMode: ["updates", "messages", "custom"],
|
|
300
|
-
configurable: { thread_id: threadId },
|
|
301
|
-
context: { ctx: this.ctx },
|
|
339
|
+
configurable: this.from === "main-agent" ? { thread_id: threadId } : void 0,
|
|
340
|
+
context: { ctx: this.ctx, decisions: chatContext.decisions },
|
|
302
341
|
recursionLimit: 100,
|
|
303
342
|
...config
|
|
304
343
|
},
|
|
@@ -311,8 +350,8 @@ class AIEmployee {
|
|
|
311
350
|
}
|
|
312
351
|
}
|
|
313
352
|
async processChatStream(stream, options) {
|
|
314
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s
|
|
315
|
-
|
|
353
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
|
|
354
|
+
const aiMessageIdMap = /* @__PURE__ */ new Map();
|
|
316
355
|
const { signal, providerName, model, provider, responseMetadata, allowEmpty = false } = options;
|
|
317
356
|
let isReasoning = false;
|
|
318
357
|
let gathered;
|
|
@@ -329,58 +368,69 @@ class AIEmployee {
|
|
|
329
368
|
}
|
|
330
369
|
await this.aiChatConversation.withTransaction(async (conversation, transaction) => {
|
|
331
370
|
const result = await conversation.addMessages(values);
|
|
332
|
-
if (toolCalls == null ? void 0 : toolCalls.length) {
|
|
333
|
-
await this.initToolCall(transaction, result.messageId, toolCalls);
|
|
334
|
-
}
|
|
335
371
|
});
|
|
336
372
|
}
|
|
337
373
|
});
|
|
338
374
|
try {
|
|
339
|
-
|
|
375
|
+
const aiEmployeeConversation = {
|
|
376
|
+
sessionId: this.sessionId,
|
|
377
|
+
from: this.from,
|
|
378
|
+
username: this.employee.username
|
|
379
|
+
};
|
|
380
|
+
this.protocol.with(aiEmployeeConversation).startStream();
|
|
340
381
|
for await (const [mode, chunks] of stream) {
|
|
341
382
|
if (mode === "messages") {
|
|
342
|
-
const [chunk] = chunks;
|
|
383
|
+
const [chunk, metadata] = chunks;
|
|
384
|
+
const { currentConversation } = metadata;
|
|
343
385
|
if (chunk.type === "ai") {
|
|
344
386
|
gathered = gathered !== void 0 ? (0, import_stream.concat)(gathered, chunk) : chunk;
|
|
345
387
|
if (chunk.content) {
|
|
346
388
|
if (isReasoning) {
|
|
347
389
|
isReasoning = false;
|
|
348
|
-
this.protocol.stopReasoning();
|
|
390
|
+
this.protocol.with(currentConversation).stopReasoning();
|
|
349
391
|
}
|
|
350
392
|
const parsedContent = provider.parseResponseChunk(chunk.content);
|
|
351
393
|
if (parsedContent) {
|
|
352
|
-
this.protocol.content(parsedContent);
|
|
394
|
+
this.protocol.with(currentConversation).content(parsedContent);
|
|
353
395
|
}
|
|
354
396
|
}
|
|
355
397
|
if ((_a = chunk.tool_call_chunks) == null ? void 0 : _a.length) {
|
|
356
|
-
this.protocol.toolCallChunks(chunk.tool_call_chunks);
|
|
398
|
+
this.protocol.with(currentConversation).toolCallChunks(chunk.tool_call_chunks);
|
|
357
399
|
}
|
|
358
400
|
const webSearch = provider.parseWebSearchAction(chunk);
|
|
359
401
|
if (webSearch == null ? void 0 : webSearch.length) {
|
|
360
|
-
this.protocol.webSearch(webSearch);
|
|
402
|
+
this.protocol.with(currentConversation).webSearch(webSearch);
|
|
361
403
|
}
|
|
362
404
|
const reasoningContent = provider.parseReasoningContent(chunk);
|
|
363
405
|
if (reasoningContent) {
|
|
364
406
|
isReasoning = true;
|
|
365
|
-
this.protocol.reasoning(reasoningContent);
|
|
407
|
+
this.protocol.with(currentConversation).reasoning(reasoningContent);
|
|
366
408
|
}
|
|
367
409
|
}
|
|
368
410
|
} else if (mode === "updates") {
|
|
369
411
|
if ("__interrupt__" in chunks) {
|
|
412
|
+
const interruptId = chunks.__interrupt__[0].id;
|
|
370
413
|
const interruptActions = this.toInterruptActions(chunks.__interrupt__[0].value);
|
|
371
414
|
if (interruptActions.size) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (!interruptAction) {
|
|
415
|
+
const toolsMap = await this.getToolsMap();
|
|
416
|
+
for (const interruptAction of interruptActions.values()) {
|
|
417
|
+
if (!interruptAction.currentConversation || !interruptAction.toolCall) {
|
|
418
|
+
this.logger.warn("currentConversation or toolCall not exist in __interrupt__", interruptAction);
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
const { sessionId, from, username } = interruptAction.currentConversation;
|
|
422
|
+
const { id: toolCallId, name: toolCallName } = interruptAction.toolCall;
|
|
423
|
+
const messageId = aiMessageIdMap.get(sessionId);
|
|
424
|
+
if (!messageId) {
|
|
375
425
|
continue;
|
|
376
426
|
}
|
|
377
|
-
await this.updateToolCallInterrupted(
|
|
378
|
-
this.protocol.toolCallStatus({
|
|
427
|
+
await this.updateToolCallInterrupted(sessionId, messageId, toolCallId, interruptId, interruptAction);
|
|
428
|
+
this.protocol.with(interruptAction.currentConversation).toolCallStatus({
|
|
379
429
|
toolCall: {
|
|
380
|
-
messageId
|
|
381
|
-
id:
|
|
382
|
-
name:
|
|
383
|
-
willInterrupt:
|
|
430
|
+
messageId,
|
|
431
|
+
id: toolCallId,
|
|
432
|
+
name: toolCallName,
|
|
433
|
+
willInterrupt: this.shouldInterruptToolCall(toolsMap.get(toolCallName))
|
|
384
434
|
},
|
|
385
435
|
invokeStatus: "interrupted",
|
|
386
436
|
interruptAction
|
|
@@ -389,7 +439,9 @@ class AIEmployee {
|
|
|
389
439
|
}
|
|
390
440
|
}
|
|
391
441
|
} else if (mode === "custom") {
|
|
442
|
+
const { currentConversation } = chunks;
|
|
392
443
|
if (chunks.action === "AfterAIMessageSaved") {
|
|
444
|
+
aiMessageIdMap.set(currentConversation.sessionId, chunks.body.messageId);
|
|
393
445
|
const data = responseMetadata.get(chunks.body.id);
|
|
394
446
|
if (data) {
|
|
395
447
|
const savedMessage = await this.aiMessagesModel.findOne({
|
|
@@ -417,32 +469,31 @@ class AIEmployee {
|
|
|
417
469
|
}
|
|
418
470
|
}
|
|
419
471
|
} else if (chunks.action === "initToolCalls") {
|
|
420
|
-
toolCalls
|
|
421
|
-
this.protocol.toolCalls(chunks.body);
|
|
472
|
+
this.protocol.with(currentConversation).toolCalls(chunks.body);
|
|
422
473
|
} else if (chunks.action === "beforeToolCall") {
|
|
423
474
|
const toolsMap = await this.getToolsMap();
|
|
424
|
-
const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((
|
|
425
|
-
this.protocol.toolCallStatus({
|
|
475
|
+
const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_c = (_b = chunks.body) == null ? void 0 : _b.toolCall) == null ? void 0 : _c.name));
|
|
476
|
+
this.protocol.with(currentConversation).toolCallStatus({
|
|
426
477
|
toolCall: {
|
|
427
|
-
messageId: (
|
|
428
|
-
id: (
|
|
429
|
-
name: (
|
|
478
|
+
messageId: (_e = (_d = chunks.body) == null ? void 0 : _d.toolCall) == null ? void 0 : _e.messageId,
|
|
479
|
+
id: (_g = (_f = chunks.body) == null ? void 0 : _f.toolCall) == null ? void 0 : _g.id,
|
|
480
|
+
name: (_i = (_h = chunks.body) == null ? void 0 : _h.toolCall) == null ? void 0 : _i.name,
|
|
430
481
|
willInterrupt
|
|
431
482
|
},
|
|
432
483
|
invokeStatus: "pending"
|
|
433
484
|
});
|
|
434
485
|
} else if (chunks.action === "afterToolCall") {
|
|
435
486
|
const toolsMap = await this.getToolsMap();
|
|
436
|
-
const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((
|
|
437
|
-
this.protocol.toolCallStatus({
|
|
487
|
+
const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_k = (_j = chunks.body) == null ? void 0 : _j.toolCall) == null ? void 0 : _k.name));
|
|
488
|
+
this.protocol.with(currentConversation).toolCallStatus({
|
|
438
489
|
toolCall: {
|
|
439
|
-
messageId: (
|
|
440
|
-
id: (
|
|
441
|
-
name: (
|
|
490
|
+
messageId: (_m = (_l = chunks.body) == null ? void 0 : _l.toolCall) == null ? void 0 : _m.messageId,
|
|
491
|
+
id: (_o = (_n = chunks.body) == null ? void 0 : _n.toolCall) == null ? void 0 : _o.id,
|
|
492
|
+
name: (_q = (_p = chunks.body) == null ? void 0 : _p.toolCall) == null ? void 0 : _q.name,
|
|
442
493
|
willInterrupt
|
|
443
494
|
},
|
|
444
495
|
invokeStatus: "done",
|
|
445
|
-
status: (
|
|
496
|
+
status: (_s = (_r = chunks.body) == null ? void 0 : _r.toolCallResult) == null ? void 0 : _s.status
|
|
446
497
|
});
|
|
447
498
|
} else if (chunks.action === "beforeSendToolMessage") {
|
|
448
499
|
const { messageId, messages } = chunks.body ?? {};
|
|
@@ -455,7 +506,7 @@ class AIEmployee {
|
|
|
455
506
|
for (const { metadata } of messages) {
|
|
456
507
|
const tools = toolsMap.get(metadata.toolName);
|
|
457
508
|
const toolCallResult = toolCallResultMap.get(metadata.toolCallId);
|
|
458
|
-
this.protocol.toolCallStatus({
|
|
509
|
+
this.protocol.with(currentConversation).toolCallStatus({
|
|
459
510
|
toolCall: {
|
|
460
511
|
messageId,
|
|
461
512
|
id: metadata.toolCallId,
|
|
@@ -467,7 +518,9 @@ class AIEmployee {
|
|
|
467
518
|
});
|
|
468
519
|
}
|
|
469
520
|
}
|
|
470
|
-
this.protocol.newMessage();
|
|
521
|
+
this.protocol.with(currentConversation).newMessage();
|
|
522
|
+
} else if (chunks.action === "afterSubAgentInvoke") {
|
|
523
|
+
this.protocol.with(currentConversation).subAgentCompleted();
|
|
471
524
|
}
|
|
472
525
|
}
|
|
473
526
|
}
|
|
@@ -475,7 +528,7 @@ class AIEmployee {
|
|
|
475
528
|
this.sendErrorResponse("Empty message");
|
|
476
529
|
return;
|
|
477
530
|
}
|
|
478
|
-
this.protocol.endStream();
|
|
531
|
+
this.protocol.with(aiEmployeeConversation).endStream();
|
|
479
532
|
} catch (err) {
|
|
480
533
|
this.ctx.log.error(err);
|
|
481
534
|
if (err.name === "GraphRecursionError") {
|
|
@@ -484,7 +537,9 @@ class AIEmployee {
|
|
|
484
537
|
this.sendErrorResponse(provider.parseResponseError(err));
|
|
485
538
|
}
|
|
486
539
|
} finally {
|
|
487
|
-
this.
|
|
540
|
+
if (this.from === "main-agent") {
|
|
541
|
+
this.ctx.res.end();
|
|
542
|
+
}
|
|
488
543
|
}
|
|
489
544
|
}
|
|
490
545
|
// === Prompts & knowledge base ===
|
|
@@ -566,6 +621,7 @@ ${workContextBackground.join("\n")}`;
|
|
|
566
621
|
}
|
|
567
622
|
}
|
|
568
623
|
const availableSkills = await this.getAvailableSkills();
|
|
624
|
+
const availableAIEmployees = await this.getAvailableAIEmployees();
|
|
569
625
|
const systemPrompt = (0, import_prompts.getSystemPrompt)({
|
|
570
626
|
aiEmployee: {
|
|
571
627
|
nickname: this.employee.nickname,
|
|
@@ -581,7 +637,8 @@ ${workContextBackground.join("\n")}`;
|
|
|
581
637
|
locale: this.ctx.getCurrentLocale() || "en-US"
|
|
582
638
|
},
|
|
583
639
|
knowledgeBase,
|
|
584
|
-
availableSkills
|
|
640
|
+
availableSkills,
|
|
641
|
+
availableAIEmployees
|
|
585
642
|
});
|
|
586
643
|
const { important } = this.ctx.action.params.values || {};
|
|
587
644
|
if (important === "GraphRecursionError") {
|
|
@@ -706,23 +763,54 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
706
763
|
transaction
|
|
707
764
|
});
|
|
708
765
|
}
|
|
709
|
-
async updateToolCallInterrupted(messageId, toolCallId, interruptAction) {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
766
|
+
async updateToolCallInterrupted(sessionId, messageId, toolCallId, interruptId, interruptAction) {
|
|
767
|
+
return await this.db.sequelize.transaction(async (transaction) => {
|
|
768
|
+
const [updated] = await this.aiToolMessagesModel.update(
|
|
769
|
+
{
|
|
770
|
+
invokeStatus: "interrupted",
|
|
771
|
+
interruptActionOrder: interruptAction.order,
|
|
772
|
+
interruptAction
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
where: {
|
|
776
|
+
sessionId,
|
|
777
|
+
messageId,
|
|
778
|
+
toolCallId,
|
|
779
|
+
invokeStatus: "init"
|
|
780
|
+
},
|
|
781
|
+
transaction
|
|
782
|
+
}
|
|
783
|
+
);
|
|
784
|
+
if (!updated) {
|
|
785
|
+
return updated;
|
|
786
|
+
}
|
|
787
|
+
const message = await this.aiMessagesModel.findOne({
|
|
717
788
|
where: {
|
|
718
|
-
sessionId: this.sessionId,
|
|
719
789
|
messageId,
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
790
|
+
sessionId
|
|
791
|
+
},
|
|
792
|
+
transaction
|
|
793
|
+
});
|
|
794
|
+
if (!message) {
|
|
795
|
+
return updated;
|
|
723
796
|
}
|
|
724
|
-
|
|
725
|
-
|
|
797
|
+
await this.aiMessagesModel.update(
|
|
798
|
+
{
|
|
799
|
+
metadata: {
|
|
800
|
+
...message.get("metadata") ?? {},
|
|
801
|
+
interruptId
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
where: {
|
|
806
|
+
messageId,
|
|
807
|
+
sessionId
|
|
808
|
+
},
|
|
809
|
+
transaction
|
|
810
|
+
}
|
|
811
|
+
);
|
|
812
|
+
return updated;
|
|
813
|
+
});
|
|
726
814
|
}
|
|
727
815
|
async updateToolCallPending(messageId, toolCallId) {
|
|
728
816
|
const [updated] = await this.aiToolMessagesModel.update(
|
|
@@ -784,7 +872,6 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
784
872
|
var _a;
|
|
785
873
|
return (_a = await this.aiToolMessagesModel.findOne({
|
|
786
874
|
where: {
|
|
787
|
-
sessionId: this.sessionId,
|
|
788
875
|
messageId,
|
|
789
876
|
toolCallId
|
|
790
877
|
}
|
|
@@ -793,7 +880,6 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
793
880
|
async getToolCallResultMap(messageId, toolCallIds) {
|
|
794
881
|
const list = (await this.aiToolMessagesModel.findAll({
|
|
795
882
|
where: {
|
|
796
|
-
sessionId: this.sessionId,
|
|
797
883
|
messageId,
|
|
798
884
|
toolCallId: {
|
|
799
885
|
[import_database.Op.in]: toolCallIds
|
|
@@ -802,19 +888,6 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
802
888
|
})).map((it) => it.toJSON());
|
|
803
889
|
return new Map(list.map((it) => [it.toolCallId, it]));
|
|
804
890
|
}
|
|
805
|
-
async getUserDecisions(messageId) {
|
|
806
|
-
const allInterruptedToolCall = await this.aiToolMessagesModel.findAll({
|
|
807
|
-
where: {
|
|
808
|
-
messageId,
|
|
809
|
-
interruptActionOrder: { [import_database.Op.not]: null }
|
|
810
|
-
},
|
|
811
|
-
order: [["interruptActionOrder", "ASC"]]
|
|
812
|
-
});
|
|
813
|
-
if (!allInterruptedToolCall.every((t) => t.invokeStatus === "waiting")) {
|
|
814
|
-
return [];
|
|
815
|
-
}
|
|
816
|
-
return allInterruptedToolCall.map((item) => item.userDecision);
|
|
817
|
-
}
|
|
818
891
|
async cancelToolCall() {
|
|
819
892
|
var _a;
|
|
820
893
|
let messageId;
|
|
@@ -829,7 +902,6 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
829
902
|
}
|
|
830
903
|
const toolMessages = (await this.aiToolMessagesModel.findAll({
|
|
831
904
|
where: {
|
|
832
|
-
sessionId: this.sessionId,
|
|
833
905
|
messageId,
|
|
834
906
|
invokeStatus: {
|
|
835
907
|
[import_database.Op.ne]: "confirmed"
|
|
@@ -1068,10 +1140,20 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
1068
1140
|
const actionRequestsMap = new Map(actionRequests.map((x) => [x.name, x]));
|
|
1069
1141
|
const reviewConfigsMap = new Map(reviewConfigs.map((x) => [x.actionName, x]));
|
|
1070
1142
|
for (const [name, actionRequest] of actionRequestsMap.entries()) {
|
|
1143
|
+
const payload = actionRequest.description ? JSON.parse(actionRequest.description) : null;
|
|
1071
1144
|
result.set(name, {
|
|
1072
1145
|
order: order++,
|
|
1073
1146
|
description: actionRequest.description,
|
|
1074
|
-
allowedDecisions: (_a = reviewConfigsMap.get(name)) == null ? void 0 : _a.allowedDecisions
|
|
1147
|
+
allowedDecisions: (_a = reviewConfigsMap.get(name)) == null ? void 0 : _a.allowedDecisions,
|
|
1148
|
+
toolCall: {
|
|
1149
|
+
id: payload.toolCallId,
|
|
1150
|
+
name: payload.toolCallName
|
|
1151
|
+
},
|
|
1152
|
+
currentConversation: {
|
|
1153
|
+
sessionId: payload.sessionId,
|
|
1154
|
+
from: payload.from,
|
|
1155
|
+
username: payload.username
|
|
1156
|
+
}
|
|
1075
1157
|
});
|
|
1076
1158
|
}
|
|
1077
1159
|
return result;
|
|
@@ -1098,11 +1180,16 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
1098
1180
|
async getAvailableSkills() {
|
|
1099
1181
|
var _a, _b;
|
|
1100
1182
|
const { skillsManager } = this.plugin.ai;
|
|
1183
|
+
const aIEmployeeTools = await this.getAIEmployeeTools();
|
|
1184
|
+
const getSkill = aIEmployeeTools.find((it) => it.definition.name === "getSkill");
|
|
1185
|
+
if (!getSkill) {
|
|
1186
|
+
return [];
|
|
1187
|
+
}
|
|
1101
1188
|
const generalSkills = await skillsManager.listSkills({ scope: "GENERAL" });
|
|
1102
1189
|
const specifiedSkillNames = ((_a = this.employee.skillSettings) == null ? void 0 : _a.skills) ?? [];
|
|
1103
1190
|
const specifiedSkills = specifiedSkillNames.length ? await skillsManager.getSkills(specifiedSkillNames) : [];
|
|
1104
1191
|
const skillFilter = ((_b = this.skillSettings) == null ? void 0 : _b.skills) ?? [];
|
|
1105
|
-
return import_lodash.default.uniqBy([...
|
|
1192
|
+
return import_lodash.default.uniqBy([...specifiedSkills || [], ...generalSkills || []], "name").filter(
|
|
1106
1193
|
(it) => skillFilter.length === 0 || skillFilter.includes(it.name)
|
|
1107
1194
|
);
|
|
1108
1195
|
}
|
|
@@ -1167,6 +1254,12 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
1167
1254
|
}
|
|
1168
1255
|
return result;
|
|
1169
1256
|
}
|
|
1257
|
+
async getAvailableAIEmployees() {
|
|
1258
|
+
const availableAIEmployees = (await (0, import_shared.listAccessibleAIEmployees)(this.ctx)).map(
|
|
1259
|
+
(employee) => (0, import_shared.serializeEmployeeSummary)(this.ctx, employee)
|
|
1260
|
+
);
|
|
1261
|
+
return availableAIEmployees;
|
|
1262
|
+
}
|
|
1170
1263
|
getMiddleware(options) {
|
|
1171
1264
|
const { providerName, model, tools, baseToolNames, messageId, agentThread } = options;
|
|
1172
1265
|
return [
|
|
@@ -1206,6 +1299,19 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
1206
1299
|
listTools(filter) {
|
|
1207
1300
|
return this.toolsManager.listTools(filter);
|
|
1208
1301
|
}
|
|
1302
|
+
withRunMetadata(config) {
|
|
1303
|
+
return {
|
|
1304
|
+
...config,
|
|
1305
|
+
metadata: {
|
|
1306
|
+
...(config == null ? void 0 : config.metadata) ?? {},
|
|
1307
|
+
currentConversation: {
|
|
1308
|
+
sessionId: this.sessionId,
|
|
1309
|
+
from: this.from,
|
|
1310
|
+
username: this.employee.get("username")
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1209
1315
|
get toolsManager() {
|
|
1210
1316
|
return this.ctx.app.aiManager.toolsManager;
|
|
1211
1317
|
}
|
|
@@ -1250,8 +1356,8 @@ class AgentThread {
|
|
|
1250
1356
|
}
|
|
1251
1357
|
}
|
|
1252
1358
|
class ChatStreamProtocol {
|
|
1253
|
-
constructor(
|
|
1254
|
-
this.
|
|
1359
|
+
constructor(streamConsumer) {
|
|
1360
|
+
this.streamConsumer = streamConsumer;
|
|
1255
1361
|
}
|
|
1256
1362
|
_statistics = {
|
|
1257
1363
|
sent: 0,
|
|
@@ -1262,71 +1368,79 @@ class ChatStreamProtocol {
|
|
|
1262
1368
|
this._statistics.sent = 0;
|
|
1263
1369
|
}
|
|
1264
1370
|
};
|
|
1265
|
-
static
|
|
1266
|
-
return new ChatStreamProtocol(ctx);
|
|
1371
|
+
static fromContext(ctx) {
|
|
1372
|
+
return new ChatStreamProtocol(ctx.res);
|
|
1267
1373
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1374
|
+
with(conversation) {
|
|
1375
|
+
const write = ({ type, body }) => {
|
|
1376
|
+
const { sessionId, from, username } = conversation;
|
|
1377
|
+
const data = `data: ${JSON.stringify({ sessionId, from, username, type, body })}
|
|
1378
|
+
|
|
1379
|
+
`;
|
|
1380
|
+
this.streamConsumer.write(data);
|
|
1381
|
+
this._statistics.addSent(data.length);
|
|
1382
|
+
};
|
|
1383
|
+
return {
|
|
1384
|
+
startStream: () => {
|
|
1385
|
+
this._statistics.reset();
|
|
1386
|
+
write({ type: "stream_start" });
|
|
1387
|
+
},
|
|
1388
|
+
endStream: () => {
|
|
1389
|
+
write({ type: "stream_end" });
|
|
1390
|
+
},
|
|
1391
|
+
subAgentCompleted: () => {
|
|
1392
|
+
write({ type: "sub_agent_completed" });
|
|
1393
|
+
},
|
|
1394
|
+
newMessage: (content) => {
|
|
1395
|
+
write({ type: "new_message", body: content });
|
|
1396
|
+
},
|
|
1397
|
+
content: (content) => {
|
|
1398
|
+
write({ type: "content", body: content });
|
|
1399
|
+
},
|
|
1400
|
+
webSearch: (content) => {
|
|
1401
|
+
write({ type: "web_search", body: content });
|
|
1402
|
+
},
|
|
1403
|
+
reasoning: (content) => {
|
|
1404
|
+
write({ type: "reasoning", body: content });
|
|
1405
|
+
},
|
|
1406
|
+
stopReasoning: () => {
|
|
1407
|
+
write({
|
|
1408
|
+
type: "reasoning",
|
|
1409
|
+
body: {
|
|
1410
|
+
status: "stop",
|
|
1411
|
+
content: ""
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
},
|
|
1415
|
+
toolCallChunks: (content) => {
|
|
1416
|
+
write({ type: "tool_call_chunks", body: content });
|
|
1417
|
+
},
|
|
1418
|
+
toolCalls: (content) => {
|
|
1419
|
+
write({ type: "tool_calls", body: content });
|
|
1420
|
+
},
|
|
1421
|
+
toolCallStatus: ({
|
|
1311
1422
|
toolCall,
|
|
1312
1423
|
invokeStatus,
|
|
1313
1424
|
status,
|
|
1314
1425
|
interruptAction
|
|
1426
|
+
}) => {
|
|
1427
|
+
write({
|
|
1428
|
+
type: "tool_call_status",
|
|
1429
|
+
body: {
|
|
1430
|
+
toolCall,
|
|
1431
|
+
invokeStatus,
|
|
1432
|
+
status,
|
|
1433
|
+
interruptAction
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1315
1436
|
}
|
|
1316
|
-
}
|
|
1437
|
+
};
|
|
1317
1438
|
}
|
|
1318
1439
|
get statistics() {
|
|
1319
1440
|
return {
|
|
1320
1441
|
sent: this._statistics.sent
|
|
1321
1442
|
};
|
|
1322
1443
|
}
|
|
1323
|
-
write({ type, body }) {
|
|
1324
|
-
const data = `data: ${JSON.stringify({ type, body })}
|
|
1325
|
-
|
|
1326
|
-
`;
|
|
1327
|
-
this.ctx.res.write(data);
|
|
1328
|
-
this._statistics.addSent(data.length);
|
|
1329
|
-
}
|
|
1330
1444
|
}
|
|
1331
1445
|
class ResponseMetadataCollector extends import_base.BaseCallbackHandler {
|
|
1332
1446
|
constructor(llmProvider, responseMetadata) {
|
|
@@ -1347,5 +1461,6 @@ class ResponseMetadataCollector extends import_base.BaseCallbackHandler {
|
|
|
1347
1461
|
}
|
|
1348
1462
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1349
1463
|
0 && (module.exports = {
|
|
1350
|
-
AIEmployee
|
|
1464
|
+
AIEmployee,
|
|
1465
|
+
ChatStreamProtocol
|
|
1351
1466
|
});
|