@nocobase/plugin-ai 2.1.0-alpha.20 → 2.1.0-alpha.22

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.
Files changed (99) hide show
  1. package/dist/ai/{ai-employees/cole.d.ts → tools/knowledge-base-retrieve.d.ts} +1 -1
  2. package/dist/ai/tools/knowledge-base-retrieve.js +94 -0
  3. package/dist/client/486.77c26e2e7f8daf28.js +10 -0
  4. package/dist/client/646.ef9d7c2ea8641044.js +10 -0
  5. package/dist/client/ai-employees/chatbox/AIEmployeeSwitch.d.ts +3 -1
  6. package/dist/client/ai-employees/chatbox/HintMessageHeader.d.ts +10 -0
  7. package/dist/client/ai-employees/chatbox/ModelSwitcher.d.ts +3 -1
  8. package/dist/client/ai-employees/chatbox/SearchSwitch.d.ts +3 -1
  9. package/dist/client/ai-employees/chatbox/Upload.d.ts +3 -1
  10. package/dist/client/ai-employees/chatbox/conversations/ConversationsList.d.ts +27 -0
  11. package/dist/client/ai-employees/chatbox/conversations/WorkflowTasksList.d.ts +31 -0
  12. package/dist/client/ai-employees/chatbox/conversations/common.d.ts +43 -0
  13. package/dist/{server/document-loader/loader.worker.d.ts → client/ai-employees/chatbox/conversations/index.d.ts} +1 -1
  14. package/dist/client/ai-employees/chatbox/hooks/useWorkflowTasks.d.ts +24 -0
  15. package/dist/client/ai-employees/chatbox/stores/chat-box.d.ts +8 -0
  16. package/dist/client/ai-employees/chatbox/stores/chat-conversations.d.ts +4 -0
  17. package/dist/client/ai-employees/chatbox/stores/workflow-tasks.d.ts +41 -0
  18. package/dist/client/ai-employees/workflow-tasks/tools/index.d.ts +10 -0
  19. package/dist/client/ai-employees/workflow-tasks/ui/WorkflowTaskOutputCard.d.ts +11 -0
  20. package/dist/client/components/ListCollapse.d.ts +28 -0
  21. package/dist/client/index.js +7 -7
  22. package/dist/client/repositories/AIConfigRepository.d.ts +3 -2
  23. package/dist/client/workflow/nodes/employee/components/AIEmployeeSelect.d.ts +10 -0
  24. package/dist/client/workflow/nodes/employee/components/assigness.d.ts +11 -0
  25. package/dist/client/workflow/nodes/employee/components/file-inputs.d.ts +10 -0
  26. package/dist/client/workflow/nodes/employee/components/message-inputs.d.ts +12 -0
  27. package/dist/client/workflow/nodes/employee/components/model-options.d.ts +10 -0
  28. package/dist/client/workflow/nodes/employee/components/skill-settings.d.ts +10 -0
  29. package/dist/client/workflow/nodes/employee/components/structured-output.d.ts +10 -0
  30. package/dist/client/workflow/nodes/employee/components/users-select.d.ts +15 -0
  31. package/dist/client/workflow/nodes/employee/components/web-search-options.d.ts +10 -0
  32. package/dist/client/workflow/nodes/employee/configuration.d.ts +12 -0
  33. package/dist/client/workflow/nodes/employee/flow-models/feedback.d.ts +13 -0
  34. package/dist/client/workflow/nodes/employee/flow-models/task.d.ts +13 -0
  35. package/dist/client/workflow/nodes/employee/index.d.ts +7 -31
  36. package/dist/externalVersion.js +14 -15
  37. package/dist/locale/en-US.json +44 -1
  38. package/dist/locale/zh-CN.json +45 -1
  39. package/dist/node_modules/fast-glob/out/index.js +8 -8
  40. package/dist/node_modules/fast-glob/package.json +1 -1
  41. package/dist/node_modules/flexsearch/dist/flexsearch.bundle.min.js +2 -2
  42. package/dist/node_modules/flexsearch/package.json +1 -1
  43. package/dist/node_modules/fs-extra/lib/index.js +1 -1
  44. package/dist/node_modules/fs-extra/package.json +1 -1
  45. package/dist/node_modules/nodejs-snowflake/nodejs_snowflake.js +1 -1
  46. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  47. package/dist/node_modules/openai/index.js +1 -1
  48. package/dist/node_modules/openai/package.json +1 -1
  49. package/dist/node_modules/zod/index.cjs +1 -1
  50. package/dist/node_modules/zod/package.json +1 -1
  51. package/dist/server/ai-employees/ai-conversations.d.ts +10 -4
  52. package/dist/server/ai-employees/ai-conversations.js +52 -14
  53. package/dist/server/ai-employees/ai-employee.d.ts +8 -10
  54. package/dist/server/ai-employees/ai-employee.js +130 -145
  55. package/dist/server/ai-employees/ai-knowledge-base.d.ts +28 -0
  56. package/dist/server/ai-employees/ai-knowledge-base.js +167 -0
  57. package/dist/server/ai-employees/middleware/index.d.ts +1 -0
  58. package/dist/server/ai-employees/middleware/index.js +3 -1
  59. package/dist/server/ai-employees/middleware/workflow-history.d.ts +22 -0
  60. package/dist/server/ai-employees/middleware/workflow-history.js +173 -0
  61. package/dist/server/collections/ai-conversations.js +12 -0
  62. package/dist/server/collections/ai-workflow-tasks.d.ts +10 -0
  63. package/dist/server/collections/ai-workflow-tasks.js +112 -0
  64. package/dist/server/collections/users-ai-workflow-tasks.d.ts +10 -0
  65. package/dist/server/collections/users-ai-workflow-tasks.js +44 -0
  66. package/dist/server/document-loader/constants.d.ts +1 -2
  67. package/dist/server/document-loader/constants.js +6 -1
  68. package/dist/server/document-loader/loader.d.ts +0 -1
  69. package/dist/server/document-loader/loader.js +2 -55
  70. package/dist/server/document-loader/types.d.ts +0 -1
  71. package/dist/server/llm-providers/provider.js +1 -1
  72. package/dist/server/manager/built-in-manager.js +5 -4
  73. package/dist/server/migrations/20260424000000-remove-cole-ai-employee.d.ts +14 -0
  74. package/dist/server/migrations/20260424000000-remove-cole-ai-employee.js +48 -0
  75. package/dist/server/plugin.d.ts +2 -0
  76. package/dist/server/plugin.js +10 -0
  77. package/dist/server/resource/aiConversations.js +29 -35
  78. package/dist/server/resource/aiWorkflowTasks.d.ts +12 -0
  79. package/dist/server/resource/aiWorkflowTasks.js +290 -0
  80. package/dist/server/utils.js +3 -2
  81. package/dist/server/workflow/nodes/employee/files.d.ts +16 -0
  82. package/dist/server/workflow/nodes/employee/files.js +125 -0
  83. package/dist/server/workflow/nodes/employee/handler.d.ts +11 -0
  84. package/dist/server/workflow/nodes/employee/handler.js +107 -0
  85. package/dist/server/workflow/nodes/employee/index.d.ts +17 -0
  86. package/dist/server/workflow/nodes/employee/index.js +391 -0
  87. package/dist/server/workflow/nodes/employee/tools.d.ts +12 -0
  88. package/dist/server/workflow/nodes/employee/tools.js +133 -0
  89. package/dist/server/workflow/nodes/employee/types.d.ts +35 -0
  90. package/dist/server/workflow/nodes/employee/types.js +24 -0
  91. package/dist/server/workflow/utils.d.ts +14 -0
  92. package/dist/server/workflow/utils.js +111 -0
  93. package/package.json +2 -2
  94. package/dist/ai/ai-employees/cole.js +0 -60
  95. package/dist/client/30.4f30511a3059c422.js +0 -10
  96. package/dist/server/document-loader/loader.worker.js +0 -68
  97. package/dist/server/document-loader/vendor/langchain/document_loaders/fs/text.d.ts +0 -20
  98. package/dist/server/document-loader/vendor/langchain/document_loaders/fs/text.js +0 -96
  99. /package/dist/client/ai-employees/chatbox/{Conversations.d.ts → conversations/Conversations.d.ts} +0 -0
@@ -45,8 +45,6 @@ var import_utils = require("../utils");
45
45
  var import_prompts = require("./prompts");
46
46
  var import_lodash = __toESM(require("lodash"));
47
47
  var import_ai_chat_conversation = require("../manager/ai-chat-conversation");
48
- var import_ai_feature_manager = require("../manager/ai-feature-manager");
49
- var import_prompts2 = require("@langchain/core/prompts");
50
48
  var import_middleware = require("./middleware");
51
49
  var import_checkpoints = require("./checkpoints");
52
50
  var import_langchain = require("langchain");
@@ -69,6 +67,8 @@ class AIEmployee {
69
67
  webSearch;
70
68
  model;
71
69
  legacy;
70
+ tools;
71
+ inWorkflow;
72
72
  constructor({
73
73
  ctx,
74
74
  employee,
@@ -78,7 +78,8 @@ class AIEmployee {
78
78
  webSearch,
79
79
  model,
80
80
  legacy,
81
- from = "main-agent"
81
+ from = "main-agent",
82
+ tools = []
82
83
  }) {
83
84
  this.employee = employee;
84
85
  this.ctx = ctx;
@@ -91,6 +92,7 @@ class AIEmployee {
91
92
  this.model = model;
92
93
  this.legacy = legacy;
93
94
  this.from = from;
95
+ this.tools = tools;
94
96
  const builtInManager = this.plugin.builtInManager;
95
97
  builtInManager.setupBuiltInInfo(ctx, this.employee);
96
98
  this.webSearch = webSearch;
@@ -106,6 +108,14 @@ class AIEmployee {
106
108
  });
107
109
  return messages;
108
110
  }
111
+ async isInWorkflow() {
112
+ if (this.inWorkflow !== void 0) {
113
+ return this.inWorkflow;
114
+ }
115
+ const conversation = await this.aiConversationsRepo.findByTargetKey(this.sessionId);
116
+ this.inWorkflow = (conversation == null ? void 0 : conversation.category) === "task";
117
+ return this.inWorkflow;
118
+ }
109
119
  // === Chat flow ===
110
120
  buildState(messages) {
111
121
  return {
@@ -125,7 +135,7 @@ class AIEmployee {
125
135
  historyMessages: [],
126
136
  tools,
127
137
  resolvedTools,
128
- middleware: this.getMiddleware({ tools, baseToolNames, model, providerName }),
138
+ middleware: await this.getMiddleware({ tools, baseToolNames, model, providerName }),
129
139
  config: void 0,
130
140
  state: void 0
131
141
  };
@@ -138,7 +148,7 @@ class AIEmployee {
138
148
  historyMessages,
139
149
  tools,
140
150
  resolvedTools,
141
- middleware: this.getMiddleware({
151
+ middleware: await this.getMiddleware({
142
152
  tools,
143
153
  baseToolNames,
144
154
  model,
@@ -183,6 +193,12 @@ class AIEmployee {
183
193
  userMessages = [],
184
194
  userDecisions
185
195
  }) {
196
+ await this.aiConversationsRepo.update({
197
+ values: { llmActiveState: "streaming" },
198
+ filter: {
199
+ sessionId: this.sessionId
200
+ }
201
+ });
186
202
  try {
187
203
  const { providerName, model, provider, chatContext, config, state } = await this.buildChatContext({
188
204
  messageId,
@@ -209,6 +225,13 @@ class AIEmployee {
209
225
  this.ctx.log.error(err);
210
226
  this.sendErrorResponse(err.message || "Chat error warning");
211
227
  return false;
228
+ } finally {
229
+ await this.aiConversationsRepo.update({
230
+ values: { llmActiveState: "idle" },
231
+ filter: {
232
+ sessionId: this.sessionId
233
+ }
234
+ });
212
235
  }
213
236
  }
214
237
  async invoke({
@@ -218,29 +241,43 @@ class AIEmployee {
218
241
  writer,
219
242
  context
220
243
  }) {
244
+ var _a;
245
+ await this.aiConversationsRepo.update({
246
+ values: { llmActiveState: "invoking" },
247
+ filter: {
248
+ sessionId: this.sessionId
249
+ }
250
+ });
221
251
  try {
222
252
  const { provider, chatContext, config, state } = await this.buildChatContext({
223
253
  messageId,
224
254
  userMessages,
225
255
  userDecisions
226
256
  });
257
+ const { threadId } = await this.getCurrentThread();
227
258
  const invokeConfig = {
228
259
  context: { ctx: this.ctx, decisions: chatContext.decisions, ...context },
229
260
  recursionLimit: 100,
261
+ configurable: this.from === "main-agent" ? { thread_id: threadId } : void 0,
230
262
  writer,
231
263
  ...config
232
264
  };
233
- if (this.from === "main-agent") {
234
- const { threadId } = await this.getCurrentThread();
235
- invokeConfig.configurable = { thread_id: threadId };
236
- }
237
- return await this.agentInvoke(provider, chatContext, invokeConfig, state);
265
+ const invokeResult = await this.agentInvoke(provider, chatContext, invokeConfig, state);
266
+ await this.handleInterruptedToolCalls((_a = invokeResult == null ? void 0 : invokeResult.__interrupt__) == null ? void 0 : _a[0], () => invokeResult == null ? void 0 : invokeResult.messageId);
267
+ return invokeResult;
238
268
  } catch (err) {
239
269
  if (err.name === "GraphInterrupt") {
240
270
  throw err;
241
271
  }
242
272
  this.ctx.log.error(err);
243
273
  throw err;
274
+ } finally {
275
+ await this.aiConversationsRepo.update({
276
+ values: { llmActiveState: "idle" },
277
+ filter: {
278
+ sessionId: this.sessionId
279
+ }
280
+ });
244
281
  }
245
282
  }
246
283
  // === Agent wiring & execution ===
@@ -322,7 +359,7 @@ class AIEmployee {
322
359
  }
323
360
  }
324
361
  async processChatStream(stream, options) {
325
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
362
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
326
363
  const aiMessageIdMap = /* @__PURE__ */ new Map();
327
364
  const { signal, providerName, model, provider, responseMetadata, allowEmpty = false } = options;
328
365
  let isReasoning = false;
@@ -384,35 +421,25 @@ class AIEmployee {
384
421
  }
385
422
  }
386
423
  } else if (mode === "updates") {
387
- if ("__interrupt__" in chunks) {
388
- const interruptId = chunks.__interrupt__[0].id;
389
- const interruptActions = this.toInterruptActions(chunks.__interrupt__[0].value);
390
- if (interruptActions.size) {
391
- const toolsMap = await this.getToolsMap();
392
- for (const interruptAction of interruptActions.values()) {
393
- if (!interruptAction.currentConversation || !interruptAction.toolCall) {
394
- this.logger.warn("currentConversation or toolCall not exist in __interrupt__", interruptAction);
395
- continue;
396
- }
397
- const { sessionId, from, username } = interruptAction.currentConversation;
398
- const { id: toolCallId, name: toolCallName } = interruptAction.toolCall;
399
- const messageId = aiMessageIdMap.get(sessionId);
400
- if (!messageId) {
401
- continue;
402
- }
403
- await this.updateToolCallInterrupted(sessionId, messageId, toolCallId, interruptId, interruptAction);
404
- this.protocol.with(interruptAction.currentConversation).toolCallStatus({
424
+ const interrupt = (_b = chunks == null ? void 0 : chunks.__interrupt__) == null ? void 0 : _b[0];
425
+ if (interrupt) {
426
+ const toolsMap = await this.getToolsMap();
427
+ await this.handleInterruptedToolCalls(
428
+ interrupt,
429
+ (sessionId) => aiMessageIdMap.get(sessionId),
430
+ ({ messageId, interruptAction, toolCall, currentConversation }) => {
431
+ this.protocol.with(currentConversation).toolCallStatus({
405
432
  toolCall: {
406
433
  messageId,
407
- id: toolCallId,
408
- name: toolCallName,
409
- willInterrupt: this.shouldInterruptToolCall(toolsMap.get(toolCallName))
434
+ id: toolCall.id,
435
+ name: toolCall.name,
436
+ willInterrupt: this.shouldInterruptToolCall(toolsMap.get(toolCall.name))
410
437
  },
411
438
  invokeStatus: "interrupted",
412
439
  interruptAction
413
440
  });
414
441
  }
415
- }
442
+ );
416
443
  }
417
444
  } else if (mode === "custom") {
418
445
  const { currentConversation } = chunks;
@@ -448,31 +475,31 @@ class AIEmployee {
448
475
  this.protocol.with(currentConversation).toolCalls(chunks.body);
449
476
  } else if (chunks.action === "beforeToolCall") {
450
477
  const toolsMap = await this.getToolsMap();
451
- const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_c = (_b = chunks.body) == null ? void 0 : _b.toolCall) == null ? void 0 : _c.name));
478
+ const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_d = (_c = chunks.body) == null ? void 0 : _c.toolCall) == null ? void 0 : _d.name));
452
479
  this.protocol.with(currentConversation).toolCallStatus({
453
480
  toolCall: {
454
- messageId: (_e = (_d = chunks.body) == null ? void 0 : _d.toolCall) == null ? void 0 : _e.messageId,
455
- id: (_g = (_f = chunks.body) == null ? void 0 : _f.toolCall) == null ? void 0 : _g.id,
456
- name: (_i = (_h = chunks.body) == null ? void 0 : _h.toolCall) == null ? void 0 : _i.name,
481
+ messageId: (_f = (_e = chunks.body) == null ? void 0 : _e.toolCall) == null ? void 0 : _f.messageId,
482
+ id: (_h = (_g = chunks.body) == null ? void 0 : _g.toolCall) == null ? void 0 : _h.id,
483
+ name: (_j = (_i = chunks.body) == null ? void 0 : _i.toolCall) == null ? void 0 : _j.name,
457
484
  willInterrupt
458
485
  },
459
486
  invokeStatus: "pending"
460
487
  });
461
488
  } else if (chunks.action === "afterToolCall") {
462
489
  const toolsMap = await this.getToolsMap();
463
- const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_k = (_j = chunks.body) == null ? void 0 : _j.toolCall) == null ? void 0 : _k.name));
490
+ const willInterrupt = this.shouldInterruptToolCall(toolsMap.get((_l = (_k = chunks.body) == null ? void 0 : _k.toolCall) == null ? void 0 : _l.name));
464
491
  this.protocol.with(currentConversation).toolCallStatus({
465
492
  toolCall: {
466
- messageId: (_m = (_l = chunks.body) == null ? void 0 : _l.toolCall) == null ? void 0 : _m.messageId,
467
- id: (_o = (_n = chunks.body) == null ? void 0 : _n.toolCall) == null ? void 0 : _o.id,
468
- name: (_q = (_p = chunks.body) == null ? void 0 : _p.toolCall) == null ? void 0 : _q.name,
493
+ messageId: (_n = (_m = chunks.body) == null ? void 0 : _m.toolCall) == null ? void 0 : _n.messageId,
494
+ id: (_p = (_o = chunks.body) == null ? void 0 : _o.toolCall) == null ? void 0 : _p.id,
495
+ name: (_r = (_q = chunks.body) == null ? void 0 : _q.toolCall) == null ? void 0 : _r.name,
469
496
  willInterrupt
470
497
  },
471
498
  invokeStatus: "done",
472
- status: (_s = (_r = chunks.body) == null ? void 0 : _r.toolCallResult) == null ? void 0 : _s.status,
473
- invokeStartTime: (_u = (_t = chunks.body) == null ? void 0 : _t.toolCallResult) == null ? void 0 : _u.invokeStartTime,
474
- invokeEndTime: (_w = (_v = chunks.body) == null ? void 0 : _v.toolCallResult) == null ? void 0 : _w.invokeEndTime,
475
- content: (_y = (_x = chunks.body) == null ? void 0 : _x.toolCallResult) == null ? void 0 : _y.content
499
+ status: (_t = (_s = chunks.body) == null ? void 0 : _s.toolCallResult) == null ? void 0 : _t.status,
500
+ invokeStartTime: (_v = (_u = chunks.body) == null ? void 0 : _u.toolCallResult) == null ? void 0 : _v.invokeStartTime,
501
+ invokeEndTime: (_x = (_w = chunks.body) == null ? void 0 : _w.toolCallResult) == null ? void 0 : _x.invokeEndTime,
502
+ content: (_z = (_y = chunks.body) == null ? void 0 : _y.toolCallResult) == null ? void 0 : _z.content
476
503
  });
477
504
  } else if (chunks.action === "beforeSendToolMessage") {
478
505
  const { messageId, messages } = chunks.body ?? {};
@@ -524,6 +551,39 @@ class AIEmployee {
524
551
  }
525
552
  }
526
553
  }
554
+ async handleInterruptedToolCalls(interrupt, getMessageId, onInterrupted) {
555
+ const interruptId = interrupt == null ? void 0 : interrupt.id;
556
+ const interruptActions = this.toInterruptActions(interrupt == null ? void 0 : interrupt.value);
557
+ if (!interruptId || !interruptActions.size) {
558
+ return;
559
+ }
560
+ for (const interruptAction of interruptActions.values()) {
561
+ const currentConversation = interruptAction.currentConversation;
562
+ const toolCall = interruptAction.toolCall;
563
+ if (!currentConversation || !toolCall) {
564
+ this.logger.warn("currentConversation or toolCall not exist in __interrupt__", interruptAction);
565
+ continue;
566
+ }
567
+ const messageId = getMessageId(currentConversation.sessionId);
568
+ if (!messageId) {
569
+ continue;
570
+ }
571
+ await this.updateToolCallInterrupted(
572
+ currentConversation.sessionId,
573
+ messageId,
574
+ toolCall.id,
575
+ interruptId,
576
+ interruptAction
577
+ );
578
+ await (onInterrupted == null ? void 0 : onInterrupted({
579
+ messageId,
580
+ interruptId,
581
+ interruptAction,
582
+ toolCall,
583
+ currentConversation
584
+ }));
585
+ }
586
+ }
527
587
  // === Prompts & knowledge base ===
528
588
  // Notice: employee.dataSourceSettings is not used in the current version.
529
589
  getEmployeeDataSourceContext() {
@@ -567,10 +627,10 @@ Field: ${field.name}, Title: ${(_a = field.options.uiSchema) == null ? void 0 :
567
627
  return message;
568
628
  }
569
629
  async getSystemPrompt(userMessages) {
570
- var _a;
630
+ var _a, _b, _c, _d, _e, _f, _g;
571
631
  const userConfig = await this.db.getRepository("usersAiEmployees").findOne({
572
632
  filter: {
573
- userId: (_a = this.ctx.auth) == null ? void 0 : _a.user.id,
633
+ userId: ((_a = this.ctx.auth) == null ? void 0 : _a.user.id) ?? 0,
574
634
  aiEmployee: this.employee.username
575
635
  }
576
636
  });
@@ -596,14 +656,14 @@ ${workContextBackground.join("\n")}`;
596
656
  ${addSystemPrompt.map((it) => it.content).join("\n")}`;
597
657
  }
598
658
  let knowledgeBase;
599
- if (this.isEnabledKnowledgeBase() && this.employee.knowledgeBasePrompt && (userMessages == null ? void 0 : userMessages.length)) {
659
+ const { knowledgeBaseManager } = this.plugin;
660
+ const employee = this.employee.toJSON();
661
+ if (await knowledgeBaseManager.isEnabledKnowledgeBase(employee) && employee.knowledgeBasePrompt && (userMessages == null ? void 0 : userMessages.length)) {
600
662
  const lastUserMessage = userMessages.filter((x) => x.role === "user").at(-1);
601
663
  if (lastUserMessage) {
602
- const docs = await this.retrieveKnowledgeBase(lastUserMessage);
603
- const knowledgeBaseData = docs.map((x) => x.content).join("\n");
604
- const promptTemplate = import_prompts2.ChatPromptTemplate.fromTemplate(this.employee.knowledgeBasePrompt);
605
- knowledgeBase = import_lodash.default.isEmpty(knowledgeBaseData) ? void 0 : await promptTemplate.format({
606
- knowledgeBaseData
664
+ knowledgeBase = await knowledgeBaseManager.retrievePrompt({
665
+ employee,
666
+ query: lastUserMessage.content.content
607
667
  });
608
668
  }
609
669
  }
@@ -621,15 +681,15 @@ ${addSystemPrompt.map((it) => it.content).join("\n")}`;
621
681
  dataSources: dataSourceMessage,
622
682
  environment: {
623
683
  database: this.db.sequelize.getDialect(),
624
- locale: this.ctx.getCurrentLocale() || "en-US",
625
- currentDateTime: getCurrentDateTimeForPrompt(this.ctx.getCurrentLocale(), getCurrentTimezone(this.ctx)),
684
+ locale: ((_c = (_b = this.ctx).getCurrentLocale) == null ? void 0 : _c.call(_b)) || "en-US",
685
+ currentDateTime: getCurrentDateTimeForPrompt((_e = (_d = this.ctx).getCurrentLocale) == null ? void 0 : _e.call(_d), getCurrentTimezone(this.ctx)),
626
686
  timezone: getCurrentTimezone(this.ctx)
627
687
  },
628
688
  knowledgeBase,
629
689
  availableSkills,
630
690
  availableAIEmployees
631
691
  });
632
- const { important } = this.ctx.action.params.values || {};
692
+ const { important } = ((_g = (_f = this.ctx.action) == null ? void 0 : _f.params) == null ? void 0 : _g.values) || {};
633
693
  if (important === "GraphRecursionError") {
634
694
  const importantPrompt = `<Important>You have already called tools multiple times and gathered sufficient information.
635
695
  First, provide a summary based on the existing information. Do not call additional tools.
@@ -639,92 +699,6 @@ If information is missing, clearly state it in the summary.</Important>`;
639
699
  return systemPrompt;
640
700
  }
641
701
  }
642
- async retrieveKnowledgeBase(userMessage) {
643
- const vectorStoreProvider = this.plugin.features.vectorStoreProvider;
644
- let queryResult = [];
645
- const queryString = userMessage.content.content;
646
- if (!queryString || import_lodash.default.isEmpty(queryString)) {
647
- return queryResult;
648
- }
649
- const { topK, score } = this.getAIEmployeeKnowledgeBaseConfig();
650
- const knowledgeBaseGroup = await this.getKnowledgeBaseGroup();
651
- for (const entry of knowledgeBaseGroup) {
652
- const { vectorStoreConfig, knowledgeBaseType, knowledgeBaseList } = entry;
653
- if (!knowledgeBaseList || import_lodash.default.isEmpty(knowledgeBaseList)) {
654
- continue;
655
- }
656
- if (knowledgeBaseType === "LOCAL") {
657
- const vectorStoreService = await vectorStoreProvider.createVectorStoreService(
658
- vectorStoreConfig.vectorStoreProvider,
659
- [
660
- {
661
- key: "vectorStoreConfigId",
662
- value: vectorStoreConfig.vectorStoreConfigId
663
- }
664
- ]
665
- );
666
- const knowledgeBaseOuterIds = knowledgeBaseList.map((x) => x.knowledgeBaseOuterId);
667
- const result = await vectorStoreService.search(queryString, {
668
- topK,
669
- score,
670
- filter: {
671
- knowledgeBaseOuterId: { in: knowledgeBaseOuterIds }
672
- }
673
- });
674
- queryResult = [...queryResult, ...result];
675
- } else if (knowledgeBaseType === "READONLY") {
676
- for (const knowledgeBase of knowledgeBaseList) {
677
- const vectorStoreService = await vectorStoreProvider.createVectorStoreService(
678
- vectorStoreConfig.vectorStoreProvider,
679
- [
680
- ...knowledgeBase.vectorStoreProps,
681
- {
682
- key: "vectorStoreConfigId",
683
- value: vectorStoreConfig.vectorStoreConfigId
684
- }
685
- ]
686
- );
687
- const result = await vectorStoreService.search(queryString, {
688
- topK,
689
- score
690
- });
691
- queryResult = [...queryResult, ...result];
692
- }
693
- } else if (knowledgeBaseType === "EXTERNAL") {
694
- for (const knowledgeBase of knowledgeBaseList) {
695
- const vectorStoreService = await vectorStoreProvider.createVectorStoreService(
696
- vectorStoreConfig.vectorStoreProvider,
697
- knowledgeBase.vectorStoreProps
698
- );
699
- const result = await vectorStoreService.search(queryString, {
700
- topK,
701
- score
702
- });
703
- queryResult = [...queryResult, ...result];
704
- }
705
- }
706
- }
707
- return queryResult;
708
- }
709
- isEnabledKnowledgeBase() {
710
- const featureEnabled = this.plugin.features.isFeaturesEnabled(Object.values(import_ai_feature_manager.EEFeatures));
711
- const knowledgeBaseEnabled = this.employee.enableKnowledgeBase;
712
- return featureEnabled && knowledgeBaseEnabled;
713
- }
714
- getAIEmployeeKnowledgeBaseConfig() {
715
- const { topK, score } = this.employee.knowledgeBase ?? {};
716
- return {
717
- topK,
718
- score
719
- };
720
- }
721
- async getKnowledgeBaseGroup() {
722
- const { knowledgeBaseIds } = this.employee.knowledgeBase ?? {};
723
- if (!knowledgeBaseIds || import_lodash.default.isEmpty(knowledgeBaseIds)) {
724
- return [];
725
- }
726
- return await this.plugin.features.knowledgeBase.getKnowledgeBaseGroup(knowledgeBaseIds);
727
- }
728
702
  // === Tool calls ===
729
703
  async initToolCall(transaction, messageId, toolCalls) {
730
704
  const nowTime = /* @__PURE__ */ new Date();
@@ -1123,7 +1097,7 @@ If information is missing, clearly state it in the summary.</Important>`;
1123
1097
  toInterruptActions(interrupt) {
1124
1098
  var _a;
1125
1099
  const result = /* @__PURE__ */ new Map();
1126
- const { actionRequests = [], reviewConfigs = [] } = interrupt;
1100
+ const { actionRequests = [], reviewConfigs = [] } = interrupt ?? {};
1127
1101
  if (!actionRequests.length) {
1128
1102
  return result;
1129
1103
  }
@@ -1159,6 +1133,13 @@ If information is missing, clearly state it in the summary.</Important>`;
1159
1133
  const generalToolsNameSet = new Set(tools.map((x) => x.definition.name));
1160
1134
  const toolMap = await this.getToolsMap();
1161
1135
  const employeeTools = ((_a = this.employee.skillSettings) == null ? void 0 : _a.tools) ?? [];
1136
+ employeeTools.push(...this.tools);
1137
+ if (await this.plugin.knowledgeBaseManager.isEnabledKnowledgeBase(this.employee.toJSON())) {
1138
+ const knowledgeBaseRetrieveTool = await this.toolsManager.getTools("knowledge-base-retrieve");
1139
+ if (knowledgeBaseRetrieveTool) {
1140
+ employeeTools.push({ name: "knowledge-base-retrieve" });
1141
+ }
1142
+ }
1162
1143
  for (const toolSetting of employeeTools) {
1163
1144
  if (generalToolsNameSet.has(toolSetting.name)) {
1164
1145
  continue;
@@ -1255,14 +1236,16 @@ If information is missing, clearly state it in the summary.</Important>`;
1255
1236
  );
1256
1237
  return availableAIEmployees;
1257
1238
  }
1258
- getMiddleware(options) {
1239
+ async getMiddleware(options) {
1259
1240
  const { providerName, model, tools, baseToolNames, messageId, agentThread } = options;
1241
+ const inWorkflow = await this.isInWorkflow();
1260
1242
  return [
1261
1243
  (0, import_middleware.skillToolBindingMiddleware)(this, {
1262
1244
  baseToolNames: Array.from(baseToolNames.values())
1263
1245
  }),
1264
1246
  (0, import_middleware.toolInteractionMiddleware)(this, tools),
1265
1247
  (0, import_middleware.toolCallStatusMiddleware)(this),
1248
+ ...inWorkflow ? [(0, import_middleware.workflowHistoryMiddleware)(this, this.db)] : [],
1266
1249
  (0, import_middleware.conversationMiddleware)(this, { providerName, model, messageId, agentThread })
1267
1250
  ];
1268
1251
  }
@@ -1288,7 +1271,9 @@ If information is missing, clearly state it in the summary.</Important>`;
1288
1271
  throw new Error("Fail to create new agent thread");
1289
1272
  }
1290
1273
  async getToolsMap() {
1291
- const tools = await this.listTools();
1274
+ const tools = await this.listTools({
1275
+ sessionId: this.sessionId
1276
+ });
1292
1277
  return new Map(tools.map((tool) => [tool.definition.name, tool]));
1293
1278
  }
1294
1279
  listTools(filter) {
@@ -0,0 +1,28 @@
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 { AIEmployee } from '../../collections/ai-employees';
10
+ import { DocumentSegmentedWithScore } from '../features';
11
+ import type PluginAIServer from '../plugin';
12
+ export type KnowledgeBaseRetrieveOptions = {
13
+ username?: string;
14
+ employee?: AIEmployee;
15
+ query: string;
16
+ };
17
+ export declare class KnowledgeBaseManager {
18
+ private readonly plugin;
19
+ constructor(plugin: PluginAIServer);
20
+ retrievePrompt({ username, employee, query }: KnowledgeBaseRetrieveOptions): Promise<string>;
21
+ retrieve({ username, employee, query }: KnowledgeBaseRetrieveOptions): Promise<DocumentSegmentedWithScore[]>;
22
+ isEnabledKnowledgeBase(username: string): Promise<boolean>;
23
+ isEnabledKnowledgeBase(employee: AIEmployee): Promise<boolean>;
24
+ private getAIEmployeeKnowledgeBaseConfig;
25
+ private getKnowledgeBaseGroup;
26
+ private getEmployee;
27
+ private get aiEmployeeRepo();
28
+ }
@@ -0,0 +1,167 @@
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 __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
+ var ai_knowledge_base_exports = {};
38
+ __export(ai_knowledge_base_exports, {
39
+ KnowledgeBaseManager: () => KnowledgeBaseManager
40
+ });
41
+ module.exports = __toCommonJS(ai_knowledge_base_exports);
42
+ var import_prompts = require("@langchain/core/prompts");
43
+ var import_ai_feature_manager = require("../manager/ai-feature-manager");
44
+ var import_lodash = __toESM(require("lodash"));
45
+ class KnowledgeBaseManager {
46
+ constructor(plugin) {
47
+ this.plugin = plugin;
48
+ }
49
+ async retrievePrompt({ username, employee, query }) {
50
+ employee = employee ?? await this.getEmployee(username);
51
+ if (!employee) {
52
+ return "Specified knowledge base not existed";
53
+ }
54
+ const promptTemplate = import_prompts.ChatPromptTemplate.fromTemplate(employee.knowledgeBasePrompt);
55
+ const docs = await this.retrieve({
56
+ employee,
57
+ query
58
+ });
59
+ if (!(docs == null ? void 0 : docs.length)) {
60
+ return "No document match in knowledge base";
61
+ }
62
+ const knowledgeBaseData = docs.map((x) => x.content).join("\n");
63
+ return import_lodash.default.isEmpty(knowledgeBaseData) ? void 0 : await promptTemplate.format({
64
+ knowledgeBaseData
65
+ });
66
+ }
67
+ async retrieve({ username, employee, query }) {
68
+ const vectorStoreProvider = this.plugin.features.vectorStoreProvider;
69
+ let queryResult = [];
70
+ if (!query || import_lodash.default.isEmpty(query)) {
71
+ return queryResult;
72
+ }
73
+ employee = employee ?? await this.getEmployee(username);
74
+ if (!employee) {
75
+ return queryResult;
76
+ }
77
+ const { topK, score } = this.getAIEmployeeKnowledgeBaseConfig(employee);
78
+ const knowledgeBaseGroup = await this.getKnowledgeBaseGroup(employee);
79
+ for (const entry of knowledgeBaseGroup) {
80
+ const { vectorStoreConfig, knowledgeBaseType, knowledgeBaseList } = entry;
81
+ if (!knowledgeBaseList || import_lodash.default.isEmpty(knowledgeBaseList)) {
82
+ continue;
83
+ }
84
+ if (knowledgeBaseType === "LOCAL") {
85
+ const vectorStoreService = await vectorStoreProvider.createVectorStoreService(
86
+ vectorStoreConfig.vectorStoreProvider,
87
+ [
88
+ {
89
+ key: "vectorStoreConfigId",
90
+ value: vectorStoreConfig.vectorStoreConfigId
91
+ }
92
+ ]
93
+ );
94
+ const knowledgeBaseOuterIds = knowledgeBaseList.map((x) => x.knowledgeBaseOuterId);
95
+ const result = await vectorStoreService.search(query, {
96
+ topK,
97
+ score,
98
+ filter: {
99
+ knowledgeBaseOuterId: { in: knowledgeBaseOuterIds }
100
+ }
101
+ });
102
+ queryResult = [...queryResult, ...result];
103
+ } else if (knowledgeBaseType === "READONLY") {
104
+ for (const knowledgeBase of knowledgeBaseList) {
105
+ const vectorStoreService = await vectorStoreProvider.createVectorStoreService(
106
+ vectorStoreConfig.vectorStoreProvider,
107
+ [
108
+ ...knowledgeBase.vectorStoreProps,
109
+ {
110
+ key: "vectorStoreConfigId",
111
+ value: vectorStoreConfig.vectorStoreConfigId
112
+ }
113
+ ]
114
+ );
115
+ const result = await vectorStoreService.search(query, {
116
+ topK,
117
+ score
118
+ });
119
+ queryResult = [...queryResult, ...result];
120
+ }
121
+ } else if (knowledgeBaseType === "EXTERNAL") {
122
+ for (const knowledgeBase of knowledgeBaseList) {
123
+ const vectorStoreService = await vectorStoreProvider.createVectorStoreService(
124
+ vectorStoreConfig.vectorStoreProvider,
125
+ knowledgeBase.vectorStoreProps
126
+ );
127
+ const result = await vectorStoreService.search(query, {
128
+ topK,
129
+ score
130
+ });
131
+ queryResult = [...queryResult, ...result];
132
+ }
133
+ }
134
+ }
135
+ return queryResult;
136
+ }
137
+ async isEnabledKnowledgeBase(usernameOrEmployee) {
138
+ const featureEnabled = this.plugin.features.isFeaturesEnabled(Object.values(import_ai_feature_manager.EEFeatures));
139
+ const employee = typeof usernameOrEmployee === "string" ? await this.getEmployee(usernameOrEmployee) : usernameOrEmployee;
140
+ const knowledgeBaseEnabled = employee == null ? void 0 : employee.enableKnowledgeBase;
141
+ return featureEnabled && knowledgeBaseEnabled;
142
+ }
143
+ getAIEmployeeKnowledgeBaseConfig(employee) {
144
+ const { topK, score } = (employee == null ? void 0 : employee.knowledgeBase) ?? {};
145
+ return {
146
+ topK,
147
+ score
148
+ };
149
+ }
150
+ async getKnowledgeBaseGroup(employee) {
151
+ const { knowledgeBaseIds } = (employee == null ? void 0 : employee.knowledgeBase) ?? {};
152
+ if (!knowledgeBaseIds || import_lodash.default.isEmpty(knowledgeBaseIds)) {
153
+ return [];
154
+ }
155
+ return await this.plugin.features.knowledgeBase.getKnowledgeBaseGroup(knowledgeBaseIds);
156
+ }
157
+ async getEmployee(username) {
158
+ return await this.aiEmployeeRepo.findOne({ filter: { username } });
159
+ }
160
+ get aiEmployeeRepo() {
161
+ return this.plugin.db.getRepository("aiEmployees");
162
+ }
163
+ }
164
+ // Annotate the CommonJS export names for ESM import in node:
165
+ 0 && (module.exports = {
166
+ KnowledgeBaseManager
167
+ });
@@ -9,3 +9,4 @@
9
9
  export * from './conversation';
10
10
  export * from './skill-tools';
11
11
  export * from './tools';
12
+ export * from './workflow-history';