@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.
Files changed (75) hide show
  1. package/dist/ai/ai-employees/atlas/index.d.ts +10 -0
  2. package/dist/ai/ai-employees/atlas/index.js +56 -0
  3. package/dist/ai/ai-employees/atlas/prompt.md +84 -0
  4. package/dist/ai/ai-employees/vera.js +1 -1
  5. package/dist/ai/tools/chartGenerator.js +1 -0
  6. package/dist/ai/tools/getSkill.js +1 -1
  7. package/dist/ai/tools/sub-agents/dispatch-sub-agent-task.d.ts +10 -0
  8. package/dist/ai/tools/sub-agents/dispatch-sub-agent-task.js +108 -0
  9. package/dist/ai/tools/sub-agents/get-ai-employee.d.ts +10 -0
  10. package/dist/ai/tools/sub-agents/get-ai-employee.js +67 -0
  11. package/dist/ai/tools/sub-agents/list-ai-employees.d.ts +10 -0
  12. package/dist/ai/tools/sub-agents/list-ai-employees.js +64 -0
  13. package/dist/ai/tools/sub-agents/shared.d.ts +33 -0
  14. package/dist/ai/tools/sub-agents/shared.js +169 -0
  15. package/dist/ai/tools/suggestions.js +2 -2
  16. package/dist/client/7237366e104efa7a.js +10 -0
  17. package/dist/client/748fbb87c1013c6e.js +10 -0
  18. package/dist/client/ai-employees/built-in/utils.d.ts +1 -0
  19. package/dist/client/ai-employees/chatbox/AIEmployeeSwitch.d.ts +0 -1
  20. package/dist/client/ai-employees/chatbox/hooks/useChatBoxActions.d.ts +5 -3
  21. package/dist/client/ai-employees/chatbox/roles.d.ts +1 -0
  22. package/dist/client/ai-employees/chatbox/stores/chat-messages.d.ts +8 -0
  23. package/dist/client/ai-employees/chatbox/utils.d.ts +15 -1
  24. package/dist/client/ai-employees/sub-agents/tools/index.d.ts +10 -0
  25. package/dist/client/ai-employees/sub-agents/ui/SubAgentDispatchCard.d.ts +21 -0
  26. package/dist/client/ai-employees/types.d.ts +19 -0
  27. package/dist/client/index.js +7 -7
  28. package/dist/externalVersion.js +16 -15
  29. package/dist/locale/en-US.json +10 -1
  30. package/dist/locale/zh-CN.json +10 -1
  31. package/dist/node_modules/fast-glob/package.json +1 -1
  32. package/dist/node_modules/flexsearch/package.json +1 -1
  33. package/dist/node_modules/fs-extra/package.json +1 -1
  34. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  35. package/dist/node_modules/openai/package.json +1 -1
  36. package/dist/node_modules/zod/package.json +1 -1
  37. package/dist/server/ai-employees/ai-conversations.d.ts +64 -0
  38. package/dist/server/ai-employees/ai-conversations.js +285 -0
  39. package/dist/server/ai-employees/ai-employee.d.ts +85 -9
  40. package/dist/server/ai-employees/ai-employee.js +264 -149
  41. package/dist/server/ai-employees/middleware/conversation.d.ts +2 -0
  42. package/dist/server/ai-employees/middleware/conversation.js +38 -5
  43. package/dist/server/ai-employees/middleware/tools.js +37 -10
  44. package/dist/server/ai-employees/prompts.d.ts +9 -1
  45. package/dist/server/ai-employees/prompts.js +24 -2
  46. package/dist/server/ai-employees/sub-agents/dispatcher.d.ts +36 -0
  47. package/dist/server/ai-employees/sub-agents/dispatcher.js +225 -0
  48. package/dist/server/ai-employees/sub-agents/index.d.ts +9 -0
  49. package/dist/server/ai-employees/sub-agents/index.js +36 -0
  50. package/dist/server/collections/ai-conversations.js +6 -0
  51. package/dist/server/llm-providers/anthropic.d.ts +1 -0
  52. package/dist/server/llm-providers/anthropic.js +2 -1
  53. package/dist/server/llm-providers/dashscope.d.ts +3 -0
  54. package/dist/server/llm-providers/dashscope.js +16 -2
  55. package/dist/server/llm-providers/deepseek.d.ts +1 -0
  56. package/dist/server/llm-providers/deepseek.js +5 -2
  57. package/dist/server/llm-providers/google-genai.d.ts +1 -0
  58. package/dist/server/llm-providers/google-genai.js +2 -1
  59. package/dist/server/llm-providers/kimi/provider.d.ts +1 -0
  60. package/dist/server/llm-providers/openai/responses.d.ts +1 -0
  61. package/dist/server/llm-providers/openai/responses.js +2 -1
  62. package/dist/server/llm-providers/provider.d.ts +1 -10
  63. package/dist/server/llm-providers/provider.js +3 -34
  64. package/dist/server/migrations/20260319000000-add-ai-conversations-from.d.ts +14 -0
  65. package/dist/server/migrations/20260319000000-add-ai-conversations-from.js +63 -0
  66. package/dist/server/plugin.d.ts +4 -0
  67. package/dist/server/plugin.js +4 -0
  68. package/dist/server/resource/aiConversations.d.ts +3 -3
  69. package/dist/server/resource/aiConversations.js +125 -159
  70. package/dist/server/types/ai-chat-conversation.type.d.ts +8 -2
  71. package/dist/server/types/ai-message.type.d.ts +7 -0
  72. package/dist/server/utils.d.ts +3 -0
  73. package/dist/server/utils.js +25 -1
  74. package/package.json +4 -2
  75. package/dist/client/27539a4356faebb1.js +0 -10
@@ -75,55 +75,61 @@ var aiConversations_default = {
75
75
  if (!userId) {
76
76
  return ctx.throw(403);
77
77
  }
78
+ const filter = ctx.action.params.filter || {};
78
79
  ctx.action.mergeParams({
79
80
  filter: {
80
- userId
81
+ ...filter,
82
+ userId,
83
+ from: filter.from ?? "main-agent"
81
84
  }
82
85
  });
83
86
  return import_actions.default.list(ctx, next);
84
87
  },
85
88
  async create(ctx, next) {
86
89
  var _a;
90
+ const plugin = ctx.app.pm.get("ai");
87
91
  const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
92
+ if (!userId) {
93
+ return ctx.throw(403);
94
+ }
88
95
  const { aiEmployee, systemMessage, skillSettings, conversationSettings } = ctx.action.params.values || {};
89
96
  const employee = await getAIEmployee(ctx, aiEmployee.username);
90
97
  if (!employee) {
91
98
  ctx.throw(400, "AI employee not found");
92
99
  }
93
- const repo = ctx.db.getRepository("aiConversations");
94
- ctx.body = await repo.create({
95
- values: {
100
+ try {
101
+ ctx.body = await plugin.aiConversationsManager.create({
96
102
  userId,
97
103
  aiEmployee,
98
104
  options: {
99
105
  systemMessage,
100
106
  skillSettings,
101
107
  conversationSettings
102
- },
103
- thread: 1
108
+ }
109
+ });
110
+ } catch (error) {
111
+ if (error.message === "AI employee not found") {
112
+ ctx.throw(400, error.message);
104
113
  }
105
- });
114
+ throw error;
115
+ }
106
116
  await next();
107
117
  },
108
118
  async update(ctx, next) {
109
119
  var _a;
120
+ const plugin = ctx.app.pm.get("ai");
110
121
  const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
122
+ if (!userId) {
123
+ return ctx.throw(403);
124
+ }
111
125
  const { filterByTk: sessionId } = ctx.action.params;
112
126
  const { title } = ctx.action.params.values || {};
113
- const repo = ctx.db.getRepository("aiConversations");
114
- ctx.body = await repo.update({
115
- filter: {
116
- userId,
117
- sessionId
118
- },
119
- values: {
120
- title
121
- }
122
- });
127
+ ctx.body = await plugin.aiConversationsManager.update({ userId, sessionId, title });
123
128
  await next();
124
129
  },
125
130
  async updateOptions(ctx, next) {
126
131
  var _a;
132
+ const plugin = ctx.app.pm.get("ai");
127
133
  const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
128
134
  if (!userId) {
129
135
  return ctx.throw(403);
@@ -136,34 +142,18 @@ var aiConversations_default = {
136
142
  if (!systemMessage && !skillSettings && !conversationSettings) {
137
143
  return ctx.throw(400, "invalid options");
138
144
  }
139
- const conversation = await ctx.db.getRepository("aiConversations").findOne({
140
- filter: {
145
+ try {
146
+ ctx.body = await plugin.aiConversationsManager.update({
147
+ userId,
141
148
  sessionId,
142
- userId
149
+ options: { systemMessage, skillSettings, conversationSettings }
150
+ });
151
+ } catch (error) {
152
+ if (error.message === "invalid sessionId") {
153
+ ctx.throw(400, error.message);
143
154
  }
144
- });
145
- if (!conversation) {
146
- ctx.throw(400, "invalid sessionId");
147
- }
148
- const options = conversation.options ?? {};
149
- if (systemMessage) {
150
- options["systemMessage"] = systemMessage;
151
- }
152
- if (skillSettings) {
153
- options["skillSettings"] = skillSettings;
155
+ throw error;
154
156
  }
155
- if (conversationSettings) {
156
- options["conversationSettings"] = conversationSettings;
157
- }
158
- ctx.body = await ctx.db.getRepository("aiConversations").update({
159
- filter: {
160
- userId,
161
- sessionId
162
- },
163
- values: {
164
- options
165
- }
166
- });
167
157
  await next();
168
158
  },
169
159
  async destroy(ctx, next) {
@@ -191,88 +181,19 @@ var aiConversations_default = {
191
181
  ctx.throw(400);
192
182
  }
193
183
  const paginate = ((_b = ctx.action.params) == null ? void 0 : _b.paginate) === "false" ? false : true;
194
- const conversation = await ctx.db.getRepository("aiConversations").findOne({
195
- filter: {
184
+ try {
185
+ ctx.body = await plugin.aiConversationsManager.getMessages({
186
+ userId,
196
187
  sessionId,
197
- userId
188
+ cursor,
189
+ paginate
190
+ });
191
+ } catch (error) {
192
+ if (error.message === "invalid sessionId") {
193
+ ctx.throw(400);
198
194
  }
199
- });
200
- if (!conversation) {
201
- ctx.throw(400);
195
+ throw error;
202
196
  }
203
- const pageSize = 10;
204
- const maxLimit = 200;
205
- const messageRepository = ctx.db.getRepository("aiConversations.messages", sessionId);
206
- const filter = {
207
- role: {
208
- $notIn: ["tool"]
209
- }
210
- };
211
- if (paginate && cursor) {
212
- filter["messageId"] = {
213
- $lt: cursor
214
- };
215
- }
216
- const rows = await messageRepository.find({
217
- sort: ["-messageId"],
218
- limit: paginate ? pageSize + 1 : maxLimit,
219
- filter
220
- });
221
- const hasMore = paginate && rows.length > pageSize;
222
- const data = hasMore ? rows.slice(0, -1) : rows;
223
- const newCursor = data.length ? data[data.length - 1].messageId : null;
224
- const toolCallIds = data.filter((row) => {
225
- var _a2;
226
- return ((_a2 = row == null ? void 0 : row.toolCalls) == null ? void 0 : _a2.length) ?? 0 > 0;
227
- }).flatMap((row) => row.toolCalls).map((toolCall) => toolCall.id);
228
- const toolMessages = await ctx.db.getRepository("aiToolMessages").find({
229
- filter: {
230
- sessionId,
231
- toolCallId: {
232
- $in: toolCallIds
233
- }
234
- }
235
- });
236
- const toolMessageKey = (messageId, toolCallId) => `${messageId}:${toolCallId}`;
237
- const toolMessageMap = new Map(
238
- toolMessages.map((toolMessage) => [
239
- toolMessageKey(toolMessage.messageId, toolMessage.toolCallId),
240
- toolMessage
241
- ])
242
- );
243
- const toolsList = await plugin.ai.toolsManager.listTools();
244
- const toolsMap = new Map(toolsList.map((t) => [t.definition.name, t]));
245
- ctx.body = {
246
- rows: data.map((row) => {
247
- var _a2, _b2;
248
- if (((_a2 = row == null ? void 0 : row.toolCalls) == null ? void 0 : _a2.length) ?? 0 > 0) {
249
- for (const toolCall of row.toolCalls) {
250
- const tools = toolsMap.get(toolCall.name);
251
- const toolMessage = toolMessageMap.get(toolMessageKey(row.messageId, toolCall.id));
252
- toolCall.invokeStatus = toolMessage == null ? void 0 : toolMessage.invokeStatus;
253
- toolCall.auto = toolMessage == null ? void 0 : toolMessage.auto;
254
- toolCall.status = toolMessage == null ? void 0 : toolMessage.status;
255
- toolCall.content = toolMessage == null ? void 0 : toolMessage.content;
256
- toolCall.execution = tools == null ? void 0 : tools.execution;
257
- toolCall.willInterrupt = (tools == null ? void 0 : tools.execution) === "frontend" || (toolMessage == null ? void 0 : toolMessage.auto) === false;
258
- toolCall.defaultPermission = tools == null ? void 0 : tools.defaultPermission;
259
- }
260
- }
261
- const providerOptions = plugin.aiManager.llmProviders.get((_b2 = row.metadata) == null ? void 0 : _b2.provider);
262
- if (!providerOptions) {
263
- return (0, import_utils.parseResponseMessage)(row);
264
- }
265
- const Provider = providerOptions.provider;
266
- const provider = new Provider({
267
- app: ctx.app
268
- });
269
- return provider.parseResponseMessage(row);
270
- }),
271
- ...paginate && {
272
- hasMore,
273
- cursor: newCursor
274
- }
275
- };
276
197
  await next();
277
198
  },
278
199
  async updateToolArgs(ctx, next) {
@@ -320,7 +241,12 @@ var aiConversations_default = {
320
241
  await next();
321
242
  },
322
243
  async sendMessages(ctx, next) {
323
- var _a, _b;
244
+ var _a, _b, _c;
245
+ const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
246
+ if (!userId) {
247
+ return ctx.throw(403);
248
+ }
249
+ const plugin = ctx.app.pm.get("ai");
324
250
  const {
325
251
  sessionId,
326
252
  aiEmployee: employeeName,
@@ -355,7 +281,10 @@ var aiConversations_default = {
355
281
  }
356
282
  try {
357
283
  const conversation = await ctx.db.getRepository("aiConversations").findOne({
358
- filterByTk: sessionId
284
+ filter: {
285
+ sessionId,
286
+ userId
287
+ }
359
288
  });
360
289
  if (!conversation) {
361
290
  if (shouldStream) {
@@ -390,29 +319,41 @@ var aiConversations_default = {
390
319
  return next();
391
320
  }
392
321
  const legacy = conversation.thread === 0;
393
- const aiEmployee = new import_ai_employee.AIEmployee(
322
+ const aiEmployee = new import_ai_employee.AIEmployee({
394
323
  ctx,
395
324
  employee,
396
325
  sessionId,
397
- (_a = conversation.options) == null ? void 0 : _a.systemMessage,
398
- (_b = conversation.options) == null ? void 0 : _b.skillSettings,
326
+ systemMessage: (_b = conversation.options) == null ? void 0 : _b.systemMessage,
327
+ skillSettings: (_c = conversation.options) == null ? void 0 : _c.skillSettings,
399
328
  webSearch,
400
329
  model,
401
330
  legacy
402
- );
331
+ });
403
332
  if (!editingMessageId) {
404
- const toolMessages = await aiEmployee.cancelToolCall();
405
- if (toolMessages == null ? void 0 : toolMessages.length) {
406
- for (let i = toolMessages.length - 1; i >= 0; i--) {
407
- const toolMessage = toolMessages[i];
408
- messages.unshift({
409
- role: toolMessage.role,
410
- content: toolMessage.content,
411
- toolCalls: toolMessage.toolCalls,
412
- attachments: toolMessage.attachments,
413
- workContext: toolMessage.workContext,
414
- metadata: toolMessage.metadata
415
- });
333
+ if (await plugin.subAgentsDispatcher.isInterrupted(ctx)) {
334
+ const userDecisions = await plugin.subAgentsDispatcher.reject(ctx);
335
+ if (userDecisions) {
336
+ if (shouldStream) {
337
+ await aiEmployee.stream({ userDecisions });
338
+ } else {
339
+ ctx.body = await aiEmployee.invoke({ userDecisions });
340
+ }
341
+ return;
342
+ }
343
+ } else {
344
+ const toolMessages = await aiEmployee.cancelToolCall();
345
+ if (toolMessages == null ? void 0 : toolMessages.length) {
346
+ for (let i = toolMessages.length - 1; i >= 0; i--) {
347
+ const toolMessage = toolMessages[i];
348
+ messages.unshift({
349
+ role: toolMessage.role,
350
+ content: toolMessage.content,
351
+ toolCalls: toolMessage.toolCalls,
352
+ attachments: toolMessage.attachments,
353
+ workContext: toolMessage.workContext,
354
+ metadata: toolMessage.metadata
355
+ });
356
+ }
416
357
  }
417
358
  }
418
359
  }
@@ -429,17 +370,36 @@ var aiConversations_default = {
429
370
  ctx.status = 500;
430
371
  ctx.body = { error: err.message || "Tool call error" };
431
372
  }
373
+ } finally {
374
+ await next();
432
375
  }
433
- await next();
434
376
  },
435
377
  async abort(ctx, next) {
378
+ var _a;
379
+ const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
380
+ if (!userId) {
381
+ return ctx.throw(403);
382
+ }
436
383
  const { sessionId } = ctx.action.params.values || {};
437
384
  const plugin = ctx.app.pm.get("ai");
385
+ const conversation = await ctx.db.getRepository("aiConversations").findOne({
386
+ filter: {
387
+ sessionId,
388
+ userId
389
+ }
390
+ });
391
+ if (!conversation) {
392
+ ctx.throw(404, "conversation not found");
393
+ }
438
394
  plugin.aiEmployeesManager.abortConversation(sessionId);
439
395
  await next();
440
396
  },
441
397
  async resendMessages(ctx, next) {
442
- var _a, _b;
398
+ var _a, _b, _c;
399
+ const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
400
+ if (!userId) {
401
+ return ctx.throw(403);
402
+ }
443
403
  setupSSEHeaders(ctx);
444
404
  const { sessionId, webSearch, model } = ctx.action.params.values || {};
445
405
  let { messageId } = ctx.action.params.values || {};
@@ -450,7 +410,8 @@ var aiConversations_default = {
450
410
  try {
451
411
  const conversation = await ctx.db.getRepository("aiConversations").findOne({
452
412
  filter: {
453
- sessionId
413
+ sessionId,
414
+ userId
454
415
  }
455
416
  });
456
417
  if (!conversation) {
@@ -496,15 +457,15 @@ var aiConversations_default = {
496
457
  sendErrorResponse(ctx, "AI employee not found");
497
458
  return next();
498
459
  }
499
- const aiEmployee = new import_ai_employee.AIEmployee(
460
+ const aiEmployee = new import_ai_employee.AIEmployee({
500
461
  ctx,
501
462
  employee,
502
463
  sessionId,
503
- (_a = conversation.options) == null ? void 0 : _a.systemMessage,
504
- (_b = conversation.options) == null ? void 0 : _b.skillSettings,
464
+ systemMessage: (_b = conversation.options) == null ? void 0 : _b.systemMessage,
465
+ skillSettings: (_c = conversation.options) == null ? void 0 : _c.skillSettings,
505
466
  webSearch,
506
467
  model
507
- );
468
+ });
508
469
  await aiEmployee.stream({ messageId, userMessages: resendMessages.length ? resendMessages : void 0 });
509
470
  } catch (err) {
510
471
  ctx.log.error(err);
@@ -532,7 +493,7 @@ var aiConversations_default = {
532
493
  if (!conversation) {
533
494
  ctx.throw(400);
534
495
  }
535
- const message = await ctx.db.getRepository("aiConversations.messages", sessionId).findOne({
496
+ const message = await ctx.db.getRepository("aiMessages").findOne({
536
497
  filter: {
537
498
  messageId
538
499
  }
@@ -546,7 +507,7 @@ var aiConversations_default = {
546
507
  }
547
508
  const aiToolMessagesModel = ctx.db.getModel("aiToolMessages");
548
509
  const toolCall = await aiToolMessagesModel.findOne({
549
- where: { sessionId, messageId, toolCallId }
510
+ where: { sessionId: message.sessionId, messageId: message.messageId, toolCallId }
550
511
  });
551
512
  if (!toolCall) {
552
513
  ctx.throw(400);
@@ -558,8 +519,8 @@ var aiConversations_default = {
558
519
  },
559
520
  {
560
521
  where: {
561
- sessionId,
562
- messageId,
522
+ sessionId: message.sessionId,
523
+ messageId: message.messageId,
563
524
  toolCallId,
564
525
  invokeStatus: "interrupted"
565
526
  }
@@ -568,8 +529,8 @@ var aiConversations_default = {
568
529
  const toolCallIds = toolCalls.map((x) => x.id);
569
530
  const toolMessages = await ctx.db.getRepository("aiToolMessages").find({
570
531
  filter: {
571
- sessionId,
572
- messageId,
532
+ sessionId: message.sessionId,
533
+ messageId: message.messageId,
573
534
  toolCallId: {
574
535
  $in: toolCallIds
575
536
  }
@@ -599,7 +560,12 @@ var aiConversations_default = {
599
560
  },
600
561
  async resumeToolCall(ctx, next) {
601
562
  var _a, _b, _c;
563
+ const userId = (_a = ctx.auth) == null ? void 0 : _a.user.id;
564
+ if (!userId) {
565
+ return ctx.throw(403);
566
+ }
602
567
  setupSSEHeaders(ctx);
568
+ const plugin = ctx.app.pm.get("ai");
603
569
  const { sessionId, messageId, model, webSearch } = ctx.action.params.values || {};
604
570
  if (!sessionId) {
605
571
  sendErrorResponse(ctx, "sessionId is required");
@@ -609,7 +575,7 @@ var aiConversations_default = {
609
575
  const conversation = await ctx.db.getRepository("aiConversations").findOne({
610
576
  filter: {
611
577
  sessionId,
612
- userId: (_a = ctx.auth) == null ? void 0 : _a.user.id
578
+ userId
613
579
  }
614
580
  });
615
581
  if (!conversation) {
@@ -623,7 +589,7 @@ var aiConversations_default = {
623
589
  }
624
590
  let message;
625
591
  if (messageId) {
626
- message = await ctx.db.getRepository("aiConversations.messages", sessionId).findOne({
592
+ message = await ctx.db.getRepository("aiMessages").findOne({
627
593
  filter: {
628
594
  messageId
629
595
  }
@@ -642,16 +608,16 @@ var aiConversations_default = {
642
608
  sendErrorResponse(ctx, "No tool calls found");
643
609
  return next();
644
610
  }
645
- const aiEmployee = new import_ai_employee.AIEmployee(
611
+ const aiEmployee = new import_ai_employee.AIEmployee({
646
612
  ctx,
647
613
  employee,
648
614
  sessionId,
649
- (_b = conversation.options) == null ? void 0 : _b.systemMessage,
650
- (_c = conversation.options) == null ? void 0 : _c.skillSettings,
615
+ systemMessage: (_b = conversation.options) == null ? void 0 : _b.systemMessage,
616
+ skillSettings: (_c = conversation.options) == null ? void 0 : _c.skillSettings,
651
617
  webSearch,
652
618
  model
653
- );
654
- const userDecisions = await aiEmployee.getUserDecisions(messageId);
619
+ });
620
+ const userDecisions = await plugin.aiConversationsManager.getUserDecisions(messageId);
655
621
  await aiEmployee.stream({
656
622
  userDecisions
657
623
  });
@@ -29,7 +29,10 @@ export type AIChatContext = {
29
29
  tool_call_id?: string;
30
30
  tool_calls?: AIToolCall[];
31
31
  }[];
32
- decisions?: UserDecision[];
32
+ decisions?: {
33
+ interruptId?: string;
34
+ decisions: UserDecision[];
35
+ };
33
36
  tools?: any[];
34
37
  middleware?: any[];
35
38
  structuredOutput?: {
@@ -48,7 +51,10 @@ export type AIMessageRemoveOptions = {
48
51
  };
49
52
  export type AIChatContextOptions = {
50
53
  userMessages?: AIMessageInput[];
51
- userDecisions?: UserDecision[];
54
+ userDecisions?: {
55
+ interruptId?: string;
56
+ decisions: UserDecision[];
57
+ };
52
58
  tools?: any[];
53
59
  middleware?: any[];
54
60
  getSystemPrompt?: (userMessages: AIMessageInput[]) => Promise<string>;
@@ -10,6 +10,7 @@ export type AIMessage = {
10
10
  messageId: string;
11
11
  sessionId: string;
12
12
  role: string;
13
+ createdAt?: string | Date;
13
14
  content: AIMessageContent;
14
15
  toolCalls?: AIToolCall[];
15
16
  attachments?: unknown[];
@@ -44,8 +45,14 @@ export type AIMessageMetadata = {
44
45
  autoCallTools?: string[];
45
46
  autoCall?: boolean;
46
47
  interrupted?: boolean;
48
+ subAgentConversations?: SubAgentConversationMetadata[];
47
49
  [key: string]: unknown;
48
50
  };
51
+ export type SubAgentConversationMetadata = {
52
+ sessionId: string;
53
+ toolCallId: string;
54
+ status: 'pending' | 'completed';
55
+ };
49
56
  export type AIToolMessage = {
50
57
  id: string;
51
58
  sessionId: string;
@@ -8,13 +8,16 @@
8
8
  */
9
9
  import { Model } from '@nocobase/database';
10
10
  import { Context } from '@nocobase/actions';
11
+ import { ToolsEntry } from '@nocobase/ai';
11
12
  export declare function sendSSEError(ctx: Context, error: Error | string, errorName?: string): void;
12
13
  export declare function stripToolCallTags(content: string): string | null;
13
14
  export declare function parseResponseMessage(row: Model): {
14
15
  key: any;
16
+ createdAt: any;
15
17
  content: any;
16
18
  role: any;
17
19
  };
18
20
  export declare function encodeLocalFile(url: string): Promise<string>;
19
21
  export declare function encodeFile(ctx: Context, url: string): Promise<string>;
20
22
  export declare function parseVariables(ctx: Context, value: string): Promise<any>;
23
+ export declare const buildTool: (toolsEntry: ToolsEntry) => import("@langchain/core/dist/tools").DynamicTool<any>;
@@ -36,6 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
37
  var utils_exports = {};
38
38
  __export(utils_exports, {
39
+ buildTool: () => buildTool,
39
40
  encodeFile: () => encodeFile,
40
41
  encodeLocalFile: () => encodeLocalFile,
41
42
  parseResponseMessage: () => parseResponseMessage,
@@ -48,6 +49,7 @@ var import_path = __toESM(require("path"));
48
49
  var import_fs = __toESM(require("fs"));
49
50
  var import_axios = __toESM(require("axios"));
50
51
  var import_utils = require("@nocobase/utils");
52
+ var import_langchain = require("langchain");
51
53
  function sendSSEError(ctx, error, errorName) {
52
54
  const body = typeof error === "string" ? error : error.message || "Unknown error";
53
55
  if (!ctx.res.headersSent) {
@@ -70,7 +72,7 @@ function stripToolCallTags(content) {
70
72
  return content.replace(/<[||]tool▁(?:calls▁begin|calls▁end|call▁begin|call▁end|sep)[||]>/g, "");
71
73
  }
72
74
  function parseResponseMessage(row) {
73
- const { content: rawContent, messageId, metadata, role, toolCalls, attachments, workContext } = row;
75
+ const { content: rawContent, messageId, metadata, role, toolCalls, attachments, workContext, createdAt } = row;
74
76
  const content = {
75
77
  ...rawContent ?? {},
76
78
  content: stripToolCallTags(rawContent == null ? void 0 : rawContent.content),
@@ -84,6 +86,7 @@ function parseResponseMessage(row) {
84
86
  }
85
87
  return {
86
88
  key: messageId,
89
+ createdAt,
87
90
  content,
88
91
  role
89
92
  };
@@ -151,8 +154,29 @@ async function parseVariables(ctx, value) {
151
154
  $nDate
152
155
  });
153
156
  }
157
+ const noWriter = (chunk) => console.warn(`No writer in tools runtime, chunk:[${chunk}]`);
158
+ const buildTool = (toolsEntry) => {
159
+ const {
160
+ invoke,
161
+ definition: { name, description, schema }
162
+ } = toolsEntry;
163
+ return (0, import_langchain.tool)(
164
+ (input, config) => {
165
+ const { context, toolCall } = config;
166
+ const writer = config["writer"] ?? noWriter;
167
+ return invoke(context.ctx, input, { toolCallId: toolCall.id, writer });
168
+ },
169
+ {
170
+ name,
171
+ description,
172
+ schema,
173
+ returnDirect: false
174
+ }
175
+ );
176
+ };
154
177
  // Annotate the CommonJS export names for ESM import in node:
155
178
  0 && (module.exports = {
179
+ buildTool,
156
180
  encodeFile,
157
181
  encodeLocalFile,
158
182
  parseResponseMessage,
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Create AI employees with diverse skills to collaborate with humans, build systems, and handle business operations.",
7
7
  "description.ru-RU": "Поддержка интеграции с AI-сервисами: предоставляются AI-узлы для рабочих процессов, расширяя возможности бизнес-обработки.",
8
8
  "description.zh-CN": "创建各种技能的 AI 员工,与人类协同,搭建系统,处理业务。",
9
- "version": "2.1.0-alpha.13",
9
+ "version": "2.1.0-alpha.14",
10
10
  "main": "dist/server/index.js",
11
11
  "homepage": "https://docs.nocobase.com/handbook/action-ai",
12
12
  "homepage.ru-RU": "https://docs-ru.nocobase.com/handbook/action-ai",
@@ -22,7 +22,9 @@
22
22
  "@nocobase/ai": "2.x",
23
23
  "@nocobase/client": "2.x",
24
24
  "@nocobase/flow-engine": "2.x",
25
+ "@nocobase/plugin-acl": "2.x",
25
26
  "@nocobase/plugin-data-source-manager": "2.x",
27
+ "@nocobase/plugin-file-manager": "2.x",
26
28
  "@nocobase/plugin-workflow": "2.x",
27
29
  "@nocobase/server": "2.x",
28
30
  "@nocobase/test": "2.x"
@@ -59,5 +61,5 @@
59
61
  "keywords": [
60
62
  "AI"
61
63
  ],
62
- "gitHead": "2807a8948412d9c235115a31a81a66f7c82dd173"
64
+ "gitHead": "d8735b541de0ff9557bba704de49c799b4962672"
63
65
  }