plugin-agent-orchestrator 1.0.5 → 1.0.13

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.
@@ -34,6 +34,90 @@ var import_prebuilt = require("@langchain/langgraph/prebuilt");
34
34
  var import_tools = require("@langchain/core/tools");
35
35
  var import_messages = require("@langchain/core/messages");
36
36
  const ORCHESTRATOR_DEPTH_KEY = "__orchestratorDepth";
37
+ function sanitizeToolPart(value) {
38
+ return (value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
39
+ }
40
+ function buildDelegateToolName(leaderUsername, subAgentUsername) {
41
+ return `delegate_${sanitizeToolPart(leaderUsername)}_to_${sanitizeToolPart(subAgentUsername)}`;
42
+ }
43
+ function isDelegateToolName(toolName) {
44
+ return toolName.startsWith("delegate_to_") || toolName.startsWith("delegate_") && toolName.includes("_to_");
45
+ }
46
+ function createDelegateToolOptions(plugin, options) {
47
+ const { leaderUsername, subAgentUsername, subAgentEmployee, maxDepth, timeout, toolName, legacyAlias, llmService, model } = options;
48
+ const toolDescription = [
49
+ `Delegate a task from "${leaderUsername}" to the AI Employee "${subAgentEmployee.nickname || subAgentUsername}".`,
50
+ legacyAlias ? "This is a backward-compatible alias for existing skill assignments." : "",
51
+ subAgentEmployee.about ? `Specialist profile: ${subAgentEmployee.about.substring(0, 200)}` : "",
52
+ "The sub-agent will execute the task independently and return its final answer."
53
+ ].filter(Boolean).join(" ");
54
+ return {
55
+ scope: "CUSTOM",
56
+ execution: "backend",
57
+ defaultPermission: "ALLOW",
58
+ silence: false,
59
+ introduction: {
60
+ title: `[${leaderUsername}] ${subAgentEmployee.nickname || subAgentUsername}${legacyAlias ? " (legacy)" : ""}`,
61
+ about: toolDescription
62
+ },
63
+ definition: {
64
+ name: toolName,
65
+ description: toolDescription,
66
+ schema: import_zod.z.object({
67
+ task: import_zod.z.string().describe("The detailed task description for the sub-agent to execute."),
68
+ context: import_zod.z.string().optional().describe("Optional additional context to help the sub-agent understand the task better.")
69
+ })
70
+ },
71
+ invoke: async (ctx, args, id) => {
72
+ const callingEmployee = resolveCallingEmployee(ctx);
73
+ if (callingEmployee && callingEmployee !== leaderUsername) {
74
+ await logDelegation(ctx, plugin, {
75
+ leaderUsername,
76
+ subAgentUsername,
77
+ toolName,
78
+ task: args.task,
79
+ context: args.context,
80
+ result: "",
81
+ status: "error",
82
+ depth: ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0,
83
+ durationMs: 0,
84
+ error: `Employee "${callingEmployee}" is not authorized to use this delegation rule.`
85
+ });
86
+ return {
87
+ status: "error",
88
+ content: `Employee "${callingEmployee}" is not authorized to delegate to "${subAgentUsername}". Configure an orchestration rule first.`
89
+ };
90
+ }
91
+ return invokeDelegateTask(ctx, plugin, {
92
+ leaderUsername,
93
+ subAgentUsername,
94
+ subAgentEmployee,
95
+ task: args.task,
96
+ context: args.context,
97
+ maxDepth: maxDepth ?? 1,
98
+ timeout: timeout ?? 12e4,
99
+ toolCallId: id,
100
+ toolName,
101
+ llmService,
102
+ model
103
+ });
104
+ }
105
+ };
106
+ }
107
+ function resolveCallingEmployee(ctx) {
108
+ var _a, _b, _c;
109
+ const raw = ctx._currentAIEmployee || ((_a = ctx.state) == null ? void 0 : _a.currentAIEmployee) || ((_c = (_b = ctx.runtime) == null ? void 0 : _b.context) == null ? void 0 : _c.currentAIEmployee);
110
+ if (!raw) return null;
111
+ return typeof raw === "string" ? raw : raw.username;
112
+ }
113
+ function truncateText(value, maxLen) {
114
+ const text = typeof value === "string" ? value : value == null ? "" : JSON.stringify(value);
115
+ return text.length > maxLen ? `${text.slice(0, maxLen)}
116
+ ...[truncated]` : text;
117
+ }
118
+ function nowIso() {
119
+ return (/* @__PURE__ */ new Date()).toISOString();
120
+ }
37
121
  function createDelegateToolsProvider(plugin) {
38
122
  return async (register) => {
39
123
  try {
@@ -43,68 +127,59 @@ function createDelegateToolsProvider(plugin) {
43
127
  filter: { enabled: true }
44
128
  });
45
129
  if (!(configs == null ? void 0 : configs.length)) return;
46
- const leadersByTool = /* @__PURE__ */ new Map();
130
+ const employeeCache = /* @__PURE__ */ new Map();
131
+ const tools = [];
132
+ const configsBySubAgent = /* @__PURE__ */ new Map();
47
133
  for (const config of configs) {
48
- const toolName = `delegate_to_${config.subAgentUsername.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
49
- if (!leadersByTool.has(toolName)) {
50
- leadersByTool.set(toolName, /* @__PURE__ */ new Set());
51
- }
52
- leadersByTool.get(toolName).add(config.leaderUsername);
134
+ const items = configsBySubAgent.get(config.subAgentUsername) || [];
135
+ items.push(config);
136
+ configsBySubAgent.set(config.subAgentUsername, items);
53
137
  }
54
- const seenSubAgents = /* @__PURE__ */ new Set();
55
138
  for (const config of configs) {
56
139
  const { leaderUsername, subAgentUsername, maxDepth, timeout } = config;
57
- if (seenSubAgents.has(subAgentUsername)) continue;
58
- seenSubAgents.add(subAgentUsername);
59
- const subAgentEmployee = await plugin.db.getRepository("aiEmployees").findOne({
60
- filter: { username: subAgentUsername }
61
- });
62
- if (!subAgentEmployee) continue;
63
- const toolName = `delegate_to_${subAgentUsername.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
64
- const toolDescription = [
65
- `Delegate a task to the AI Employee "${subAgentEmployee.nickname || subAgentUsername}".`,
66
- subAgentEmployee.about ? `Specialist profile: ${subAgentEmployee.about.substring(0, 200)}` : "",
67
- "The sub-agent will execute the task independently and return its final answer."
68
- ].filter(Boolean).join(" ");
69
- const allowedLeaders = leadersByTool.get(toolName);
70
- register.registerTools({
71
- scope: "CUSTOM",
72
- execution: "backend",
73
- defaultPermission: "ALLOW",
74
- silence: false,
75
- introduction: {
76
- title: `[Sub-Agent] ${subAgentEmployee.nickname || subAgentUsername}`,
77
- about: toolDescription
78
- },
79
- definition: {
80
- name: toolName,
81
- description: toolDescription,
82
- schema: import_zod.z.object({
83
- task: import_zod.z.string().describe("The detailed task description for the sub-agent to execute."),
84
- context: import_zod.z.string().optional().describe("Optional additional context to help the sub-agent understand the task better.")
85
- })
86
- },
87
- invoke: async (ctx, args, id) => {
88
- var _a, _b;
89
- const callingEmployee = ((_a = ctx._currentAIEmployee) == null ? void 0 : _a.username) || ((_b = ctx.state) == null ? void 0 : _b.currentAIEmployee);
90
- if (callingEmployee && !allowedLeaders.has(callingEmployee)) {
91
- return {
92
- status: "error",
93
- content: `Employee "${callingEmployee}" is not authorized to delegate to "${subAgentUsername}". Configure an orchestration rule first.`
94
- };
95
- }
96
- return invokeDelegateTask(ctx, plugin, {
97
- leaderUsername: callingEmployee || Array.from(allowedLeaders)[0] || "",
98
- subAgentUsername,
99
- subAgentEmployee,
100
- task: args.task,
101
- context: args.context,
102
- maxDepth: maxDepth ?? 1,
103
- timeout: timeout ?? 12e4,
104
- toolCallId: id
105
- });
140
+ let subAgentEmployee = employeeCache.get(subAgentUsername);
141
+ if (!subAgentEmployee) {
142
+ subAgentEmployee = await plugin.db.getRepository("aiEmployees").findOne({
143
+ filter: { username: subAgentUsername }
144
+ });
145
+ if (subAgentEmployee) {
146
+ employeeCache.set(subAgentUsername, subAgentEmployee);
106
147
  }
107
- });
148
+ }
149
+ if (!subAgentEmployee) continue;
150
+ const toolName = buildDelegateToolName(leaderUsername, subAgentUsername);
151
+ tools.push(createDelegateToolOptions(plugin, {
152
+ leaderUsername,
153
+ subAgentUsername,
154
+ subAgentEmployee,
155
+ maxDepth,
156
+ timeout,
157
+ toolName,
158
+ llmService: config.llmService,
159
+ model: config.model
160
+ }));
161
+ }
162
+ for (const [subAgentUsername, items] of configsBySubAgent.entries()) {
163
+ if (items.length !== 1) continue;
164
+ const config = items[0];
165
+ const subAgentEmployee = employeeCache.get(subAgentUsername);
166
+ if (!subAgentEmployee) continue;
167
+ const legacyToolName = `delegate_to_${sanitizeToolPart(subAgentUsername)}`;
168
+ if (tools.some((tool) => tool.definition.name === legacyToolName)) continue;
169
+ tools.push(createDelegateToolOptions(plugin, {
170
+ leaderUsername: config.leaderUsername,
171
+ subAgentUsername,
172
+ subAgentEmployee,
173
+ maxDepth: config.maxDepth,
174
+ timeout: config.timeout,
175
+ toolName: legacyToolName,
176
+ legacyAlias: true,
177
+ llmService: config.llmService,
178
+ model: config.model
179
+ }));
180
+ }
181
+ if (tools.length) {
182
+ register.registerTools(tools);
108
183
  }
109
184
  } catch (e) {
110
185
  plugin.app.log.error("[AgentOrchestrator] Failed to register delegate tools", e);
@@ -112,24 +187,66 @@ function createDelegateToolsProvider(plugin) {
112
187
  };
113
188
  }
114
189
  async function invokeDelegateTask(ctx, plugin, options) {
115
- var _a, _b;
116
- const { leaderUsername, subAgentUsername, subAgentEmployee, task, context, maxDepth, timeout, toolCallId } = options;
190
+ var _a, _b, _c, _d, _e;
191
+ const { leaderUsername, subAgentUsername, subAgentEmployee, task, context, maxDepth, timeout, toolCallId, toolName, llmService, model } = options;
117
192
  const currentDepth = ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0;
118
193
  if (currentDepth >= maxDepth) {
194
+ await logDelegation(ctx, plugin, {
195
+ leaderUsername,
196
+ subAgentUsername,
197
+ toolName,
198
+ task,
199
+ context,
200
+ result: "",
201
+ status: "error",
202
+ depth: currentDepth,
203
+ durationMs: 0,
204
+ error: `Delegation depth limit reached (${currentDepth}/${maxDepth}).`
205
+ });
119
206
  return {
120
207
  status: "error",
121
208
  content: `Delegation depth limit reached (${currentDepth}/${maxDepth}). Sub-agent "${subAgentUsername}" cannot delegate further.`
122
209
  };
123
210
  }
124
211
  const startTime = Date.now();
212
+ const trace = [
213
+ {
214
+ type: "start",
215
+ at: nowIso(),
216
+ title: `Delegation started: ${leaderUsername} -> ${subAgentUsername}`,
217
+ content: task
218
+ }
219
+ ];
220
+ const logRecord = await logDelegation(ctx, plugin, {
221
+ leaderUsername,
222
+ subAgentUsername,
223
+ toolName,
224
+ task,
225
+ context,
226
+ result: "",
227
+ status: "running",
228
+ depth: currentDepth,
229
+ durationMs: 0,
230
+ trace
231
+ });
125
232
  try {
126
233
  const aiPlugin = ctx.app.pm.get("ai");
127
234
  if (!aiPlugin) {
128
235
  throw new Error("Plugin AI is not installed or enabled");
129
236
  }
130
- const modelSettings = subAgentEmployee.modelSettings;
237
+ let modelSettings = subAgentEmployee.modelSettings;
238
+ if (llmService && model) {
239
+ modelSettings = { llmService, model };
240
+ }
131
241
  if (!(modelSettings == null ? void 0 : modelSettings.llmService) || !(modelSettings == null ? void 0 : modelSettings.model)) {
132
- throw new Error(`Sub-agent "${subAgentUsername}" has no LLM model configured. Please configure a model in the AI Employee settings.`);
242
+ const leaderEmployee = await plugin.db.getRepository("aiEmployees").findOne({
243
+ filter: { username: leaderUsername }
244
+ });
245
+ const dynamicModel = (_c = (_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) == null ? void 0 : _c.model;
246
+ modelSettings = (leaderEmployee == null ? void 0 : leaderEmployee.modelSettings) || dynamicModel;
247
+ if (!(modelSettings == null ? void 0 : modelSettings.llmService) || !(modelSettings == null ? void 0 : modelSettings.model)) {
248
+ throw new Error(`Sub-agent "${subAgentUsername}" has no LLM model configured (and leader fallback failed). Please configure a model in the Orchestrator Config or AI Employee settings.`);
249
+ }
133
250
  }
134
251
  const { provider } = await aiPlugin.aiManager.getLLMService({
135
252
  llmService: modelSettings.llmService,
@@ -138,27 +255,54 @@ async function invokeDelegateTask(ctx, plugin, options) {
138
255
  const chatModel = provider.createModel();
139
256
  const coreToolsManager = ctx.app.aiManager.toolsManager;
140
257
  const allTools = await coreToolsManager.listTools();
141
- const employeeSkills = (((_a = subAgentEmployee.skillSettings) == null ? void 0 : _a.skills) ?? []).map((s) => typeof s === "string" ? s : s.name).filter(Boolean);
258
+ const employeeSkills = (((_d = subAgentEmployee.skillSettings) == null ? void 0 : _d.skills) ?? []).map((s) => typeof s === "string" ? s : s.name).filter(Boolean);
142
259
  const langchainTools = [];
143
260
  for (const toolEntry of allTools) {
144
- const toolName = toolEntry.definition.name;
145
- if (!toolName) continue;
146
- if (!employeeSkills.includes(toolName) || toolName.startsWith("delegate_to_")) {
261
+ const toolName2 = toolEntry.definition.name;
262
+ if (!toolName2) continue;
263
+ if (!employeeSkills.includes(toolName2) || isDelegateToolName(toolName2)) {
147
264
  continue;
148
265
  }
149
266
  langchainTools.push(
150
267
  new import_tools.DynamicStructuredTool({
151
- name: toolName.replace(/[^a-zA-Z0-9_-]/g, "_"),
152
- description: toolEntry.definition.description || toolName,
268
+ name: toolName2.replace(/[^a-zA-Z0-9_-]/g, "_"),
269
+ description: toolEntry.definition.description || toolName2,
153
270
  schema: toolEntry.definition.schema || import_zod.z.object({}),
154
271
  func: async (toolArgs) => {
155
272
  const invokeCtx = Object.create(ctx);
156
273
  invokeCtx[ORCHESTRATOR_DEPTH_KEY] = currentDepth + 1;
157
- const res = await toolEntry.invoke(invokeCtx, toolArgs, `orch-${toolCallId}`);
158
- if ((res == null ? void 0 : res.status) === "error") {
159
- throw new Error(`Tool <${toolName}> failed: ${res.content}`);
274
+ trace.push({
275
+ type: "tool_call",
276
+ at: nowIso(),
277
+ title: `Calling tool: ${toolEntry.definition.name}`,
278
+ toolName: toolEntry.definition.name,
279
+ args: toolArgs
280
+ });
281
+ try {
282
+ const res = await toolEntry.invoke(invokeCtx, toolArgs, `orch-${toolCallId}`);
283
+ trace.push({
284
+ type: "tool_result",
285
+ at: nowIso(),
286
+ title: `Tool finished: ${toolEntry.definition.name}`,
287
+ toolName: toolEntry.definition.name,
288
+ status: (res == null ? void 0 : res.status) || "success",
289
+ content: truncateText((res == null ? void 0 : res.content) ?? res, 2e3)
290
+ });
291
+ if ((res == null ? void 0 : res.status) === "error") {
292
+ throw new Error(`Tool <${toolEntry.definition.name}> failed: ${res.content}`);
293
+ }
294
+ return typeof (res == null ? void 0 : res.content) === "string" ? res.content : JSON.stringify(res);
295
+ } catch (e) {
296
+ trace.push({
297
+ type: "tool_error",
298
+ at: nowIso(),
299
+ title: `Tool failed: ${toolEntry.definition.name}`,
300
+ toolName: toolEntry.definition.name,
301
+ status: "error",
302
+ content: e.message
303
+ });
304
+ throw e;
160
305
  }
161
- return typeof (res == null ? void 0 : res.content) === "string" ? res.content : JSON.stringify(res);
162
306
  }
163
307
  })
164
308
  );
@@ -168,7 +312,7 @@ async function invokeDelegateTask(ctx, plugin, options) {
168
312
  llm: chatModel,
169
313
  tools: langchainTools
170
314
  });
171
- const systemPrompt = ((_b = subAgentEmployee.chatSettings) == null ? void 0 : _b.systemPrompt) || subAgentEmployee.bio || `You are an AI assistant named "${subAgentEmployee.nickname || subAgentUsername}". ${subAgentEmployee.about || ""}`;
315
+ const systemPrompt = ((_e = subAgentEmployee.chatSettings) == null ? void 0 : _e.systemPrompt) || subAgentEmployee.bio || `You are an AI assistant named "${subAgentEmployee.nickname || subAgentUsername}". ${subAgentEmployee.about || ""}`;
172
316
  const combinedTask = context ? `Task: ${task}
173
317
 
174
318
  Context Provided:
@@ -178,15 +322,27 @@ ${context}` : `Task: ${task}`;
178
322
  invokePromise,
179
323
  createTimeout(timeout, subAgentUsername, abortController)
180
324
  ]);
181
- const content = result || "Sub-agent completed the task but produced no output.";
325
+ const content = result.content || "Sub-agent completed the task but produced no output.";
326
+ trace.push({
327
+ type: "finish",
328
+ at: nowIso(),
329
+ title: `Delegation finished: ${subAgentUsername}`,
330
+ status: "success",
331
+ content: truncateText(content, 2e3)
332
+ });
182
333
  await logDelegation(ctx, plugin, {
334
+ id: logRecord == null ? void 0 : logRecord.id,
183
335
  leaderUsername,
184
336
  subAgentUsername,
337
+ toolName,
185
338
  task,
339
+ context,
186
340
  result: content,
187
341
  status: "success",
188
342
  depth: currentDepth,
189
- durationMs: Date.now() - startTime
343
+ durationMs: Date.now() - startTime,
344
+ trace,
345
+ messages: result.messages
190
346
  });
191
347
  return {
192
348
  status: "success",
@@ -195,15 +351,29 @@ ${context}` : `Task: ${task}`;
195
351
  } catch (e) {
196
352
  plugin.app.log.error(`[AgentOrchestrator] Sub-agent ${subAgentUsername} failed`, e);
197
353
  await logDelegation(ctx, plugin, {
354
+ id: logRecord == null ? void 0 : logRecord.id,
198
355
  leaderUsername,
199
356
  subAgentUsername,
357
+ toolName,
200
358
  task,
359
+ context,
201
360
  result: "",
202
361
  status: "error",
203
362
  depth: currentDepth,
204
363
  durationMs: Date.now() - startTime,
205
- error: e.message
206
- }).catch(() => {
364
+ error: e.message,
365
+ trace: [
366
+ ...trace,
367
+ {
368
+ type: "error",
369
+ at: nowIso(),
370
+ title: `Delegation failed: ${subAgentUsername}`,
371
+ status: "error",
372
+ content: e.message
373
+ }
374
+ ]
375
+ }).catch((logErr) => {
376
+ plugin.app.log.warn("[AgentOrchestrator] Failed to save error log for delegation", logErr);
207
377
  });
208
378
  return {
209
379
  status: "error",
@@ -215,45 +385,89 @@ async function logDelegation(ctx, plugin, data) {
215
385
  var _a, _b, _c, _d, _e;
216
386
  try {
217
387
  const logsRepo = plugin.db.getRepository("orchestratorLogs");
218
- if (!logsRepo) return;
219
- await logsRepo.create({
388
+ if (!logsRepo) {
389
+ plugin.app.log.warn("[AgentOrchestrator] orchestratorLogs repository not found \u2014 skipping log");
390
+ return;
391
+ }
392
+ let userId;
393
+ try {
394
+ userId = ((_b = (_a = ctx.auth) == null ? void 0 : _a.user) == null ? void 0 : _b.id) || ((_d = (_c = ctx.state) == null ? void 0 : _c.currentUser) == null ? void 0 : _d.id);
395
+ } catch {
396
+ }
397
+ const values = {
398
+ leaderUsername: data.leaderUsername,
399
+ subAgentUsername: data.subAgentUsername,
400
+ toolName: data.toolName,
401
+ task: truncateText(data.task, 1e4),
402
+ context: truncateText(data.context || "", 1e4),
403
+ result: truncateText(data.result || "", 5e4),
404
+ status: data.status,
405
+ depth: data.depth,
406
+ durationMs: data.durationMs,
407
+ error: truncateText(data.error || "", 1e4),
408
+ trace: data.trace || [],
409
+ messages: data.messages || [],
410
+ userId,
411
+ updatedAt: /* @__PURE__ */ new Date()
412
+ };
413
+ if (data.id) {
414
+ await logsRepo.update({
415
+ filterByTk: data.id,
416
+ values
417
+ });
418
+ return { id: data.id };
419
+ }
420
+ const record = await logsRepo.create({
220
421
  values: {
221
- leaderUsername: data.leaderUsername,
222
- subAgentUsername: data.subAgentUsername,
223
- toolName: `delegate_to_${data.subAgentUsername}`,
224
- task: data.task.substring(0, 2e3),
225
- result: data.result.substring(0, 5e3),
226
- status: data.status,
227
- depth: data.depth,
228
- durationMs: data.durationMs,
229
- error: (_a = data.error) == null ? void 0 : _a.substring(0, 2e3),
230
- userId: ((_c = (_b = ctx.auth) == null ? void 0 : _b.user) == null ? void 0 : _c.id) || ((_e = (_d = ctx.state) == null ? void 0 : _d.currentUser) == null ? void 0 : _e.id)
422
+ ...values,
423
+ createdAt: /* @__PURE__ */ new Date()
231
424
  }
232
425
  });
426
+ return ((_e = record == null ? void 0 : record.toJSON) == null ? void 0 : _e.call(record)) || record;
233
427
  } catch (e) {
234
428
  plugin.app.log.warn("[AgentOrchestrator] Failed to log delegation event", e);
235
429
  }
236
430
  }
237
431
  async function executeAgent(executor, systemPrompt, task, signal) {
238
- const streamOptions = { recursionLimit: 50, streamMode: "messages" };
432
+ const config = { recursionLimit: 50 };
239
433
  if (signal) {
240
- streamOptions.signal = signal;
434
+ config.signal = signal;
241
435
  }
242
- const stream = await executor.stream(
436
+ const finalState = await executor.invoke(
243
437
  {
244
438
  messages: [new import_messages.SystemMessage(systemPrompt), new import_messages.HumanMessage(task)]
245
439
  },
246
- streamOptions
440
+ config
247
441
  );
248
- let aiContentCache = "";
249
- for await (const chunk of stream) {
250
- if (signal == null ? void 0 : signal.aborted) break;
251
- const [message] = chunk;
252
- if (message.getType() === "ai" && message.content) {
253
- aiContentCache += message.content.toString();
254
- }
442
+ const messages = (finalState == null ? void 0 : finalState.messages) || [];
443
+ const lastAIMessage = [...messages].reverse().find((m) => m.getType() === "ai");
444
+ if (!lastAIMessage || !lastAIMessage.content) {
445
+ return { content: "", messages: serializeMessages(messages) };
446
+ }
447
+ let content = "";
448
+ if (typeof lastAIMessage.content === "string") {
449
+ content = lastAIMessage.content;
450
+ } else if (Array.isArray(lastAIMessage.content)) {
451
+ content = lastAIMessage.content.map((c) => c.text || JSON.stringify(c)).join("\n");
452
+ } else {
453
+ content = String(lastAIMessage.content);
255
454
  }
256
- return aiContentCache || "";
455
+ return { content, messages: serializeMessages(messages) };
456
+ }
457
+ function serializeMessages(messages) {
458
+ return (messages || []).map((message, index) => {
459
+ const type = typeof message.getType === "function" ? message.getType() : message.type;
460
+ return {
461
+ index,
462
+ type,
463
+ name: message.name,
464
+ content: truncateText(message.content, 1e4),
465
+ toolCalls: message.tool_calls || message.toolCalls || [],
466
+ toolCallId: message.tool_call_id,
467
+ additionalKwargs: message.additional_kwargs,
468
+ responseMetadata: message.response_metadata
469
+ };
470
+ });
257
471
  }
258
472
  function createTimeout(ms, agentName, abortController) {
259
473
  return new Promise(
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "displayName.zh-CN": "代理协调器",
5
5
  "displayName.vi-VN": "Điều phối Agent",
6
6
  "description": "Hierarchical Multi-Agent orchestration for NocoBase AI Employees. Enables Leader agents to delegate tasks to Sub-Agent employees without modifying core plugin-ai.",
7
- "version": "1.0.5",
7
+ "version": "1.0.13",
8
8
  "license": "Apache-2.0",
9
9
  "main": "dist/server/index.js",
10
10
  "keywords": [