sparkecoder 0.1.122 → 0.1.123
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.
- package/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +67 -14
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +124 -24
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-DczYH89U.d.ts → index-Bcz0aCAR.d.ts} +104 -104
- package/dist/index.d.ts +5 -5
- package/dist/index.js +124 -24
- package/dist/index.js.map +1 -1
- package/dist/{schema-DxrKyetI.d.ts → schema-BWbWmfDQ.d.ts} +3 -3
- package/dist/{search-CVVfuBPZ.d.ts → search-DOzC4ojH.d.ts} +4 -4
- package/dist/server/index.js +124 -24
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +3 -3
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_ssgManifest.js +0 -0
- /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_buildManifest.js +0 -0
- /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → MP4p8_EldjbZ69dONoEcM}/_ssgManifest.js +0 -0
|
@@ -85,7 +85,7 @@ declare const sessions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
85
85
|
tableName: "sessions";
|
|
86
86
|
dataType: "string";
|
|
87
87
|
columnType: "SQLiteText";
|
|
88
|
-
data: "
|
|
88
|
+
data: "error" | "completed" | "active" | "waiting";
|
|
89
89
|
driverParam: string;
|
|
90
90
|
notNull: true;
|
|
91
91
|
hasDefault: true;
|
|
@@ -391,7 +391,7 @@ declare const toolExecutions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
391
391
|
tableName: "tool_executions";
|
|
392
392
|
dataType: "string";
|
|
393
393
|
columnType: "SQLiteText";
|
|
394
|
-
data: "
|
|
394
|
+
data: "error" | "completed" | "pending" | "approved" | "rejected";
|
|
395
395
|
driverParam: string;
|
|
396
396
|
notNull: true;
|
|
397
397
|
hasDefault: true;
|
|
@@ -814,7 +814,7 @@ declare const terminals: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
814
814
|
tableName: "terminals";
|
|
815
815
|
dataType: "string";
|
|
816
816
|
columnType: "SQLiteText";
|
|
817
|
-
data: "
|
|
817
|
+
data: "error" | "running" | "stopped";
|
|
818
818
|
driverParam: string;
|
|
819
819
|
notNull: true;
|
|
820
820
|
hasDefault: true;
|
|
@@ -16,11 +16,11 @@ interface BashToolOptions {
|
|
|
16
16
|
declare function createBashTool(options: BashToolOptions): ai.Tool<{
|
|
17
17
|
background: boolean;
|
|
18
18
|
id?: string | undefined;
|
|
19
|
-
input?: string | undefined;
|
|
20
19
|
command?: string | undefined;
|
|
20
|
+
input?: string | undefined;
|
|
21
21
|
kill?: boolean | undefined;
|
|
22
22
|
tail?: number | undefined;
|
|
23
|
-
key?: "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "
|
|
23
|
+
key?: "y" | "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "n" | undefined;
|
|
24
24
|
}, {
|
|
25
25
|
success: boolean;
|
|
26
26
|
id: string;
|
|
@@ -66,7 +66,7 @@ declare function createBashTool(options: BashToolOptions): ai.Tool<{
|
|
|
66
66
|
id: string;
|
|
67
67
|
output: string;
|
|
68
68
|
exitCode: number;
|
|
69
|
-
status: "
|
|
69
|
+
status: "error" | "completed" | "running" | "stopped";
|
|
70
70
|
message?: undefined;
|
|
71
71
|
error?: undefined;
|
|
72
72
|
} | {
|
|
@@ -218,8 +218,8 @@ interface SearchToolOptions {
|
|
|
218
218
|
* Progress is streamed back to the UI so users can see exploration happening.
|
|
219
219
|
*/
|
|
220
220
|
declare function createSearchTool(options: SearchToolOptions): ai.Tool<{
|
|
221
|
-
query: string;
|
|
222
221
|
context: string;
|
|
222
|
+
query: string;
|
|
223
223
|
}, {
|
|
224
224
|
success: boolean;
|
|
225
225
|
error: string;
|
package/dist/server/index.js
CHANGED
|
@@ -7459,6 +7459,55 @@ function wrapToolsNeverThrow(tools) {
|
|
|
7459
7459
|
}
|
|
7460
7460
|
return wrapped;
|
|
7461
7461
|
}
|
|
7462
|
+
function ensureToolResultsFollowCalls(messages) {
|
|
7463
|
+
if (!Array.isArray(messages) || messages.length < 3) return messages;
|
|
7464
|
+
let mutated = false;
|
|
7465
|
+
const result = messages.slice();
|
|
7466
|
+
let i = 0;
|
|
7467
|
+
while (i < result.length) {
|
|
7468
|
+
const msg = result[i];
|
|
7469
|
+
if (msg?.role !== "assistant" || !Array.isArray(msg.content)) {
|
|
7470
|
+
i++;
|
|
7471
|
+
continue;
|
|
7472
|
+
}
|
|
7473
|
+
const callIds = /* @__PURE__ */ new Set();
|
|
7474
|
+
for (const part of msg.content) {
|
|
7475
|
+
if (part?.type === "tool-call" && typeof part.toolCallId === "string") {
|
|
7476
|
+
callIds.add(part.toolCallId);
|
|
7477
|
+
}
|
|
7478
|
+
}
|
|
7479
|
+
if (callIds.size === 0) {
|
|
7480
|
+
i++;
|
|
7481
|
+
continue;
|
|
7482
|
+
}
|
|
7483
|
+
let toolIdx = -1;
|
|
7484
|
+
for (let j = i + 1; j < result.length; j++) {
|
|
7485
|
+
const m = result[j];
|
|
7486
|
+
if (m?.role === "assistant" && Array.isArray(m.content) && m.content.some((p) => p?.type === "tool-call")) {
|
|
7487
|
+
break;
|
|
7488
|
+
}
|
|
7489
|
+
if (m?.role === "tool" && Array.isArray(m.content)) {
|
|
7490
|
+
const answersOne = m.content.some(
|
|
7491
|
+
(p) => p?.type === "tool-result" && typeof p.toolCallId === "string" && callIds.has(p.toolCallId)
|
|
7492
|
+
);
|
|
7493
|
+
if (answersOne) {
|
|
7494
|
+
toolIdx = j;
|
|
7495
|
+
break;
|
|
7496
|
+
}
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
if (toolIdx > i + 1) {
|
|
7500
|
+
const [toolMsg] = result.splice(toolIdx, 1);
|
|
7501
|
+
result.splice(i + 1, 0, toolMsg);
|
|
7502
|
+
mutated = true;
|
|
7503
|
+
console.warn(
|
|
7504
|
+
`[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.`
|
|
7505
|
+
);
|
|
7506
|
+
}
|
|
7507
|
+
i++;
|
|
7508
|
+
}
|
|
7509
|
+
return mutated ? result : messages;
|
|
7510
|
+
}
|
|
7462
7511
|
function repairToolPairing(messages) {
|
|
7463
7512
|
const toolCallIds = /* @__PURE__ */ new Set();
|
|
7464
7513
|
const toolResultIds = /* @__PURE__ */ new Set();
|
|
@@ -7578,6 +7627,7 @@ ${summaryContent}`
|
|
|
7578
7627
|
];
|
|
7579
7628
|
}
|
|
7580
7629
|
messages = repairToolPairing(messages);
|
|
7630
|
+
messages = ensureToolResultsFollowCalls(messages);
|
|
7581
7631
|
messages = ensureEndsWithUserOrTool(messages);
|
|
7582
7632
|
return messages;
|
|
7583
7633
|
}
|
|
@@ -7772,7 +7822,7 @@ ${summaryContent}`
|
|
|
7772
7822
|
}
|
|
7773
7823
|
}
|
|
7774
7824
|
async addResponseMessages(messages) {
|
|
7775
|
-
const safe = repairToolPairing(messages);
|
|
7825
|
+
const safe = ensureToolResultsFollowCalls(repairToolPairing(messages));
|
|
7776
7826
|
await messageQueries.addMany(this.sessionId, safe);
|
|
7777
7827
|
try {
|
|
7778
7828
|
const { appendTurn: appendTurn2, flattenContent: flattenContent2 } = await Promise.resolve().then(() => (init_conversation_archive(), conversation_archive_exports));
|
|
@@ -9883,7 +9933,7 @@ ${prompt}` });
|
|
|
9883
9933
|
const config = getConfig();
|
|
9884
9934
|
const userContent = this.buildUserMessageContent(options.prompt, options.attachments);
|
|
9885
9935
|
if (!options.skipSaveUserMessage) {
|
|
9886
|
-
this.context.addUserMessage(userContent);
|
|
9936
|
+
await this.context.addUserMessage(userContent);
|
|
9887
9937
|
}
|
|
9888
9938
|
await sessionQueries.updateStatus(this.session.id, "active");
|
|
9889
9939
|
let systemPrompt = await buildSystemPrompt({
|
|
@@ -9931,9 +9981,10 @@ ${personality.trim()}`;
|
|
|
9931
9981
|
// aborted mid-tool). Repairing in `prepareStep` guarantees no orphan
|
|
9932
9982
|
// ever reaches the model and we never hit AI_MissingToolResultsError.
|
|
9933
9983
|
prepareStep: async ({ messages: stepMessages }) => {
|
|
9934
|
-
const
|
|
9935
|
-
|
|
9936
|
-
|
|
9984
|
+
const paired = repairToolPairing(stepMessages);
|
|
9985
|
+
const ordered = ensureToolResultsFollowCalls(paired);
|
|
9986
|
+
if (ordered === stepMessages) return {};
|
|
9987
|
+
return { messages: ordered };
|
|
9937
9988
|
},
|
|
9938
9989
|
onStepFinish: async (step) => {
|
|
9939
9990
|
options.onStepFinish?.(step);
|
|
@@ -9946,7 +9997,7 @@ ${personality.trim()}`;
|
|
|
9946
9997
|
const result = await stream;
|
|
9947
9998
|
const response = await result.response;
|
|
9948
9999
|
const responseMessages = response.messages;
|
|
9949
|
-
this.context.addResponseMessages(responseMessages);
|
|
10000
|
+
await this.context.addResponseMessages(responseMessages);
|
|
9950
10001
|
};
|
|
9951
10002
|
return {
|
|
9952
10003
|
sessionId: this.session.id,
|
|
@@ -9960,7 +10011,7 @@ ${personality.trim()}`;
|
|
|
9960
10011
|
*/
|
|
9961
10012
|
async run(options) {
|
|
9962
10013
|
const config = getConfig();
|
|
9963
|
-
this.context.addUserMessage(options.prompt);
|
|
10014
|
+
await this.context.addUserMessage(options.prompt);
|
|
9964
10015
|
const systemPrompt = await buildSystemPrompt({
|
|
9965
10016
|
workingDirectory: this.session.workingDirectory,
|
|
9966
10017
|
skillsDirectories: config.resolvedSkillsDirectories,
|
|
@@ -9984,13 +10035,14 @@ ${personality.trim()}`;
|
|
|
9984
10035
|
} : void 0,
|
|
9985
10036
|
// Repair tool pairing before every step (see `stream()` for full rationale).
|
|
9986
10037
|
prepareStep: async ({ messages: stepMessages }) => {
|
|
9987
|
-
const
|
|
9988
|
-
|
|
9989
|
-
|
|
10038
|
+
const paired = repairToolPairing(stepMessages);
|
|
10039
|
+
const ordered = ensureToolResultsFollowCalls(paired);
|
|
10040
|
+
if (ordered === stepMessages) return {};
|
|
10041
|
+
return { messages: ordered };
|
|
9990
10042
|
}
|
|
9991
10043
|
});
|
|
9992
10044
|
const responseMessages = result.response.messages;
|
|
9993
|
-
this.context.addResponseMessages(responseMessages);
|
|
10045
|
+
await this.context.addResponseMessages(responseMessages);
|
|
9994
10046
|
return {
|
|
9995
10047
|
text: result.text,
|
|
9996
10048
|
steps: result.steps
|
|
@@ -10173,9 +10225,10 @@ ${p.text}` : p.text;
|
|
|
10173
10225
|
// See the matching note in `stream()` — repair tool pairing before
|
|
10174
10226
|
// every step so we never feed the model an orphan tool-call.
|
|
10175
10227
|
prepareStep: async ({ messages: stepMessages }) => {
|
|
10176
|
-
const
|
|
10177
|
-
|
|
10178
|
-
|
|
10228
|
+
const paired = repairToolPairing(stepMessages);
|
|
10229
|
+
const ordered = ensureToolResultsFollowCalls(paired);
|
|
10230
|
+
if (ordered === stepMessages) return {};
|
|
10231
|
+
return { messages: ordered };
|
|
10179
10232
|
},
|
|
10180
10233
|
onStepFinish: async (step) => {
|
|
10181
10234
|
options.onStepFinish?.(step);
|
|
@@ -12043,31 +12096,44 @@ async function recoverFromMissingToolResults(sessionId, error) {
|
|
|
12043
12096
|
} catch (err) {
|
|
12044
12097
|
console.warn("[missing-tool-recovery] could not load messages:", err?.message || err);
|
|
12045
12098
|
}
|
|
12046
|
-
const
|
|
12099
|
+
const toolInfoByCallId = /* @__PURE__ */ new Map();
|
|
12100
|
+
const resultMessageIndexByCallId = /* @__PURE__ */ new Map();
|
|
12047
12101
|
const existingResultIds = /* @__PURE__ */ new Set();
|
|
12048
|
-
for (
|
|
12102
|
+
for (let idx = 0; idx < history.length; idx++) {
|
|
12103
|
+
const msg = history[idx];
|
|
12049
12104
|
if (!Array.isArray(msg.content)) continue;
|
|
12050
12105
|
for (const part of msg.content) {
|
|
12051
12106
|
if (part?.type === "tool-call" && typeof part.toolCallId === "string") {
|
|
12052
|
-
if (typeof part.toolName === "string")
|
|
12107
|
+
if (typeof part.toolName === "string") {
|
|
12108
|
+
toolInfoByCallId.set(part.toolCallId, { toolName: part.toolName, callMessageIndex: idx });
|
|
12109
|
+
}
|
|
12053
12110
|
}
|
|
12054
12111
|
if (part?.type === "tool-result" && typeof part.toolCallId === "string") {
|
|
12055
12112
|
existingResultIds.add(part.toolCallId);
|
|
12113
|
+
resultMessageIndexByCallId.set(part.toolCallId, idx);
|
|
12056
12114
|
}
|
|
12057
12115
|
}
|
|
12058
12116
|
}
|
|
12059
|
-
const resolved = toolCallIds.map((id) =>
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
|
|
12117
|
+
const resolved = toolCallIds.map((id) => {
|
|
12118
|
+
const info = toolInfoByCallId.get(id);
|
|
12119
|
+
const resultIdx = resultMessageIndexByCallId.get(id);
|
|
12120
|
+
const wedgedRoles = info && typeof resultIdx === "number" && resultIdx > info.callMessageIndex + 1 ? history.slice(info.callMessageIndex + 1, resultIdx).map((m) => m.role) : void 0;
|
|
12121
|
+
return {
|
|
12122
|
+
toolCallId: id,
|
|
12123
|
+
toolName: info?.toolName ?? "unknown",
|
|
12124
|
+
foundInAssistantMessage: !!info,
|
|
12125
|
+
callMessageIndex: info?.callMessageIndex,
|
|
12126
|
+
resultMessageIndex: resultIdx,
|
|
12127
|
+
wedgedMessageRoles: wedgedRoles
|
|
12128
|
+
};
|
|
12129
|
+
});
|
|
12064
12130
|
const stillOrphaned = toolCallIds.filter((id) => !existingResultIds.has(id));
|
|
12065
12131
|
let syntheticToolMessageSaved = false;
|
|
12066
12132
|
if (stillOrphaned.length > 0) {
|
|
12067
12133
|
const syntheticParts = stillOrphaned.map((id) => ({
|
|
12068
12134
|
type: "tool-result",
|
|
12069
12135
|
toolCallId: id,
|
|
12070
|
-
toolName:
|
|
12136
|
+
toolName: toolInfoByCallId.get(id)?.toolName ?? "unknown",
|
|
12071
12137
|
output: {
|
|
12072
12138
|
type: "text",
|
|
12073
12139
|
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.]"
|
|
@@ -12084,15 +12150,49 @@ async function recoverFromMissingToolResults(sessionId, error) {
|
|
|
12084
12150
|
}
|
|
12085
12151
|
}
|
|
12086
12152
|
const lastFewMessageRoles = history.slice(-6).map((m) => m.role);
|
|
12153
|
+
const first = resolved.find((r) => r.callMessageIndex !== void 0);
|
|
12154
|
+
let contextSnapshot;
|
|
12155
|
+
if (first?.callMessageIndex !== void 0) {
|
|
12156
|
+
const start = Math.max(0, first.callMessageIndex - 1);
|
|
12157
|
+
const end = Math.min(
|
|
12158
|
+
history.length,
|
|
12159
|
+
Math.max(first.callMessageIndex, first.resultMessageIndex ?? first.callMessageIndex) + 2
|
|
12160
|
+
);
|
|
12161
|
+
contextSnapshot = history.slice(start, end).map((m, offset) => ({
|
|
12162
|
+
index: start + offset,
|
|
12163
|
+
role: m.role,
|
|
12164
|
+
summary: summarizeContent(m.content)
|
|
12165
|
+
}));
|
|
12166
|
+
}
|
|
12167
|
+
const anyWedged = resolved.some((r) => r.wedgedMessageRoles && r.wedgedMessageRoles.length > 0);
|
|
12087
12168
|
return {
|
|
12088
12169
|
kind: "missing_tool_results",
|
|
12089
12170
|
toolCallIds,
|
|
12090
12171
|
resolved,
|
|
12091
12172
|
syntheticToolMessageSaved,
|
|
12092
12173
|
lastFewMessageRoles,
|
|
12093
|
-
|
|
12174
|
+
contextSnapshot,
|
|
12175
|
+
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."
|
|
12094
12176
|
};
|
|
12095
12177
|
}
|
|
12178
|
+
function summarizeContent(content) {
|
|
12179
|
+
if (typeof content === "string") {
|
|
12180
|
+
return content.length > 160 ? content.slice(0, 160) + "\u2026" : content;
|
|
12181
|
+
}
|
|
12182
|
+
if (!Array.isArray(content)) return String(content);
|
|
12183
|
+
const parts = content.map((p) => {
|
|
12184
|
+
if (!p || typeof p !== "object") return String(p);
|
|
12185
|
+
if (p.type === "text") {
|
|
12186
|
+
const t = String(p.text ?? "");
|
|
12187
|
+
return `text(${t.length > 80 ? t.slice(0, 80) + "\u2026" : t})`;
|
|
12188
|
+
}
|
|
12189
|
+
if (p.type === "tool-call") return `tool-call(${p.toolName}:${p.toolCallId})`;
|
|
12190
|
+
if (p.type === "tool-result") return `tool-result(${p.toolName ?? "?"}:${p.toolCallId})`;
|
|
12191
|
+
if (p.type === "reasoning") return "reasoning";
|
|
12192
|
+
return p.type ?? "unknown";
|
|
12193
|
+
});
|
|
12194
|
+
return parts.join(", ");
|
|
12195
|
+
}
|
|
12096
12196
|
|
|
12097
12197
|
// src/server/routes/agents.ts
|
|
12098
12198
|
init_agent();
|