@ai-setting/roy-agent-core 1.5.89 → 1.5.90

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 (26) hide show
  1. package/dist/env/agent/index.js +3 -3
  2. package/dist/env/event-source/index.js +8 -4
  3. package/dist/env/index.js +9 -9
  4. package/dist/env/llm/index.js +4 -2
  5. package/dist/env/session/index.js +3 -3
  6. package/dist/env/session/storage/index.js +2 -2
  7. package/dist/env/task/plugins/index.js +1 -1
  8. package/dist/env/workflow/engine/index.js +2 -2
  9. package/dist/env/workflow/index.js +3 -3
  10. package/dist/env/workflow/nodes/index.js +1 -1
  11. package/dist/index.js +119 -14
  12. package/dist/shared/@ai-setting/{roy-agent-core-r0m0at3x.js → roy-agent-core-0r4ndyn9.js} +119 -7
  13. package/dist/shared/@ai-setting/{roy-agent-core-fvfc7f6v.js → roy-agent-core-2c8eraxq.js} +62 -8
  14. package/dist/shared/@ai-setting/{roy-agent-core-h2d1s8yd.js → roy-agent-core-5ykms33a.js} +1 -1
  15. package/dist/shared/@ai-setting/{roy-agent-core-fgpnv7dt.js → roy-agent-core-8zjntsbb.js} +71 -28
  16. package/dist/shared/@ai-setting/{roy-agent-core-vneyghpg.js → roy-agent-core-ddq5hcp5.js} +1 -1
  17. package/dist/shared/@ai-setting/{roy-agent-core-qhhxx2x2.js → roy-agent-core-ds5f75pg.js} +2 -1
  18. package/dist/shared/@ai-setting/{roy-agent-core-3f6k060j.js → roy-agent-core-j0107ww1.js} +1 -1
  19. package/dist/shared/@ai-setting/{roy-agent-core-2q7cshpm.js → roy-agent-core-m683wd1n.js} +283 -15
  20. package/dist/shared/@ai-setting/{roy-agent-core-qbq3jgrn.js → roy-agent-core-rkz8r2sx.js} +1 -1
  21. package/dist/shared/@ai-setting/{roy-agent-core-c1j7ev4e.js → roy-agent-core-txwf64pd.js} +70 -0
  22. package/dist/shared/@ai-setting/{roy-agent-core-m3dkyprg.js → roy-agent-core-w0kb72ve.js} +7 -2
  23. package/dist/shared/@ai-setting/{roy-agent-core-hc20420t.js → roy-agent-core-z240ts1r.js} +27 -3
  24. package/dist/shared/@ai-setting/{roy-agent-core-q7sqeax6.js → roy-agent-core-zky9jse4.js} +163 -3
  25. package/package.json +1 -1
  26. /package/dist/shared/@ai-setting/{roy-agent-core-4f3976cd.js → roy-agent-core-k5hxvaf0.js} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  MemorySessionStore,
8
8
  SQLiteSessionStore
9
- } from "./roy-agent-core-q7sqeax6.js";
9
+ } from "./roy-agent-core-zky9jse4.js";
10
10
  import {
11
11
  envKeyToConfigKey
12
12
  } from "./roy-agent-core-qxhq8ven.js";
@@ -66,8 +66,38 @@ init_search_query_parser();
66
66
  import path from "path";
67
67
  import { z } from "zod";
68
68
  var logger = createLogger("session");
69
+ function sleep(ms) {
70
+ return new Promise((resolve) => setTimeout(resolve, ms));
71
+ }
72
+ function isBusyError(err) {
73
+ if (err == null)
74
+ return false;
75
+ const e = err;
76
+ if (typeof e.code === "string") {
77
+ if (/^SQLITE_(BUSY|LOCKED)$/i.test(e.code))
78
+ return true;
79
+ }
80
+ if (typeof e.errno === "number" && (e.errno === 5 || e.errno === 6)) {
81
+ return true;
82
+ }
83
+ const msg = e.message ?? "";
84
+ return /SQLiteError:\s+(database is locked|database table is locked)/i.test(msg);
85
+ }
86
+
87
+ class AddMessageLockExhaustedError extends Error {
88
+ kind = "lock_exhausted";
89
+ attempts;
90
+ cause;
91
+ constructor(attempts, cause) {
92
+ super(`Failed to add message after ${attempts} attempts: ${String(cause)}`);
93
+ this.name = "AddMessageLockExhaustedError";
94
+ this.attempts = attempts;
95
+ this.cause = cause;
96
+ }
97
+ }
69
98
 
70
99
  class SessionComponent extends BaseComponent {
100
+ static BACKOFFS_MS = [50, 100, 200];
71
101
  name = "session";
72
102
  version = "1.1.0";
73
103
  config;
@@ -323,14 +353,38 @@ class SessionComponent extends BaseComponent {
323
353
  async addMessage(sessionId, message) {
324
354
  const contentPreview = typeof message.content === "string" ? message.content.substring(0, 100) : JSON.stringify(message.content).substring(0, 100);
325
355
  logger.info(`[SessionComponent.addMessage] sessionId=${sessionId}, role=${message.role}, content="${contentPreview}"`);
326
- try {
327
- const messageId = await this.store?.addMessage(sessionId, message);
328
- logger.info(`[SessionComponent.addMessage] Success: messageId=${messageId}`);
329
- return messageId;
330
- } catch (error) {
331
- logger.error(`[SessionComponent] Failed to add message: ${error}`);
332
- return;
356
+ return this.addMessageWithRetry(sessionId, message);
357
+ }
358
+ async addMessageWithRetry(sessionId, message) {
359
+ const MAX_ATTEMPTS = SessionComponent.BACKOFFS_MS.length;
360
+ for (let attempt = 0;attempt < MAX_ATTEMPTS; attempt++) {
361
+ try {
362
+ const messageId = await this.store?.addMessage(sessionId, message);
363
+ if (attempt > 0) {
364
+ logger.info(`[SessionComponent.addMessage] Recovered after ${attempt + 1} attempts: messageId=${messageId}`);
365
+ } else {
366
+ logger.info(`[SessionComponent.addMessage] Success: messageId=${messageId}`);
367
+ }
368
+ return messageId;
369
+ } catch (error) {
370
+ if (!isBusyError(error)) {
371
+ logger.error(`[SessionComponent] Failed to add message (non-busy): ${error}`);
372
+ return;
373
+ }
374
+ const isLastAttempt = attempt === MAX_ATTEMPTS - 1;
375
+ if (isLastAttempt) {
376
+ logger.error(`[SessionComponent] Failed to add message after ${MAX_ATTEMPTS} attempts (busy): ${error}`);
377
+ throw new AddMessageLockExhaustedError(MAX_ATTEMPTS, error);
378
+ }
379
+ const backoffMs = SessionComponent.BACKOFFS_MS[attempt];
380
+ logger.warn(`[SessionComponent] SQLITE_BUSY on attempt ${attempt + 1}/${MAX_ATTEMPTS}, retrying in ${backoffMs}ms: ${error}`);
381
+ await sleep(backoffMs);
382
+ }
333
383
  }
384
+ return;
385
+ }
386
+ async addMessages(sessionId, messages) {
387
+ return this.store?.addMessages(sessionId, messages) ?? [];
334
388
  }
335
389
  async getMessages(sessionId, options) {
336
390
  const messages = await this.store?.getMessages(sessionId, options?.offset, options?.limit);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  invoke
3
- } from "./roy-agent-core-r0m0at3x.js";
3
+ } from "./roy-agent-core-0r4ndyn9.js";
4
4
  import {
5
5
  ContextError,
6
6
  ErrorCodes
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  withTimeout
3
- } from "./roy-agent-core-r0m0at3x.js";
3
+ } from "./roy-agent-core-0r4ndyn9.js";
4
4
  import {
5
5
  truncateOutputInline
6
6
  } from "./roy-agent-core-hxsbegfc.js";
@@ -16,7 +16,7 @@ import {
16
16
  } from "./roy-agent-core-ctdhjv68.js";
17
17
  import {
18
18
  SessionMessageConverter
19
- } from "./roy-agent-core-c1j7ev4e.js";
19
+ } from "./roy-agent-core-txwf64pd.js";
20
20
  import {
21
21
  safeParseToolArgs
22
22
  } from "./roy-agent-core-ce10b0ez.js";
@@ -115,23 +115,53 @@ function toLLMMessage(msg) {
115
115
  toolName = toolResult?.toolName;
116
116
  } else {
117
117
  const toolCallParts = msg.content.filter((part) => part.type === "tool-call");
118
- const contentParts = msg.content.filter((part) => part.type === "text").map((part) => part.text || "");
119
- content = contentParts.join(`
118
+ const hasMultimodalPart = msg.content.some((part) => part.type === "image" || part.type === "file");
119
+ if (hasMultimodalPart) {
120
+ const llmContentParts = [];
121
+ for (const part of msg.content) {
122
+ if (part.type === "text") {
123
+ llmContentParts.push({ type: "text", text: part.text || "" });
124
+ } else if (part.type === "image") {
125
+ llmContentParts.push({ type: "image", image: part.image });
126
+ } else if (part.type === "file") {
127
+ llmContentParts.push({
128
+ type: "file",
129
+ file: part.data ?? part.file,
130
+ mediaType: part.mediaType || "application/octet-stream"
131
+ });
132
+ }
133
+ }
134
+ if (msg.role === "assistant" && toolCallParts.length > 0) {
135
+ for (const part of toolCallParts) {
136
+ const argsString = typeof part.input === "string" ? part.input : JSON.stringify(part.input || {});
137
+ toolCalls = (toolCalls ?? []).concat([{
138
+ id: part.toolCallId,
139
+ name: part.toolName || "unknown",
140
+ arguments: argsString,
141
+ function: { name: part.toolName || "unknown", arguments: argsString }
142
+ }]);
143
+ }
144
+ }
145
+ content = llmContentParts;
146
+ } else {
147
+ const contentParts = msg.content.filter((part) => part.type === "text").map((part) => part.text || "");
148
+ content = contentParts.join(`
120
149
  `);
121
- if (msg.role === "assistant" && toolCallParts.length > 0) {
122
- toolCalls = toolCallParts.map((part) => {
123
- const argsString = typeof part.input === "string" ? part.input : JSON.stringify(part.input || {});
124
- const toolName2 = part.toolName || "unknown";
125
- return {
126
- id: part.toolCallId,
127
- name: toolName2,
128
- arguments: argsString,
129
- function: {
150
+ if (msg.role === "assistant" && toolCallParts.length > 0) {
151
+ toolCalls = toolCallParts.map((part) => {
152
+ const argsString = typeof part.input === "string" ? part.input : JSON.stringify(part.input || {});
153
+ const toolName2 = part.toolName || "unknown";
154
+ return {
155
+ id: part.toolCallId,
130
156
  name: toolName2,
131
- arguments: argsString
132
- }
133
- };
134
- });
157
+ arguments: argsString,
158
+ function: {
159
+ name: toolName2,
160
+ arguments: argsString
161
+ }
162
+ };
163
+ });
164
+ }
135
165
  }
136
166
  }
137
167
  } else {
@@ -550,7 +580,8 @@ class AgentComponent extends BaseComponent {
550
580
  throw new Error(`Agent not found: ${agentName}`);
551
581
  }
552
582
  const runId = `${agentName}:${++this.runCounter}`;
553
- logger.info(`Starting agent run: ${agentName} (runId=${runId})`, { query: query.substring(0, 100) });
583
+ const querySummary = typeof query === "string" ? query.substring(0, 100) : query.filter((p) => p.type === "text").map((p) => p.text).join(" ").substring(0, 100) || "[multimodal query]";
584
+ logger.info(`Starting agent run: ${agentName} (runId=${runId})`, { query: querySummary });
554
585
  agent.status = "running";
555
586
  this.aborted.set(runId, false);
556
587
  const abortController = new AbortController;
@@ -559,24 +590,25 @@ class AgentComponent extends BaseComponent {
559
590
  this.doomLoopCaches.set(runId, new Map);
560
591
  }
561
592
  await this.resolveSystemPrompt(agent, agentName);
593
+ let resolvedSystemPrompt;
562
594
  if (agent.config.systemPrompt) {
563
- const sp = agent.config.systemPrompt;
564
- if (sp.includes("{{workspace_dir}}")) {
595
+ resolvedSystemPrompt = agent.config.systemPrompt;
596
+ if (resolvedSystemPrompt.includes("{{workspace_dir}}")) {
565
597
  const workspaceDir = this.env?.getComponent?.("config")?.get?.("workspace_dir") || process.cwd();
566
- agent.config.systemPrompt = agent.config.systemPrompt.replaceAll("{{workspace_dir}}", String(workspaceDir));
598
+ resolvedSystemPrompt = resolvedSystemPrompt.replaceAll("{{workspace_dir}}", String(workspaceDir));
567
599
  }
568
- if (sp.includes("{{memory}}")) {
600
+ if (resolvedSystemPrompt.includes("{{memory}}")) {
569
601
  try {
570
602
  const memoryComponent = this.env?.getComponent?.("memory");
571
603
  if (memoryComponent && typeof memoryComponent.recallMemory === "function") {
572
604
  const memoryContent = await memoryComponent.recallMemory();
573
- agent.config.systemPrompt = agent.config.systemPrompt.replace("{{memory}}", memoryContent || "(No memory)");
605
+ resolvedSystemPrompt = resolvedSystemPrompt.replaceAll("{{memory}}", memoryContent || "(No memory)");
574
606
  } else {
575
- agent.config.systemPrompt = agent.config.systemPrompt.replace("{{memory}}", "(Memory component not available)");
607
+ resolvedSystemPrompt = resolvedSystemPrompt.replaceAll("{{memory}}", "(Memory component not available)");
576
608
  }
577
609
  } catch (err) {
578
610
  logger.warn(`[AgentComponent._run] Failed to replace {{memory}}: ${err}`);
579
- agent.config.systemPrompt = agent.config.systemPrompt.replace("{{memory}}", "(Failed to load memory)");
611
+ resolvedSystemPrompt = resolvedSystemPrompt.replaceAll("{{memory}}", "(Failed to load memory)");
580
612
  }
581
613
  }
582
614
  }
@@ -597,7 +629,7 @@ class AgentComponent extends BaseComponent {
597
629
  maxIterations: agent.config.maxIterations,
598
630
  messages: [],
599
631
  tools: this.getAvailableTools(agent, effectiveContext),
600
- systemPrompt: agent.config.systemPrompt || "You are a helpful assistant.",
632
+ systemPrompt: resolvedSystemPrompt ?? agent.config.systemPrompt ?? "You are a helpful assistant.",
601
633
  context: effectiveContext
602
634
  };
603
635
  let historyMessageCount = 0;
@@ -969,6 +1001,7 @@ class AgentComponent extends BaseComponent {
969
1001
  }
970
1002
  this.aborted.delete(runId);
971
1003
  this.abortControllers.delete(runId);
1004
+ this.doomLoopCaches.delete(runId);
972
1005
  if (result.error) {
973
1006
  this.pushEnvEvent({
974
1007
  type: "agent.error",
@@ -1292,6 +1325,7 @@ ${additionInfo}`
1292
1325
  logger.warn("SessionComponent not found, skipping session recording");
1293
1326
  return;
1294
1327
  }
1328
+ const filtered2 = [];
1295
1329
  for (const msg of allMessages) {
1296
1330
  if (msg.role === "system") {
1297
1331
  continue;
@@ -1304,10 +1338,19 @@ ${additionInfo}`
1304
1338
  continue;
1305
1339
  }
1306
1340
  }
1307
- await sessionComponent.addMessage(sessionId, this.messageConverter.fromModelMessage(msg, { sessionID: sessionId }));
1341
+ filtered2.push(this.messageConverter.fromModelMessage(msg, { sessionID: sessionId }));
1308
1342
  }
1343
+ if (filtered2.length === 0) {
1344
+ return;
1345
+ }
1346
+ await sessionComponent.addMessages(sessionId, filtered2);
1309
1347
  } catch (err) {
1310
- logger.warn(`Failed to record session messages: ${err}`);
1348
+ const kind = err && typeof err === "object" && "kind" in err ? err.kind : undefined;
1349
+ if (kind === "lock_exhausted") {
1350
+ logger.error(`[recordSessionMessages] DROPPED ${filtered?.length ?? "?"} message(s) — SQLITE_BUSY retry exhausted after ${err.attempts ?? "?"} attempts. Session ${sessionId} is now inconsistent with LLM context. Original: ${err}`);
1351
+ } else {
1352
+ logger.error(`[recordSessionMessages] Failed to record session messages for ${sessionId}: ${err}`);
1353
+ }
1311
1354
  }
1312
1355
  }
1313
1356
  isEmptyMessage(content) {
@@ -6,7 +6,7 @@ import {
6
6
  isBuiltInEventSourceType,
7
7
  isValidEventSourceType,
8
8
  validateEventSourceConfig
9
- } from "./roy-agent-core-qhhxx2x2.js";
9
+ } from "./roy-agent-core-ds5f75pg.js";
10
10
  import"./roy-agent-core-fs0mn2jk.js";
11
11
  export {
12
12
  validateEventSourceConfig,
@@ -1,7 +1,8 @@
1
1
  // src/env/event-source/types.ts
2
2
  var BUILT_IN_EVENT_SOURCE_TYPES = {
3
3
  LARK_CLI: "lark-cli",
4
- TIMER: "timer"
4
+ TIMER: "timer",
5
+ BOUNTY_IM: "bounty-im"
5
6
  };
6
7
  var BUILT_IN_EVENT_SOURCE_TYPE_LIST = Object.values(BUILT_IN_EVENT_SOURCE_TYPES);
7
8
 
@@ -19,7 +19,7 @@ import {
19
19
  init_skill_node,
20
20
  init_tool_node,
21
21
  init_workflow_node
22
- } from "./roy-agent-core-hc20420t.js";
22
+ } from "./roy-agent-core-z240ts1r.js";
23
23
  import {
24
24
  WorkflowError,
25
25
  createWorkflowEvent,