@nocobase/plugin-ai 2.1.0-beta.29 → 2.1.0-beta.30
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/docs/nocobase/api/cli/api/dynamic.md +7 -0
- package/dist/ai/docs/nocobase/api/cli/api/resource/index.md +3 -0
- package/dist/ai/docs/nocobase/api/cli/app/down.md +7 -3
- package/dist/ai/docs/nocobase/api/cli/app/index.md +1 -1
- package/dist/ai/docs/nocobase/api/cli/app/logs.md +3 -0
- package/dist/ai/docs/nocobase/api/cli/app/restart.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/app/start.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/app/stop.md +3 -0
- package/dist/ai/docs/nocobase/api/cli/app/upgrade.md +5 -0
- package/dist/ai/docs/nocobase/api/cli/env/add.md +11 -3
- package/dist/ai/docs/nocobase/api/cli/env/auth.md +1 -1
- package/dist/ai/docs/nocobase/api/cli/env/current.md +29 -0
- package/dist/ai/docs/nocobase/api/cli/env/index.md +22 -4
- package/dist/ai/docs/nocobase/api/cli/env/info.md +1 -5
- package/dist/ai/docs/nocobase/api/cli/env/list.md +11 -6
- package/dist/ai/docs/nocobase/api/cli/env/remove.md +4 -1
- package/dist/ai/docs/nocobase/api/cli/env/status.md +52 -0
- package/dist/ai/docs/nocobase/api/cli/env/update.md +1 -1
- package/dist/ai/docs/nocobase/api/cli/env/use.md +11 -1
- package/dist/ai/docs/nocobase/api/cli/index.md +13 -1
- package/dist/ai/docs/nocobase/api/cli/license/activate.md +4 -1
- package/dist/ai/docs/nocobase/api/cli/license/id.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/license/plugins/clean.md +5 -1
- package/dist/ai/docs/nocobase/api/cli/license/plugins/list.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/license/plugins/sync.md +5 -1
- package/dist/ai/docs/nocobase/api/cli/license/status.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/plugin/disable.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/plugin/enable.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/plugin/list.md +4 -0
- package/dist/ai/docs/nocobase/api/cli/session/id.md +28 -0
- package/dist/ai/docs/nocobase/api/cli/session/index.md +41 -0
- package/dist/ai/docs/nocobase/api/cli/session/remove.md +35 -0
- package/dist/ai/docs/nocobase/api/cli/session/setup.md +47 -0
- package/dist/client/119.c6bf8c6433167d81.js +10 -0
- package/dist/client/228.b4b709f93b86b6b9.js +10 -0
- package/dist/client/{486.afbed6b132b3c0dd.js → 486.dcac8f3fcec19c33.js} +1 -1
- package/dist/client/597.b0d64948d74cf6cb.js +10 -0
- package/dist/client/646.5860101cb28c8272.js +10 -0
- package/dist/client/711.92cd94681fde7e05.js +10 -0
- package/dist/client/768.5177bff46ae71a5b.js +10 -0
- package/dist/client/792.abb57765453bcbcc.js +10 -0
- package/dist/client/820.f72ef2462b61d812.js +10 -0
- package/dist/client/927.ac9ee9a8c1cb4f1d.js +10 -0
- package/dist/client/ai-employees/chatbox/conversations/ConversationsList.d.ts +1 -15
- package/dist/client/ai-employees/chatbox/conversations/WorkflowTasksList.d.ts +1 -21
- package/dist/client/ai-employees/chatbox/hooks/useChat.d.ts +125 -0
- package/dist/client/ai-employees/chatbox/hooks/useChatBoxActions.d.ts +1 -1
- package/dist/client/ai-employees/chatbox/hooks/useChatConversationActions.d.ts +13 -1
- package/dist/client/ai-employees/chatbox/hooks/useChatMessageActions.d.ts +8 -8
- package/dist/client/ai-employees/chatbox/stores/chat-conversations.d.ts +4 -0
- package/dist/client/ai-employees/chatbox/stores/chat-messages.d.ts +77 -50
- package/dist/client/ai-employees/chatbox/stores/chat-tool-call.d.ts +24 -16
- package/dist/client/ai-employees/types.d.ts +1 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +4 -4
- package/dist/externalVersion.js +16 -15
- package/dist/locale/en-US.json +1 -0
- package/dist/locale/zh-CN.json +1 -0
- package/dist/node_modules/@langchain/xai/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/jsonrepair/package.json +1 -1
- package/dist/node_modules/just-bash/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 +3 -1
- package/dist/server/ai-employees/ai-conversations.js +40 -3
- package/dist/server/ai-employees/ai-employee.d.ts +16 -14
- package/dist/server/ai-employees/ai-employee.js +65 -43
- package/dist/server/ai-employees/middleware/conversation.js +11 -9
- package/dist/server/collections/ai-conversations.js +6 -0
- package/dist/server/manager/llm-stream-manager.d.ts +37 -0
- package/dist/server/manager/llm-stream-manager.js +142 -0
- package/dist/server/plugin.d.ts +2 -0
- package/dist/server/plugin.js +3 -0
- package/dist/server/resource/aiConversations.d.ts +8 -0
- package/dist/server/resource/aiConversations.js +129 -2
- package/package.json +2 -2
- package/dist/client/119.78774f3ad953af49.js +0 -10
- package/dist/client/228.a3df2921c8beb766.js +0 -10
- package/dist/client/597.aa363881a325b5c0.js +0 -10
- package/dist/client/646.217a40387efbd163.js +0 -10
- package/dist/client/711.266b8f1c520d467a.js +0 -10
- package/dist/client/768.973ce32e15099a48.js +0 -10
- package/dist/client/792.2e48eab4767d662a.js +0 -10
- package/dist/client/820.6a26239ea96c075a.js +0 -10
- package/dist/client/927.ff5cd05b14901ae6.js +0 -10
|
@@ -70,6 +70,7 @@ class AIEmployee {
|
|
|
70
70
|
legacy;
|
|
71
71
|
tools;
|
|
72
72
|
inWorkflow;
|
|
73
|
+
streamCached;
|
|
73
74
|
constructor({
|
|
74
75
|
ctx,
|
|
75
76
|
employee,
|
|
@@ -94,10 +95,17 @@ class AIEmployee {
|
|
|
94
95
|
this.legacy = legacy;
|
|
95
96
|
this.from = from;
|
|
96
97
|
this.tools = tools;
|
|
98
|
+
this.streamCached = this.plugin.llmStreamCachedManager.getCached(sessionId);
|
|
97
99
|
const builtInManager = this.plugin.builtInManager;
|
|
98
100
|
builtInManager.setupBuiltInInfo(ctx, this.employee);
|
|
99
101
|
this.webSearch = webSearch;
|
|
100
|
-
this.protocol = ChatStreamProtocol.fromContext(ctx)
|
|
102
|
+
this.protocol = ChatStreamProtocol.fromContext(ctx, async (chunk) => {
|
|
103
|
+
try {
|
|
104
|
+
await this.streamCached.append(chunk);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
this.logger.warn("Failed to append LLM stream cache", { sessionId: this.sessionId, error });
|
|
107
|
+
}
|
|
108
|
+
});
|
|
101
109
|
}
|
|
102
110
|
async getFormatMessages(userMessages) {
|
|
103
111
|
const { provider } = await this.plugin.aiManager.getLLMService({
|
|
@@ -194,6 +202,7 @@ class AIEmployee {
|
|
|
194
202
|
userMessages = [],
|
|
195
203
|
userDecisions
|
|
196
204
|
}) {
|
|
205
|
+
await this.streamCached.clear();
|
|
197
206
|
await this.aiConversationsRepo.update({
|
|
198
207
|
values: { llmActiveState: "streaming" },
|
|
199
208
|
filter: {
|
|
@@ -228,11 +237,12 @@ class AIEmployee {
|
|
|
228
237
|
return false;
|
|
229
238
|
} finally {
|
|
230
239
|
await this.aiConversationsRepo.update({
|
|
231
|
-
values: { llmActiveState: "idle" },
|
|
240
|
+
values: { llmActiveState: "idle", read: false },
|
|
232
241
|
filter: {
|
|
233
242
|
sessionId: this.sessionId
|
|
234
243
|
}
|
|
235
244
|
});
|
|
245
|
+
await this.streamCached.clear();
|
|
236
246
|
}
|
|
237
247
|
}
|
|
238
248
|
async invoke({
|
|
@@ -386,6 +396,14 @@ class AIEmployee {
|
|
|
386
396
|
}
|
|
387
397
|
} catch (e) {
|
|
388
398
|
this.logger.error("Fail to save message after conversation abort", gathered);
|
|
399
|
+
} finally {
|
|
400
|
+
await this.aiConversationsRepo.update({
|
|
401
|
+
values: { llmActiveState: "idle", read: true },
|
|
402
|
+
filter: {
|
|
403
|
+
sessionId: this.sessionId
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
await this.streamCached.clear();
|
|
389
407
|
}
|
|
390
408
|
});
|
|
391
409
|
try {
|
|
@@ -394,7 +412,7 @@ class AIEmployee {
|
|
|
394
412
|
from: this.from,
|
|
395
413
|
username: this.employee.username
|
|
396
414
|
};
|
|
397
|
-
this.protocol.with(aiEmployeeConversation).startStream();
|
|
415
|
+
await this.protocol.with(aiEmployeeConversation).startStream();
|
|
398
416
|
for await (const [mode, chunks] of stream) {
|
|
399
417
|
if (mode === "messages") {
|
|
400
418
|
const [chunk, metadata] = chunks;
|
|
@@ -404,24 +422,24 @@ class AIEmployee {
|
|
|
404
422
|
if (chunk.content) {
|
|
405
423
|
if (isReasoning) {
|
|
406
424
|
isReasoning = false;
|
|
407
|
-
this.protocol.with(currentConversation).stopReasoning();
|
|
425
|
+
await this.protocol.with(currentConversation).stopReasoning();
|
|
408
426
|
}
|
|
409
427
|
const parsedContent = provider.parseResponseChunk(chunk.content);
|
|
410
428
|
if (parsedContent) {
|
|
411
|
-
this.protocol.with(currentConversation).content(parsedContent);
|
|
429
|
+
await this.protocol.with(currentConversation).content(parsedContent);
|
|
412
430
|
}
|
|
413
431
|
}
|
|
414
432
|
if ((_a = chunk.tool_call_chunks) == null ? void 0 : _a.length) {
|
|
415
|
-
this.protocol.with(currentConversation).toolCallChunks(chunk.tool_call_chunks);
|
|
433
|
+
await this.protocol.with(currentConversation).toolCallChunks(chunk.tool_call_chunks);
|
|
416
434
|
}
|
|
417
435
|
const webSearch = provider.parseWebSearchAction(chunk);
|
|
418
436
|
if (webSearch == null ? void 0 : webSearch.length) {
|
|
419
|
-
this.protocol.with(currentConversation).webSearch(webSearch);
|
|
437
|
+
await this.protocol.with(currentConversation).webSearch(webSearch);
|
|
420
438
|
}
|
|
421
439
|
const reasoningContent = provider.parseReasoningContent(chunk);
|
|
422
440
|
if (reasoningContent) {
|
|
423
441
|
isReasoning = true;
|
|
424
|
-
this.protocol.with(currentConversation).reasoning(reasoningContent);
|
|
442
|
+
await this.protocol.with(currentConversation).reasoning(reasoningContent);
|
|
425
443
|
}
|
|
426
444
|
}
|
|
427
445
|
} else if (mode === "updates") {
|
|
@@ -431,8 +449,8 @@ class AIEmployee {
|
|
|
431
449
|
await this.handleInterruptedToolCalls(
|
|
432
450
|
interrupt,
|
|
433
451
|
(sessionId) => aiMessageIdMap.get(sessionId),
|
|
434
|
-
({ messageId, interruptAction, toolCall, currentConversation }) => {
|
|
435
|
-
this.protocol.with(currentConversation).toolCallStatus({
|
|
452
|
+
async ({ messageId, interruptAction, toolCall, currentConversation }) => {
|
|
453
|
+
await this.protocol.with(currentConversation).toolCallStatus({
|
|
436
454
|
toolCall: {
|
|
437
455
|
messageId,
|
|
438
456
|
id: toolCall.id,
|
|
@@ -448,6 +466,7 @@ class AIEmployee {
|
|
|
448
466
|
} else if (mode === "custom") {
|
|
449
467
|
const { currentConversation } = chunks;
|
|
450
468
|
if (chunks.action === "AfterAIMessageSaved") {
|
|
469
|
+
await this.streamCached.skipped();
|
|
451
470
|
aiMessageIdMap.set(currentConversation.sessionId, chunks.body.messageId);
|
|
452
471
|
const data = responseMetadata.get(chunks.body.id);
|
|
453
472
|
if (data) {
|
|
@@ -476,11 +495,11 @@ class AIEmployee {
|
|
|
476
495
|
}
|
|
477
496
|
}
|
|
478
497
|
} else if (chunks.action === "initToolCalls") {
|
|
479
|
-
this.protocol.with(currentConversation).toolCalls(chunks.body);
|
|
498
|
+
await this.protocol.with(currentConversation).toolCalls(chunks.body);
|
|
480
499
|
} else if (chunks.action === "beforeToolCall") {
|
|
481
500
|
const toolsMap = await this.getToolsMap();
|
|
482
501
|
const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_d = (_c = chunks.body) == null ? void 0 : _c.toolCall) == null ? void 0 : _d.name));
|
|
483
|
-
this.protocol.with(currentConversation).toolCallStatus({
|
|
502
|
+
await this.protocol.with(currentConversation).toolCallStatus({
|
|
484
503
|
toolCall: {
|
|
485
504
|
messageId: (_f = (_e = chunks.body) == null ? void 0 : _e.toolCall) == null ? void 0 : _f.messageId,
|
|
486
505
|
id: (_h = (_g = chunks.body) == null ? void 0 : _g.toolCall) == null ? void 0 : _h.id,
|
|
@@ -492,7 +511,7 @@ class AIEmployee {
|
|
|
492
511
|
} else if (chunks.action === "afterToolCall") {
|
|
493
512
|
const toolsMap = await this.getToolsMap();
|
|
494
513
|
const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_l = (_k = chunks.body) == null ? void 0 : _k.toolCall) == null ? void 0 : _l.name));
|
|
495
|
-
this.protocol.with(currentConversation).toolCallStatus({
|
|
514
|
+
await this.protocol.with(currentConversation).toolCallStatus({
|
|
496
515
|
toolCall: {
|
|
497
516
|
messageId: (_n = (_m = chunks.body) == null ? void 0 : _m.toolCall) == null ? void 0 : _n.messageId,
|
|
498
517
|
id: (_p = (_o = chunks.body) == null ? void 0 : _o.toolCall) == null ? void 0 : _p.id,
|
|
@@ -516,7 +535,7 @@ class AIEmployee {
|
|
|
516
535
|
for (const { metadata } of messages) {
|
|
517
536
|
const tools = toolsMap.get(metadata.toolName);
|
|
518
537
|
const toolCallResult = toolCallResultMap.get(metadata.toolCallId);
|
|
519
|
-
this.protocol.with(currentConversation).toolCallStatus({
|
|
538
|
+
await this.protocol.with(currentConversation).toolCallStatus({
|
|
520
539
|
toolCall: {
|
|
521
540
|
messageId,
|
|
522
541
|
id: metadata.toolCallId,
|
|
@@ -531,9 +550,9 @@ class AIEmployee {
|
|
|
531
550
|
});
|
|
532
551
|
}
|
|
533
552
|
}
|
|
534
|
-
this.protocol.with(currentConversation).newMessage();
|
|
553
|
+
await this.protocol.with(currentConversation).newMessage();
|
|
535
554
|
} else if (chunks.action === "afterSubAgentInvoke") {
|
|
536
|
-
this.protocol.with(currentConversation).subAgentCompleted();
|
|
555
|
+
await this.protocol.with(currentConversation).subAgentCompleted();
|
|
537
556
|
}
|
|
538
557
|
}
|
|
539
558
|
}
|
|
@@ -541,7 +560,7 @@ class AIEmployee {
|
|
|
541
560
|
this.sendErrorResponse("Empty message");
|
|
542
561
|
return;
|
|
543
562
|
}
|
|
544
|
-
this.protocol.with(aiEmployeeConversation).endStream();
|
|
563
|
+
await this.protocol.with(aiEmployeeConversation).endStream();
|
|
545
564
|
} catch (err) {
|
|
546
565
|
this.ctx.log.error(err);
|
|
547
566
|
if (err.name === "GraphRecursionError") {
|
|
@@ -1393,8 +1412,9 @@ class AgentThread {
|
|
|
1393
1412
|
}
|
|
1394
1413
|
}
|
|
1395
1414
|
class ChatStreamProtocol {
|
|
1396
|
-
constructor(streamConsumer) {
|
|
1415
|
+
constructor(streamConsumer, onWrite) {
|
|
1397
1416
|
this.streamConsumer = streamConsumer;
|
|
1417
|
+
this.onWrite = onWrite;
|
|
1398
1418
|
}
|
|
1399
1419
|
_statistics = {
|
|
1400
1420
|
sent: 0,
|
|
@@ -1405,43 +1425,45 @@ class ChatStreamProtocol {
|
|
|
1405
1425
|
this._statistics.sent = 0;
|
|
1406
1426
|
}
|
|
1407
1427
|
};
|
|
1408
|
-
static fromContext(ctx) {
|
|
1409
|
-
return new ChatStreamProtocol(ctx.res);
|
|
1428
|
+
static fromContext(ctx, onWrite) {
|
|
1429
|
+
return new ChatStreamProtocol(ctx.res, onWrite);
|
|
1410
1430
|
}
|
|
1411
1431
|
with(conversation) {
|
|
1412
|
-
const write = ({ type, body }) => {
|
|
1432
|
+
const write = async ({ type, body }) => {
|
|
1433
|
+
var _a;
|
|
1413
1434
|
const { sessionId, from, username } = conversation;
|
|
1414
1435
|
const data = `data: ${JSON.stringify({ sessionId, from, username, type, body })}
|
|
1415
1436
|
|
|
1416
1437
|
`;
|
|
1438
|
+
await ((_a = this.onWrite) == null ? void 0 : _a.call(this, data));
|
|
1417
1439
|
this.streamConsumer.write(data);
|
|
1418
1440
|
this._statistics.addSent(data.length);
|
|
1419
1441
|
};
|
|
1420
1442
|
return {
|
|
1421
|
-
startStream: () => {
|
|
1443
|
+
startStream: async () => {
|
|
1422
1444
|
this._statistics.reset();
|
|
1423
|
-
write({ type: "stream_start" });
|
|
1445
|
+
await write({ type: "stream_start" });
|
|
1424
1446
|
},
|
|
1425
|
-
endStream: () => {
|
|
1426
|
-
write({ type: "stream_end" });
|
|
1447
|
+
endStream: async () => {
|
|
1448
|
+
await write({ type: "stream_end" });
|
|
1427
1449
|
},
|
|
1428
|
-
subAgentCompleted: () => {
|
|
1429
|
-
write({ type: "sub_agent_completed" });
|
|
1450
|
+
subAgentCompleted: async () => {
|
|
1451
|
+
await write({ type: "sub_agent_completed" });
|
|
1430
1452
|
},
|
|
1431
|
-
newMessage: (content) => {
|
|
1432
|
-
write({ type: "new_message", body: content });
|
|
1453
|
+
newMessage: async (content) => {
|
|
1454
|
+
await write({ type: "new_message", body: content });
|
|
1433
1455
|
},
|
|
1434
|
-
content: (content) => {
|
|
1435
|
-
write({ type: "content", body: content });
|
|
1456
|
+
content: async (content) => {
|
|
1457
|
+
await write({ type: "content", body: content });
|
|
1436
1458
|
},
|
|
1437
|
-
webSearch: (content) => {
|
|
1438
|
-
write({ type: "web_search", body: content });
|
|
1459
|
+
webSearch: async (content) => {
|
|
1460
|
+
await write({ type: "web_search", body: content });
|
|
1439
1461
|
},
|
|
1440
|
-
reasoning: (content) => {
|
|
1441
|
-
write({ type: "reasoning", body: content });
|
|
1462
|
+
reasoning: async (content) => {
|
|
1463
|
+
await write({ type: "reasoning", body: content });
|
|
1442
1464
|
},
|
|
1443
|
-
stopReasoning: () => {
|
|
1444
|
-
write({
|
|
1465
|
+
stopReasoning: async () => {
|
|
1466
|
+
await write({
|
|
1445
1467
|
type: "reasoning",
|
|
1446
1468
|
body: {
|
|
1447
1469
|
status: "stop",
|
|
@@ -1449,13 +1471,13 @@ class ChatStreamProtocol {
|
|
|
1449
1471
|
}
|
|
1450
1472
|
});
|
|
1451
1473
|
},
|
|
1452
|
-
toolCallChunks: (content) => {
|
|
1453
|
-
write({ type: "tool_call_chunks", body: content });
|
|
1474
|
+
toolCallChunks: async (content) => {
|
|
1475
|
+
await write({ type: "tool_call_chunks", body: content });
|
|
1454
1476
|
},
|
|
1455
|
-
toolCalls: (content) => {
|
|
1456
|
-
write({ type: "tool_calls", body: content });
|
|
1477
|
+
toolCalls: async (content) => {
|
|
1478
|
+
await write({ type: "tool_calls", body: content });
|
|
1457
1479
|
},
|
|
1458
|
-
toolCallStatus: ({
|
|
1480
|
+
toolCallStatus: async ({
|
|
1459
1481
|
toolCall,
|
|
1460
1482
|
invokeStatus,
|
|
1461
1483
|
status,
|
|
@@ -1464,7 +1486,7 @@ class ChatStreamProtocol {
|
|
|
1464
1486
|
content,
|
|
1465
1487
|
interruptAction
|
|
1466
1488
|
}) => {
|
|
1467
|
-
write({
|
|
1489
|
+
await write({
|
|
1468
1490
|
type: "tool_call_status",
|
|
1469
1491
|
body: {
|
|
1470
1492
|
toolCall,
|
|
@@ -109,6 +109,9 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
111
|
},
|
|
112
|
+
afterAgent: async () => {
|
|
113
|
+
aiEmployee.removeAbortController();
|
|
114
|
+
},
|
|
112
115
|
beforeModel: async (state, runtime) => {
|
|
113
116
|
var _a;
|
|
114
117
|
const { messageId: messageId2 } = state;
|
|
@@ -159,7 +162,6 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
159
162
|
if ((lastMessage == null ? void 0 : lastMessage.type) !== "ai") {
|
|
160
163
|
return newState;
|
|
161
164
|
}
|
|
162
|
-
aiEmployee.removeAbortController();
|
|
163
165
|
if ((_a = runtime.signal) == null ? void 0 : _a.aborted) {
|
|
164
166
|
return newState;
|
|
165
167
|
}
|
|
@@ -180,19 +182,19 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
180
182
|
fillToolCall(result, toolsMap, initializedToolCalls, toolCalls);
|
|
181
183
|
}
|
|
182
184
|
});
|
|
183
|
-
(
|
|
185
|
+
if (toolCalls == null ? void 0 : toolCalls.length) {
|
|
186
|
+
(_b = runtime.writer) == null ? void 0 : _b.call(runtime, {
|
|
187
|
+
action: "initToolCalls",
|
|
188
|
+
body: { toolCalls },
|
|
189
|
+
currentConversation
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
(_c = runtime.writer) == null ? void 0 : _c.call(runtime, {
|
|
184
193
|
action: "AfterAIMessageSaved",
|
|
185
194
|
body: { id: aiMessage.id, messageId: newState.messageId },
|
|
186
195
|
currentConversation
|
|
187
196
|
});
|
|
188
197
|
}
|
|
189
|
-
if (toolCalls == null ? void 0 : toolCalls.length) {
|
|
190
|
-
(_c = runtime.writer) == null ? void 0 : _c.call(runtime, {
|
|
191
|
-
action: "initToolCalls",
|
|
192
|
-
body: { toolCalls },
|
|
193
|
-
currentConversation
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
198
|
return newState;
|
|
197
199
|
} catch (e) {
|
|
198
200
|
(_f = (_e = (_d = runtime.context) == null ? void 0 : _d.ctx) == null ? void 0 : _e.logger) == null ? void 0 : _f.error(e);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import PluginAIServer from '../plugin';
|
|
10
|
+
export declare class LLMStreamCachedManager {
|
|
11
|
+
private readonly plugin;
|
|
12
|
+
private cachePromise?;
|
|
13
|
+
constructor(plugin: PluginAIServer);
|
|
14
|
+
getCached(sessionId: string): LLMStreamCached;
|
|
15
|
+
clear(sessionId: string): Promise<void>;
|
|
16
|
+
append(sessionId: string, chunk: string): Promise<void>;
|
|
17
|
+
stream(sessionId: string, options?: {
|
|
18
|
+
pollInterval?: number;
|
|
19
|
+
initialWaitTimeout?: number;
|
|
20
|
+
}): AsyncGenerator<string, void, void>;
|
|
21
|
+
private getChunks;
|
|
22
|
+
private getCache;
|
|
23
|
+
private withLock;
|
|
24
|
+
private getLockKey;
|
|
25
|
+
}
|
|
26
|
+
export declare class LLMStreamCached {
|
|
27
|
+
private readonly sessionId;
|
|
28
|
+
private readonly manager;
|
|
29
|
+
constructor(sessionId: string, manager: LLMStreamCachedManager);
|
|
30
|
+
clear(): Promise<void>;
|
|
31
|
+
append(chunk: string): Promise<void>;
|
|
32
|
+
skipped(): Promise<void>;
|
|
33
|
+
stream(options?: {
|
|
34
|
+
pollInterval?: number;
|
|
35
|
+
initialWaitTimeout?: number;
|
|
36
|
+
}): AsyncGenerator<string, void, void>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var llm_stream_manager_exports = {};
|
|
28
|
+
__export(llm_stream_manager_exports, {
|
|
29
|
+
LLMStreamCached: () => LLMStreamCached,
|
|
30
|
+
LLMStreamCachedManager: () => LLMStreamCachedManager
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(llm_stream_manager_exports);
|
|
33
|
+
var import_utils = require("@nocobase/utils");
|
|
34
|
+
const CACHE_NAME = "ai-llm-stream-cache";
|
|
35
|
+
const LOCK_KEY_PREFIX = "ai-llm-stream-lock";
|
|
36
|
+
const WRITE_LOCK_TTL = 3e3;
|
|
37
|
+
const CACHE_TTL = 10 * 60 * 1e3;
|
|
38
|
+
const STREAM_END_MARK = '"type":"stream_end"';
|
|
39
|
+
const SKIPPED_MARK = "__skipped__";
|
|
40
|
+
const DEFAULT_POLL_INTERVAL = 50;
|
|
41
|
+
const DEFAULT_INITIAL_WAIT_TIMEOUT = 1e3;
|
|
42
|
+
class LLMStreamCachedManager {
|
|
43
|
+
constructor(plugin) {
|
|
44
|
+
this.plugin = plugin;
|
|
45
|
+
}
|
|
46
|
+
cachePromise;
|
|
47
|
+
getCached(sessionId) {
|
|
48
|
+
return new LLMStreamCached(sessionId, this);
|
|
49
|
+
}
|
|
50
|
+
async clear(sessionId) {
|
|
51
|
+
await this.withLock(sessionId, async () => {
|
|
52
|
+
const cache = await this.getCache();
|
|
53
|
+
await cache.del(sessionId);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async append(sessionId, chunk) {
|
|
57
|
+
await this.withLock(sessionId, async () => {
|
|
58
|
+
const cache = await this.getCache();
|
|
59
|
+
const chunks = await cache.get(sessionId) ?? [];
|
|
60
|
+
chunks.push(chunk);
|
|
61
|
+
await cache.set(sessionId, chunks, CACHE_TTL);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async *stream(sessionId, options) {
|
|
65
|
+
const pollInterval = (options == null ? void 0 : options.pollInterval) ?? DEFAULT_POLL_INTERVAL;
|
|
66
|
+
const initialWaitTimeout = (options == null ? void 0 : options.initialWaitTimeout) ?? DEFAULT_INITIAL_WAIT_TIMEOUT;
|
|
67
|
+
let offset = 0;
|
|
68
|
+
let waited = 0;
|
|
69
|
+
let completed = false;
|
|
70
|
+
while (!completed) {
|
|
71
|
+
const chunks = await this.getChunks(sessionId);
|
|
72
|
+
const lastSkippedIndex = chunks.lastIndexOf(SKIPPED_MARK);
|
|
73
|
+
if (lastSkippedIndex >= offset) {
|
|
74
|
+
offset = lastSkippedIndex + 1;
|
|
75
|
+
}
|
|
76
|
+
while (offset < chunks.length) {
|
|
77
|
+
const chunk = chunks[offset++];
|
|
78
|
+
yield chunk;
|
|
79
|
+
waited = 0;
|
|
80
|
+
if (chunk.includes(STREAM_END_MARK)) {
|
|
81
|
+
completed = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (completed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!chunks.length) {
|
|
89
|
+
if (offset > 0) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (waited >= initialWaitTimeout) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
waited += pollInterval;
|
|
96
|
+
}
|
|
97
|
+
await (0, import_utils.sleep)(pollInterval);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async getChunks(sessionId) {
|
|
101
|
+
const cache = await this.getCache();
|
|
102
|
+
return await cache.get(sessionId) ?? [];
|
|
103
|
+
}
|
|
104
|
+
async getCache() {
|
|
105
|
+
this.cachePromise ??= this.plugin.app.cacheManager.createCache({
|
|
106
|
+
name: CACHE_NAME,
|
|
107
|
+
store: this.plugin.app.cacheManager.defaultStore
|
|
108
|
+
});
|
|
109
|
+
return this.cachePromise;
|
|
110
|
+
}
|
|
111
|
+
async withLock(sessionId, fn) {
|
|
112
|
+
return await this.plugin.app.lockManager.runExclusive(this.getLockKey(sessionId), fn, WRITE_LOCK_TTL);
|
|
113
|
+
}
|
|
114
|
+
getLockKey(sessionId) {
|
|
115
|
+
return `${LOCK_KEY_PREFIX}:${sessionId}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
class LLMStreamCached {
|
|
119
|
+
constructor(sessionId, manager) {
|
|
120
|
+
this.sessionId = sessionId;
|
|
121
|
+
this.manager = manager;
|
|
122
|
+
}
|
|
123
|
+
async clear() {
|
|
124
|
+
await this.manager.clear(this.sessionId);
|
|
125
|
+
}
|
|
126
|
+
async append(chunk) {
|
|
127
|
+
await this.manager.append(this.sessionId, chunk);
|
|
128
|
+
}
|
|
129
|
+
async skipped() {
|
|
130
|
+
await this.append(SKIPPED_MARK);
|
|
131
|
+
}
|
|
132
|
+
async *stream(options) {
|
|
133
|
+
for await (const chunk of this.manager.stream(this.sessionId, options)) {
|
|
134
|
+
yield chunk;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
139
|
+
0 && (module.exports = {
|
|
140
|
+
LLMStreamCached,
|
|
141
|
+
LLMStreamCachedManager
|
|
142
|
+
});
|
package/dist/server/plugin.d.ts
CHANGED
|
@@ -20,11 +20,13 @@ import { DocumentLoaders } from './document-loader';
|
|
|
20
20
|
import type PluginFileManagerServer from '@nocobase/plugin-file-manager';
|
|
21
21
|
import { SubAgentsDispatcher } from './ai-employees/sub-agents';
|
|
22
22
|
import { KnowledgeBaseManager } from './ai-employees/ai-knowledge-base';
|
|
23
|
+
import { LLMStreamCachedManager } from './manager/llm-stream-manager';
|
|
23
24
|
export declare class PluginAIServer extends Plugin {
|
|
24
25
|
features: AIPluginFeatureManagerImpl;
|
|
25
26
|
aiManager: AIManager;
|
|
26
27
|
aiEmployeesManager: AIEmployeesManager;
|
|
27
28
|
aiConversationsManager: AIConversationsManager;
|
|
29
|
+
llmStreamCachedManager: LLMStreamCachedManager;
|
|
28
30
|
builtInManager: BuiltInManager;
|
|
29
31
|
aiContextDatasourceManager: AIContextDatasourceManager;
|
|
30
32
|
aiCodingManager: AICodingManager;
|
package/dist/server/plugin.js
CHANGED
|
@@ -77,11 +77,13 @@ var import_mimo = require("./llm-providers/mimo");
|
|
|
77
77
|
var import_sub_agents = require("./ai-employees/sub-agents");
|
|
78
78
|
var import_employee = require("./workflow/nodes/employee");
|
|
79
79
|
var import_ai_knowledge_base = require("./ai-employees/ai-knowledge-base");
|
|
80
|
+
var import_llm_stream_manager = require("./manager/llm-stream-manager");
|
|
80
81
|
class PluginAIServer extends import_server.Plugin {
|
|
81
82
|
features = new import_ai_feature_manager.AIPluginFeatureManagerImpl();
|
|
82
83
|
aiManager = new import_ai_manager.AIManager(this);
|
|
83
84
|
aiEmployeesManager = new import_ai_employees_manager.AIEmployeesManager(this);
|
|
84
85
|
aiConversationsManager = new import_ai_conversations.AIConversationsManager(this);
|
|
86
|
+
llmStreamCachedManager = new import_llm_stream_manager.LLMStreamCachedManager(this);
|
|
85
87
|
builtInManager = new import_built_in_manager.BuiltInManager(this);
|
|
86
88
|
aiContextDatasourceManager = new import_ai_context_datasource_manager.AIContextDatasourceManager(this);
|
|
87
89
|
aiCodingManager = new import_ai_coding_manager.AICodingManager(this);
|
|
@@ -135,6 +137,7 @@ class PluginAIServer extends import_server.Plugin {
|
|
|
135
137
|
this.registerWorkflow();
|
|
136
138
|
this.registerWorkContextResolveStrategy();
|
|
137
139
|
(0, import_employee.registerAIEmployeeTaskNotification)(this);
|
|
140
|
+
(0, import_ai_conversations.registerAIConversationReadNotification)(this);
|
|
138
141
|
(0, import_employee.registerOnJobAbortedHandler)(this);
|
|
139
142
|
}
|
|
140
143
|
registerLLMProviders() {
|
|
@@ -7,10 +7,17 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Context, Next } from '@nocobase/actions';
|
|
10
|
+
declare function parallelConversationsLimit(ctx: Context, next: Next): Promise<never>;
|
|
10
11
|
declare const _default: {
|
|
11
12
|
name: string;
|
|
13
|
+
middlewares: {
|
|
14
|
+
only: string[];
|
|
15
|
+
handler: typeof parallelConversationsLimit;
|
|
16
|
+
}[];
|
|
12
17
|
actions: {
|
|
13
18
|
list(ctx: Context, next: Next): Promise<void>;
|
|
19
|
+
unreadCount(ctx: Context, next: Next): Promise<never>;
|
|
20
|
+
unreadCounts(ctx: Context, next: Next): Promise<never>;
|
|
14
21
|
create(ctx: Context, next: Next): Promise<never>;
|
|
15
22
|
update(ctx: Context, next: Next): Promise<never>;
|
|
16
23
|
updateOptions(ctx: Context, next: Next): Promise<never>;
|
|
@@ -19,6 +26,7 @@ declare const _default: {
|
|
|
19
26
|
updateToolArgs(ctx: Context, next: Next): Promise<any>;
|
|
20
27
|
sendMessages(ctx: Context, next: Next): Promise<any>;
|
|
21
28
|
abort(ctx: Context, next: Next): Promise<never>;
|
|
29
|
+
resumeStream(ctx: Context, next: Next): Promise<never>;
|
|
22
30
|
resendMessages(ctx: Context, next: Next): Promise<any>;
|
|
23
31
|
updateUserDecision(ctx: Context, next: Next): Promise<never>;
|
|
24
32
|
resumeToolCall(ctx: Context, next: Next): Promise<any>;
|