sparkecoder 0.1.122 → 0.1.124

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 (136) hide show
  1. package/dist/agent/index.d.ts +3 -3
  2. package/dist/agent/index.js +67 -14
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +201 -66
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +2 -2
  7. package/dist/{index-DczYH89U.d.ts → index-Bcz0aCAR.d.ts} +104 -104
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.js +124 -24
  10. package/dist/index.js.map +1 -1
  11. package/dist/{schema-DxrKyetI.d.ts → schema-BWbWmfDQ.d.ts} +3 -3
  12. package/dist/{search-CVVfuBPZ.d.ts → search-DOzC4ojH.d.ts} +4 -4
  13. package/dist/server/index.js +124 -24
  14. package/dist/server/index.js.map +1 -1
  15. package/dist/skills/default/recording.md +2 -2
  16. package/dist/tools/index.d.ts +3 -3
  17. package/package.json +1 -1
  18. package/src/skills/default/recording.md +2 -2
  19. package/web/.next/BUILD_ID +1 -1
  20. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  21. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  22. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  23. package/web/.next/standalone/web/.next/server/app/(main)/agents/page_client-reference-manifest.js +1 -1
  24. package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
  25. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
  26. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  27. package/web/.next/standalone/web/.next/server/app/(main)/settings/page_client-reference-manifest.js +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  29. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  36. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  37. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  41. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
  44. package/web/.next/standalone/web/.next/server/app/agents.rsc +3 -3
  45. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +2 -2
  46. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +2 -2
  48. package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +3 -3
  49. package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  53. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  62. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  64. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  70. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  71. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  74. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  78. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  79. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  80. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  82. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  83. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  84. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  85. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  86. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  87. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  88. package/web/.next/standalone/web/.next/server/app/index.rsc +3 -3
  89. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
  90. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
  91. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
  92. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  93. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  94. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  95. package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
  96. package/web/.next/standalone/web/.next/server/app/settings.rsc +3 -3
  97. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +2 -2
  98. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
  99. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +2 -2
  100. package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  101. package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  102. package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  103. package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  104. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c87abaf4._.js → 2374f_12d55e68._.js} +1 -1
  105. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_1f3f2d00._.js → 2374f_1c0639c2._.js} +1 -1
  106. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a0d5caeb._.js → 2374f_28cd6777._.js} +1 -1
  107. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_570c34dc._.js → 2374f_5f47a9b7._.js} +1 -1
  108. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_d8122230._.js → 2374f_aa218457._.js} +1 -1
  109. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_9c560f3a._.js → 2374f_f678a96f._.js} +1 -1
  110. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_38945fd9._.js → 2374f_fac4000d._.js} +1 -1
  111. package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__4de426bd._.js → [root-of-the-server]__e5911ea8._.js} +4 -4
  112. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_62ca4286._.js → web_2966b3a3._.js} +2 -2
  113. package/web/.next/standalone/web/.next/server/chunks/ssr/web_4fe3c244._.js +1 -1
  114. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  115. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  116. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  117. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  118. package/web/.next/standalone/web/.next/static/chunks/{91988e253d5fa420.js → 4d95c15f712c9e06.js} +5 -5
  119. package/web/.next/standalone/web/.next/static/chunks/780c93257fac7d43.js +1 -0
  120. package/web/.next/standalone/web/.next/static/static/chunks/{91988e253d5fa420.js → 4d95c15f712c9e06.js} +5 -5
  121. package/web/.next/standalone/web/.next/static/static/chunks/780c93257fac7d43.js +1 -0
  122. package/web/.next/standalone/web/src/components/chat-interface.tsx +112 -1
  123. package/web/.next/static/chunks/{91988e253d5fa420.js → 4d95c15f712c9e06.js} +5 -5
  124. package/web/.next/static/chunks/780c93257fac7d43.js +1 -0
  125. package/web/.next/standalone/web/.next/static/chunks/f0f19357f3fb7cf8.js +0 -1
  126. package/web/.next/standalone/web/.next/static/static/chunks/f0f19357f3fb7cf8.js +0 -1
  127. package/web/.next/static/chunks/f0f19357f3fb7cf8.js +0 -1
  128. /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_buildManifest.js +0 -0
  129. /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_clientMiddlewareManifest.json +0 -0
  130. /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_ssgManifest.js +0 -0
  131. /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_buildManifest.js +0 -0
  132. /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_clientMiddlewareManifest.json +0 -0
  133. /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_ssgManifest.js +0 -0
  134. /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_buildManifest.js +0 -0
  135. /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_clientMiddlewareManifest.json +0 -0
  136. /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_ssgManifest.js +0 -0
package/dist/index.js CHANGED
@@ -7476,6 +7476,55 @@ function wrapToolsNeverThrow(tools) {
7476
7476
  }
7477
7477
  return wrapped;
7478
7478
  }
7479
+ function ensureToolResultsFollowCalls(messages) {
7480
+ if (!Array.isArray(messages) || messages.length < 3) return messages;
7481
+ let mutated = false;
7482
+ const result = messages.slice();
7483
+ let i = 0;
7484
+ while (i < result.length) {
7485
+ const msg = result[i];
7486
+ if (msg?.role !== "assistant" || !Array.isArray(msg.content)) {
7487
+ i++;
7488
+ continue;
7489
+ }
7490
+ const callIds = /* @__PURE__ */ new Set();
7491
+ for (const part of msg.content) {
7492
+ if (part?.type === "tool-call" && typeof part.toolCallId === "string") {
7493
+ callIds.add(part.toolCallId);
7494
+ }
7495
+ }
7496
+ if (callIds.size === 0) {
7497
+ i++;
7498
+ continue;
7499
+ }
7500
+ let toolIdx = -1;
7501
+ for (let j = i + 1; j < result.length; j++) {
7502
+ const m = result[j];
7503
+ if (m?.role === "assistant" && Array.isArray(m.content) && m.content.some((p) => p?.type === "tool-call")) {
7504
+ break;
7505
+ }
7506
+ if (m?.role === "tool" && Array.isArray(m.content)) {
7507
+ const answersOne = m.content.some(
7508
+ (p) => p?.type === "tool-result" && typeof p.toolCallId === "string" && callIds.has(p.toolCallId)
7509
+ );
7510
+ if (answersOne) {
7511
+ toolIdx = j;
7512
+ break;
7513
+ }
7514
+ }
7515
+ }
7516
+ if (toolIdx > i + 1) {
7517
+ const [toolMsg] = result.splice(toolIdx, 1);
7518
+ result.splice(i + 1, 0, toolMsg);
7519
+ mutated = true;
7520
+ console.warn(
7521
+ `[tool-repair] Reordered tool-result message from index ${toolIdx} to ${i + 1} to immediately follow assistant tool-call(s) (${[...callIds].join(", ")}). ${toolIdx - i - 1} message(s) were wedged between them.`
7522
+ );
7523
+ }
7524
+ i++;
7525
+ }
7526
+ return mutated ? result : messages;
7527
+ }
7479
7528
  function repairToolPairing(messages) {
7480
7529
  const toolCallIds = /* @__PURE__ */ new Set();
7481
7530
  const toolResultIds = /* @__PURE__ */ new Set();
@@ -7595,6 +7644,7 @@ ${summaryContent}`
7595
7644
  ];
7596
7645
  }
7597
7646
  messages = repairToolPairing(messages);
7647
+ messages = ensureToolResultsFollowCalls(messages);
7598
7648
  messages = ensureEndsWithUserOrTool(messages);
7599
7649
  return messages;
7600
7650
  }
@@ -7789,7 +7839,7 @@ ${summaryContent}`
7789
7839
  }
7790
7840
  }
7791
7841
  async addResponseMessages(messages) {
7792
- const safe = repairToolPairing(messages);
7842
+ const safe = ensureToolResultsFollowCalls(repairToolPairing(messages));
7793
7843
  await messageQueries.addMany(this.sessionId, safe);
7794
7844
  try {
7795
7845
  const { appendTurn: appendTurn2, flattenContent: flattenContent2 } = await Promise.resolve().then(() => (init_conversation_archive(), conversation_archive_exports));
@@ -9900,7 +9950,7 @@ ${prompt}` });
9900
9950
  const config = getConfig();
9901
9951
  const userContent = this.buildUserMessageContent(options.prompt, options.attachments);
9902
9952
  if (!options.skipSaveUserMessage) {
9903
- this.context.addUserMessage(userContent);
9953
+ await this.context.addUserMessage(userContent);
9904
9954
  }
9905
9955
  await sessionQueries.updateStatus(this.session.id, "active");
9906
9956
  let systemPrompt = await buildSystemPrompt({
@@ -9948,9 +9998,10 @@ ${personality.trim()}`;
9948
9998
  // aborted mid-tool). Repairing in `prepareStep` guarantees no orphan
9949
9999
  // ever reaches the model and we never hit AI_MissingToolResultsError.
9950
10000
  prepareStep: async ({ messages: stepMessages }) => {
9951
- const repaired = repairToolPairing(stepMessages);
9952
- if (repaired === stepMessages) return {};
9953
- return { messages: repaired };
10001
+ const paired = repairToolPairing(stepMessages);
10002
+ const ordered = ensureToolResultsFollowCalls(paired);
10003
+ if (ordered === stepMessages) return {};
10004
+ return { messages: ordered };
9954
10005
  },
9955
10006
  onStepFinish: async (step) => {
9956
10007
  options.onStepFinish?.(step);
@@ -9963,7 +10014,7 @@ ${personality.trim()}`;
9963
10014
  const result = await stream;
9964
10015
  const response = await result.response;
9965
10016
  const responseMessages = response.messages;
9966
- this.context.addResponseMessages(responseMessages);
10017
+ await this.context.addResponseMessages(responseMessages);
9967
10018
  };
9968
10019
  return {
9969
10020
  sessionId: this.session.id,
@@ -9977,7 +10028,7 @@ ${personality.trim()}`;
9977
10028
  */
9978
10029
  async run(options) {
9979
10030
  const config = getConfig();
9980
- this.context.addUserMessage(options.prompt);
10031
+ await this.context.addUserMessage(options.prompt);
9981
10032
  const systemPrompt = await buildSystemPrompt({
9982
10033
  workingDirectory: this.session.workingDirectory,
9983
10034
  skillsDirectories: config.resolvedSkillsDirectories,
@@ -10001,13 +10052,14 @@ ${personality.trim()}`;
10001
10052
  } : void 0,
10002
10053
  // Repair tool pairing before every step (see `stream()` for full rationale).
10003
10054
  prepareStep: async ({ messages: stepMessages }) => {
10004
- const repaired = repairToolPairing(stepMessages);
10005
- if (repaired === stepMessages) return {};
10006
- return { messages: repaired };
10055
+ const paired = repairToolPairing(stepMessages);
10056
+ const ordered = ensureToolResultsFollowCalls(paired);
10057
+ if (ordered === stepMessages) return {};
10058
+ return { messages: ordered };
10007
10059
  }
10008
10060
  });
10009
10061
  const responseMessages = result.response.messages;
10010
- this.context.addResponseMessages(responseMessages);
10062
+ await this.context.addResponseMessages(responseMessages);
10011
10063
  return {
10012
10064
  text: result.text,
10013
10065
  steps: result.steps
@@ -10190,9 +10242,10 @@ ${p.text}` : p.text;
10190
10242
  // See the matching note in `stream()` — repair tool pairing before
10191
10243
  // every step so we never feed the model an orphan tool-call.
10192
10244
  prepareStep: async ({ messages: stepMessages }) => {
10193
- const repaired = repairToolPairing(stepMessages);
10194
- if (repaired === stepMessages) return {};
10195
- return { messages: repaired };
10245
+ const paired = repairToolPairing(stepMessages);
10246
+ const ordered = ensureToolResultsFollowCalls(paired);
10247
+ if (ordered === stepMessages) return {};
10248
+ return { messages: ordered };
10196
10249
  },
10197
10250
  onStepFinish: async (step) => {
10198
10251
  options.onStepFinish?.(step);
@@ -12063,31 +12116,44 @@ async function recoverFromMissingToolResults(sessionId, error) {
12063
12116
  } catch (err) {
12064
12117
  console.warn("[missing-tool-recovery] could not load messages:", err?.message || err);
12065
12118
  }
12066
- const toolNameByCallId = /* @__PURE__ */ new Map();
12119
+ const toolInfoByCallId = /* @__PURE__ */ new Map();
12120
+ const resultMessageIndexByCallId = /* @__PURE__ */ new Map();
12067
12121
  const existingResultIds = /* @__PURE__ */ new Set();
12068
- for (const msg of history) {
12122
+ for (let idx = 0; idx < history.length; idx++) {
12123
+ const msg = history[idx];
12069
12124
  if (!Array.isArray(msg.content)) continue;
12070
12125
  for (const part of msg.content) {
12071
12126
  if (part?.type === "tool-call" && typeof part.toolCallId === "string") {
12072
- if (typeof part.toolName === "string") toolNameByCallId.set(part.toolCallId, part.toolName);
12127
+ if (typeof part.toolName === "string") {
12128
+ toolInfoByCallId.set(part.toolCallId, { toolName: part.toolName, callMessageIndex: idx });
12129
+ }
12073
12130
  }
12074
12131
  if (part?.type === "tool-result" && typeof part.toolCallId === "string") {
12075
12132
  existingResultIds.add(part.toolCallId);
12133
+ resultMessageIndexByCallId.set(part.toolCallId, idx);
12076
12134
  }
12077
12135
  }
12078
12136
  }
12079
- const resolved = toolCallIds.map((id) => ({
12080
- toolCallId: id,
12081
- toolName: toolNameByCallId.get(id) ?? "unknown",
12082
- foundInAssistantMessage: toolNameByCallId.has(id)
12083
- }));
12137
+ const resolved = toolCallIds.map((id) => {
12138
+ const info = toolInfoByCallId.get(id);
12139
+ const resultIdx = resultMessageIndexByCallId.get(id);
12140
+ const wedgedRoles = info && typeof resultIdx === "number" && resultIdx > info.callMessageIndex + 1 ? history.slice(info.callMessageIndex + 1, resultIdx).map((m) => m.role) : void 0;
12141
+ return {
12142
+ toolCallId: id,
12143
+ toolName: info?.toolName ?? "unknown",
12144
+ foundInAssistantMessage: !!info,
12145
+ callMessageIndex: info?.callMessageIndex,
12146
+ resultMessageIndex: resultIdx,
12147
+ wedgedMessageRoles: wedgedRoles
12148
+ };
12149
+ });
12084
12150
  const stillOrphaned = toolCallIds.filter((id) => !existingResultIds.has(id));
12085
12151
  let syntheticToolMessageSaved = false;
12086
12152
  if (stillOrphaned.length > 0) {
12087
12153
  const syntheticParts = stillOrphaned.map((id) => ({
12088
12154
  type: "tool-result",
12089
12155
  toolCallId: id,
12090
- toolName: toolNameByCallId.get(id) ?? "unknown",
12156
+ toolName: toolInfoByCallId.get(id)?.toolName ?? "unknown",
12091
12157
  output: {
12092
12158
  type: "text",
12093
12159
  value: "[Auto-recovered: the original tool execution never produced a result (crash, timeout, or message stripped during context compaction). This synthetic placeholder lets the conversation continue.]"
@@ -12104,15 +12170,49 @@ async function recoverFromMissingToolResults(sessionId, error) {
12104
12170
  }
12105
12171
  }
12106
12172
  const lastFewMessageRoles = history.slice(-6).map((m) => m.role);
12173
+ const first = resolved.find((r) => r.callMessageIndex !== void 0);
12174
+ let contextSnapshot;
12175
+ if (first?.callMessageIndex !== void 0) {
12176
+ const start = Math.max(0, first.callMessageIndex - 1);
12177
+ const end = Math.min(
12178
+ history.length,
12179
+ Math.max(first.callMessageIndex, first.resultMessageIndex ?? first.callMessageIndex) + 2
12180
+ );
12181
+ contextSnapshot = history.slice(start, end).map((m, offset) => ({
12182
+ index: start + offset,
12183
+ role: m.role,
12184
+ summary: summarizeContent(m.content)
12185
+ }));
12186
+ }
12187
+ const anyWedged = resolved.some((r) => r.wedgedMessageRoles && r.wedgedMessageRoles.length > 0);
12107
12188
  return {
12108
12189
  kind: "missing_tool_results",
12109
12190
  toolCallIds,
12110
12191
  resolved,
12111
12192
  syntheticToolMessageSaved,
12112
12193
  lastFewMessageRoles,
12113
- hint: syntheticToolMessageSaved ? "Synthetic tool-result(s) saved. Re-send your message to continue." : "Could not auto-recover; please reset the session or revert to the previous checkpoint."
12194
+ contextSnapshot,
12195
+ hint: anyWedged ? "A non-tool message was wedged between the assistant tool-call and its tool-result (likely a Slack/system inbox event that arrived mid-turn). " + (syntheticToolMessageSaved ? "Synthetic tool-result was added as a fallback, but the proper fix (now in place) is the reordering pass that moves tool-results to immediately follow their tool-calls." : "The reordering pass should fix this on the next turn; if not, revert to the previous checkpoint.") : syntheticToolMessageSaved ? "Synthetic tool-result(s) saved. Re-send your message to continue." : "Could not auto-recover; please reset the session or revert to the previous checkpoint."
12114
12196
  };
12115
12197
  }
12198
+ function summarizeContent(content) {
12199
+ if (typeof content === "string") {
12200
+ return content.length > 160 ? content.slice(0, 160) + "\u2026" : content;
12201
+ }
12202
+ if (!Array.isArray(content)) return String(content);
12203
+ const parts = content.map((p) => {
12204
+ if (!p || typeof p !== "object") return String(p);
12205
+ if (p.type === "text") {
12206
+ const t = String(p.text ?? "");
12207
+ return `text(${t.length > 80 ? t.slice(0, 80) + "\u2026" : t})`;
12208
+ }
12209
+ if (p.type === "tool-call") return `tool-call(${p.toolName}:${p.toolCallId})`;
12210
+ if (p.type === "tool-result") return `tool-result(${p.toolName ?? "?"}:${p.toolCallId})`;
12211
+ if (p.type === "reasoning") return "reasoning";
12212
+ return p.type ?? "unknown";
12213
+ });
12214
+ return parts.join(", ");
12215
+ }
12116
12216
 
12117
12217
  // src/server/routes/agents.ts
12118
12218
  init_agent();