@rynfar/meridian 1.62.3 → 1.62.5
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/{cli-3ysfatce.js → cli-dya07jbg.js} +268 -173
- package/dist/cli.js +1 -1
- package/dist/proxy/adapter.d.ts +5 -0
- package/dist/proxy/adapter.d.ts.map +1 -1
- package/dist/proxy/adapters/opencode.d.ts.map +1 -1
- package/dist/proxy/agentDefs.d.ts +9 -7
- package/dist/proxy/agentDefs.d.ts.map +1 -1
- package/dist/proxy/messages.d.ts +0 -28
- package/dist/proxy/messages.d.ts.map +1 -1
- package/dist/proxy/passthroughEarlyStop.d.ts +45 -42
- package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -1
- package/dist/proxy/query.d.ts +3 -2
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/cache.d.ts +1 -1
- package/dist/proxy/session/cache.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts +12 -2
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/sessionStore.d.ts +6 -3
- package/dist/proxy/sessionStore.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
|
@@ -153,30 +153,44 @@ function parseAgentDescriptions(taskDescription) {
|
|
|
153
153
|
}
|
|
154
154
|
return agents;
|
|
155
155
|
}
|
|
156
|
-
function
|
|
156
|
+
function mapModelTier(model) {
|
|
157
|
+
if (!model)
|
|
158
|
+
return "inherit";
|
|
159
|
+
const lower = model.toLowerCase();
|
|
160
|
+
if (lower.includes("opus"))
|
|
161
|
+
return "opus";
|
|
162
|
+
if (lower.includes("fable") || lower.includes("mythos"))
|
|
163
|
+
return "fable";
|
|
164
|
+
if (lower.includes("haiku"))
|
|
165
|
+
return "haiku";
|
|
166
|
+
if (lower.includes("sonnet"))
|
|
167
|
+
return "sonnet";
|
|
168
|
+
return "inherit";
|
|
169
|
+
}
|
|
170
|
+
function buildAgentDefinitions(taskDescription, mcpToolNames, modelTier = "inherit") {
|
|
157
171
|
const descriptions = parseAgentDescriptions(taskDescription);
|
|
158
172
|
const agents = {};
|
|
159
173
|
for (const [name, description] of descriptions) {
|
|
160
174
|
agents[name] = {
|
|
161
175
|
description,
|
|
162
176
|
prompt: buildAgentPrompt(name, description),
|
|
163
|
-
model:
|
|
177
|
+
model: modelTier,
|
|
164
178
|
...mcpToolNames?.length ? { tools: [...mcpToolNames] } : {}
|
|
165
179
|
};
|
|
166
180
|
}
|
|
167
181
|
if (descriptions.size > 0) {
|
|
168
|
-
ensureDefaultAgents(agents, mcpToolNames);
|
|
182
|
+
ensureDefaultAgents(agents, mcpToolNames, modelTier);
|
|
169
183
|
addCaseVariants(agents);
|
|
170
184
|
}
|
|
171
185
|
return agents;
|
|
172
186
|
}
|
|
173
|
-
function ensureDefaultAgents(agents, mcpToolNames) {
|
|
187
|
+
function ensureDefaultAgents(agents, mcpToolNames, modelTier) {
|
|
174
188
|
for (const [name, description] of Object.entries(DEFAULT_AGENT_TYPES)) {
|
|
175
189
|
if (!agents[name]) {
|
|
176
190
|
agents[name] = {
|
|
177
191
|
description,
|
|
178
192
|
prompt: buildAgentPrompt(name, description),
|
|
179
|
-
model:
|
|
193
|
+
model: modelTier,
|
|
180
194
|
...mcpToolNames?.length ? { tools: [...mcpToolNames] } : {}
|
|
181
195
|
};
|
|
182
196
|
}
|
|
@@ -223,10 +237,10 @@ function parseAgentNamesFromSchema(taskTool) {
|
|
|
223
237
|
return [];
|
|
224
238
|
return enumNames.filter((n) => typeof n === "string");
|
|
225
239
|
}
|
|
226
|
-
function buildAgentDefinitionsFromTool(taskTool, mcpToolNames) {
|
|
240
|
+
function buildAgentDefinitionsFromTool(taskTool, mcpToolNames, modelTier = "inherit") {
|
|
227
241
|
const rawDescription = getNested(taskTool, "description");
|
|
228
242
|
const description = typeof rawDescription === "string" ? rawDescription : "";
|
|
229
|
-
const fromDescription = buildAgentDefinitions(description, mcpToolNames);
|
|
243
|
+
const fromDescription = buildAgentDefinitions(description, mcpToolNames, modelTier);
|
|
230
244
|
if (Object.keys(fromDescription).length > 0)
|
|
231
245
|
return fromDescription;
|
|
232
246
|
const names = parseAgentNamesFromSchema(taskTool);
|
|
@@ -240,11 +254,11 @@ function buildAgentDefinitionsFromTool(taskTool, mcpToolNames) {
|
|
|
240
254
|
agents[name] = {
|
|
241
255
|
description: desc,
|
|
242
256
|
prompt: buildAgentPrompt(name, desc),
|
|
243
|
-
model:
|
|
257
|
+
model: modelTier,
|
|
244
258
|
...mcpToolNames?.length ? { tools: [...mcpToolNames] } : {}
|
|
245
259
|
};
|
|
246
260
|
}
|
|
247
|
-
ensureDefaultAgents(agents, mcpToolNames);
|
|
261
|
+
ensureDefaultAgents(agents, mcpToolNames, modelTier);
|
|
248
262
|
addCaseVariants(agents);
|
|
249
263
|
return agents;
|
|
250
264
|
}
|
|
@@ -1974,13 +1988,6 @@ ${history}
|
|
|
1974
1988
|
|
|
1975
1989
|
` + last.text;
|
|
1976
1990
|
}
|
|
1977
|
-
function framePassthroughContinuation(delta) {
|
|
1978
|
-
if (!delta)
|
|
1979
|
-
return delta;
|
|
1980
|
-
return `${PASSTHROUGH_CONTINUATION_LEAD_IN}
|
|
1981
|
-
|
|
1982
|
-
${delta}`;
|
|
1983
|
-
}
|
|
1984
1991
|
function stripNonStandardStreamFields(event) {
|
|
1985
1992
|
if (event && typeof event === "object") {
|
|
1986
1993
|
const e = event;
|
|
@@ -2119,7 +2126,7 @@ function extractSystemText(system) {
|
|
|
2119
2126
|
return system.filter((b) => b?.type === "text" && typeof b.text === "string" && b.text).map((b) => b.text).filter((text) => !TRANSPORT_HEADER_BLOCK.test(text)).join(`
|
|
2120
2127
|
`);
|
|
2121
2128
|
}
|
|
2122
|
-
var HASH_IGNORED_BLOCK_TYPES, HASH_HANDLED_BLOCK_TYPES, HASH_SERIALIZED_BLOCK_TYPES,
|
|
2129
|
+
var HASH_IGNORED_BLOCK_TYPES, HASH_HANDLED_BLOCK_TYPES, HASH_SERIALIZED_BLOCK_TYPES, MULTIMODAL_TYPES, TOOL_TARGET_KEYS, TOOL_TARGET_MAX = 80, CONTENT_SUMMARY_MAX = 120, TRANSPORT_HEADER_BLOCK;
|
|
2123
2130
|
var init_messages = __esm(() => {
|
|
2124
2131
|
HASH_IGNORED_BLOCK_TYPES = new Set(["thinking", "redacted_thinking"]);
|
|
2125
2132
|
HASH_HANDLED_BLOCK_TYPES = new Set(["text", "tool_use", "tool_result"]);
|
|
@@ -2136,7 +2143,6 @@ var init_messages = __esm(() => {
|
|
|
2136
2143
|
"tool_search_tool_result",
|
|
2137
2144
|
"container_upload"
|
|
2138
2145
|
]);
|
|
2139
|
-
PASSTHROUGH_CONTINUATION_LEAD_IN = "The tool calls from your previous turn were forwarded to the client, which has now executed them — " + "their results follow. The instruction to end that turn without further text applied to it alone and " + "is now discharged: continue the work and respond.";
|
|
2140
2146
|
MULTIMODAL_TYPES = new Set(["image", "document", "file"]);
|
|
2141
2147
|
TOOL_TARGET_KEYS = ["filePath", "file_path", "path", "command", "code", "pattern", "query", "url"];
|
|
2142
2148
|
TRANSPORT_HEADER_BLOCK = /^\s*x-anthropic-[a-z0-9-]*header\s*:/i;
|
|
@@ -2199,7 +2205,7 @@ var init_opencode = __esm(() => {
|
|
|
2199
2205
|
if (Array.isArray(body.tools)) {
|
|
2200
2206
|
const taskTool = body.tools.find((t) => t.name === "task" || t.name === "Task");
|
|
2201
2207
|
if (taskTool) {
|
|
2202
|
-
sdkAgents = buildAgentDefinitionsFromTool(taskTool, [...allowedMcpTools]);
|
|
2208
|
+
sdkAgents = buildAgentDefinitionsFromTool(taskTool, [...allowedMcpTools], mapModelTier(body.model));
|
|
2203
2209
|
}
|
|
2204
2210
|
}
|
|
2205
2211
|
let sdkHooks = undefined;
|
|
@@ -2278,6 +2284,9 @@ var init_opencode2 = __esm(() => {
|
|
|
2278
2284
|
getSessionId(c) {
|
|
2279
2285
|
return c.req.header("x-opencode-session") ?? c.req.header("x-session-affinity");
|
|
2280
2286
|
},
|
|
2287
|
+
getAgentMode(c) {
|
|
2288
|
+
return c.req.header("x-opencode-agent-mode");
|
|
2289
|
+
},
|
|
2281
2290
|
extractWorkingDirectory(body) {
|
|
2282
2291
|
return extractClientCwd(body);
|
|
2283
2292
|
},
|
|
@@ -2314,7 +2323,7 @@ var init_opencode2 = __esm(() => {
|
|
|
2314
2323
|
const taskTool = body.tools.find((t) => t.name === "task" || t.name === "Task");
|
|
2315
2324
|
if (!taskTool)
|
|
2316
2325
|
return {};
|
|
2317
|
-
return buildAgentDefinitionsFromTool(taskTool, [...mcpToolNames]);
|
|
2326
|
+
return buildAgentDefinitionsFromTool(taskTool, [...mcpToolNames], mapModelTier(body.model));
|
|
2318
2327
|
},
|
|
2319
2328
|
buildSdkHooks(body, sdkAgents) {
|
|
2320
2329
|
const validAgentNames = Object.keys(sdkAgents);
|
|
@@ -11111,6 +11120,17 @@ function noteAssistantContent(tracker, content) {
|
|
|
11111
11120
|
}
|
|
11112
11121
|
}
|
|
11113
11122
|
}
|
|
11123
|
+
function noteAssistantMessage(tracker, message) {
|
|
11124
|
+
const m = message;
|
|
11125
|
+
if (m?.type !== "assistant")
|
|
11126
|
+
return;
|
|
11127
|
+
const content = m.message?.content;
|
|
11128
|
+
const before = tracker.expected.size;
|
|
11129
|
+
noteAssistantContent(tracker, content);
|
|
11130
|
+
if (tracker.expected.size > before) {
|
|
11131
|
+
tracker.toolCallAssistantUuid = typeof m.uuid === "string" && m.uuid.length > 0 ? m.uuid : undefined;
|
|
11132
|
+
}
|
|
11133
|
+
}
|
|
11114
11134
|
function noteUserContent(tracker, content) {
|
|
11115
11135
|
if (!Array.isArray(content))
|
|
11116
11136
|
return;
|
|
@@ -11121,43 +11141,69 @@ function noteUserContent(tracker, content) {
|
|
|
11121
11141
|
}
|
|
11122
11142
|
}
|
|
11123
11143
|
}
|
|
11124
|
-
function
|
|
11125
|
-
if (tracker.fired)
|
|
11126
|
-
return false;
|
|
11144
|
+
function allForwardedCallsResolved(tracker) {
|
|
11127
11145
|
if (tracker.expected.size === 0)
|
|
11128
11146
|
return false;
|
|
11129
11147
|
for (const id of tracker.expected) {
|
|
11130
11148
|
if (!tracker.resolved.has(id))
|
|
11131
11149
|
return false;
|
|
11132
11150
|
}
|
|
11151
|
+
return true;
|
|
11152
|
+
}
|
|
11153
|
+
function isCompleteToolResultContinuation(messages, expectedIds) {
|
|
11154
|
+
if (expectedIds.length === 0 || messages.length === 0)
|
|
11155
|
+
return false;
|
|
11156
|
+
const expected = new Set(expectedIds);
|
|
11157
|
+
const actual = new Set;
|
|
11158
|
+
const echoedCalls = new Set;
|
|
11159
|
+
let sawUser = false;
|
|
11160
|
+
let sawNonToolResult = false;
|
|
11161
|
+
for (const message of messages) {
|
|
11162
|
+
if (message.role === "assistant" && !sawUser) {
|
|
11163
|
+
if (Array.isArray(message.content)) {
|
|
11164
|
+
for (const rawBlock of message.content) {
|
|
11165
|
+
const block = rawBlock;
|
|
11166
|
+
if (block?.type !== "tool_use")
|
|
11167
|
+
continue;
|
|
11168
|
+
if (typeof block.id !== "string" || !expected.has(block.id) || echoedCalls.has(block.id))
|
|
11169
|
+
return false;
|
|
11170
|
+
echoedCalls.add(block.id);
|
|
11171
|
+
}
|
|
11172
|
+
}
|
|
11173
|
+
continue;
|
|
11174
|
+
}
|
|
11175
|
+
if (message.role !== "user" || !Array.isArray(message.content) || sawUser)
|
|
11176
|
+
return false;
|
|
11177
|
+
sawUser = true;
|
|
11178
|
+
for (const rawBlock of message.content) {
|
|
11179
|
+
const block = rawBlock;
|
|
11180
|
+
if (block?.type === "tool_result") {
|
|
11181
|
+
if (sawNonToolResult || typeof block.tool_use_id !== "string")
|
|
11182
|
+
return false;
|
|
11183
|
+
if (!expected.has(block.tool_use_id) || actual.has(block.tool_use_id))
|
|
11184
|
+
return false;
|
|
11185
|
+
actual.add(block.tool_use_id);
|
|
11186
|
+
} else {
|
|
11187
|
+
sawNonToolResult = true;
|
|
11188
|
+
}
|
|
11189
|
+
}
|
|
11190
|
+
}
|
|
11191
|
+
return actual.size === expected.size && (echoedCalls.size === 0 || echoedCalls.size === expected.size);
|
|
11192
|
+
}
|
|
11193
|
+
function settledToolCallAssistantUuid(tracker) {
|
|
11194
|
+
return allForwardedCallsResolved(tracker) ? tracker.toolCallAssistantUuid : undefined;
|
|
11195
|
+
}
|
|
11196
|
+
function shouldEarlyStop(tracker) {
|
|
11197
|
+
if (tracker.fired || !settledToolCallAssistantUuid(tracker))
|
|
11198
|
+
return false;
|
|
11133
11199
|
tracker.fired = true;
|
|
11134
11200
|
return true;
|
|
11135
11201
|
}
|
|
11136
11202
|
function clientAbortDisposition(input) {
|
|
11137
11203
|
if (input.isIndependentSession || !input.profileSessionId)
|
|
11138
11204
|
return { action: "none" };
|
|
11139
|
-
if (!input.passthrough)
|
|
11140
|
-
return { action: "evict" };
|
|
11141
|
-
if (input.currentSessionId && !input.sawDuplicateToolUse && input.resumeBoundaryUuid) {
|
|
11142
|
-
return { action: "store", resumeUuid: input.resumeBoundaryUuid };
|
|
11143
|
-
}
|
|
11144
11205
|
return { action: "evict" };
|
|
11145
11206
|
}
|
|
11146
|
-
function resumeBoundaryUuid(message) {
|
|
11147
|
-
const m = message;
|
|
11148
|
-
if (m?.type !== "user")
|
|
11149
|
-
return;
|
|
11150
|
-
if (typeof m.uuid !== "string" || m.uuid.length === 0)
|
|
11151
|
-
return;
|
|
11152
|
-
const content = m.message?.content;
|
|
11153
|
-
if (!Array.isArray(content))
|
|
11154
|
-
return;
|
|
11155
|
-
const hasResult = content.some((block) => {
|
|
11156
|
-
const b = block;
|
|
11157
|
-
return b?.type === "tool_result";
|
|
11158
|
-
});
|
|
11159
|
-
return hasResult ? m.uuid : undefined;
|
|
11160
|
-
}
|
|
11161
11207
|
|
|
11162
11208
|
// src/proxy/envelopeIntegrity.ts
|
|
11163
11209
|
function checkEmptyToolInputs(contentBlocks, tools) {
|
|
@@ -20032,6 +20078,13 @@ function normalizeContextUsage(usage) {
|
|
|
20032
20078
|
return lastIteration ?? usage;
|
|
20033
20079
|
}
|
|
20034
20080
|
var MIN_SUFFIX_FOR_COMPACTION = 2;
|
|
20081
|
+
function withClientAssistantUuid(existing, clientMessageCount, uuid) {
|
|
20082
|
+
const next = existing.slice(0, clientMessageCount + 1);
|
|
20083
|
+
while (next.length < clientMessageCount)
|
|
20084
|
+
next.push(null);
|
|
20085
|
+
next[clientMessageCount] = typeof uuid === "string" && uuid.length > 0 ? uuid : null;
|
|
20086
|
+
return next;
|
|
20087
|
+
}
|
|
20035
20088
|
function computeLineageHash(messages) {
|
|
20036
20089
|
if (!messages || messages.length === 0)
|
|
20037
20090
|
return "";
|
|
@@ -20347,15 +20400,20 @@ function writeStore(store) {
|
|
|
20347
20400
|
}
|
|
20348
20401
|
}
|
|
20349
20402
|
}
|
|
20403
|
+
function hasLegacyUserDenialBoundary(session) {
|
|
20404
|
+
const legacy = session.passthroughResumeUuid;
|
|
20405
|
+
return typeof legacy === "string" && legacy.length > 0 && !session.passthroughToolCallAssistantUuid;
|
|
20406
|
+
}
|
|
20350
20407
|
function lookupSharedSession(key) {
|
|
20351
20408
|
const store = readStore();
|
|
20352
|
-
|
|
20409
|
+
const session = store[key];
|
|
20410
|
+
return session && !hasLegacyUserDenialBoundary(session) ? session : undefined;
|
|
20353
20411
|
}
|
|
20354
20412
|
function lookupSharedSessionByClaudeId(claudeSessionId) {
|
|
20355
20413
|
const sessions = Object.values(readStore());
|
|
20356
20414
|
let newest;
|
|
20357
20415
|
for (const session of sessions) {
|
|
20358
|
-
if (session.claudeSessionId !== claudeSessionId)
|
|
20416
|
+
if (session.claudeSessionId !== claudeSessionId || hasLegacyUserDenialBoundary(session))
|
|
20359
20417
|
continue;
|
|
20360
20418
|
if (!newest || session.lastUsedAt > newest.lastUsedAt) {
|
|
20361
20419
|
newest = session;
|
|
@@ -20363,7 +20421,7 @@ function lookupSharedSessionByClaudeId(claudeSessionId) {
|
|
|
20363
20421
|
}
|
|
20364
20422
|
return newest;
|
|
20365
20423
|
}
|
|
20366
|
-
function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes,
|
|
20424
|
+
function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes, passthroughToolCallAssistantUuid, passthroughToolCallIds) {
|
|
20367
20425
|
const path3 = getStorePath();
|
|
20368
20426
|
const lockPath = `${path3}.lock`;
|
|
20369
20427
|
const hasLock = skipLocking ? false : acquireLock(lockPath);
|
|
@@ -20383,7 +20441,8 @@ function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, mes
|
|
|
20383
20441
|
messageHashes: messageHashes ?? existing?.messageHashes,
|
|
20384
20442
|
messageBlockHashes: messageBlockHashes ?? existing?.messageBlockHashes,
|
|
20385
20443
|
sdkMessageUuids: sdkMessageUuids ?? existing?.sdkMessageUuids,
|
|
20386
|
-
|
|
20444
|
+
passthroughToolCallAssistantUuid: passthroughToolCallAssistantUuid === undefined ? existing?.passthroughToolCallAssistantUuid : passthroughToolCallAssistantUuid ?? undefined,
|
|
20445
|
+
passthroughToolCallIds: passthroughToolCallIds === undefined ? existing?.passthroughToolCallIds : passthroughToolCallIds ?? undefined,
|
|
20387
20446
|
contextUsage: contextUsage ?? existing?.contextUsage,
|
|
20388
20447
|
...previousClaudeSessionId ? { previousClaudeSessionId } : {}
|
|
20389
20448
|
};
|
|
@@ -20581,7 +20640,8 @@ function lookupSession(sessionId, messages, workingDirectory) {
|
|
|
20581
20640
|
messageHashes: shared.messageHashes,
|
|
20582
20641
|
messageBlockHashes: shared.messageBlockHashes,
|
|
20583
20642
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
20584
|
-
|
|
20643
|
+
passthroughToolCallAssistantUuid: shared.passthroughToolCallAssistantUuid,
|
|
20644
|
+
passthroughToolCallIds: shared.passthroughToolCallIds,
|
|
20585
20645
|
contextUsage: shared.contextUsage
|
|
20586
20646
|
};
|
|
20587
20647
|
const result = classifyLineage(state, messages, sessionId);
|
|
@@ -20611,7 +20671,8 @@ function lookupSession(sessionId, messages, workingDirectory) {
|
|
|
20611
20671
|
messageHashes: shared.messageHashes,
|
|
20612
20672
|
messageBlockHashes: shared.messageBlockHashes,
|
|
20613
20673
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
20614
|
-
|
|
20674
|
+
passthroughToolCallAssistantUuid: shared.passthroughToolCallAssistantUuid,
|
|
20675
|
+
passthroughToolCallIds: shared.passthroughToolCallIds,
|
|
20615
20676
|
contextUsage: shared.contextUsage
|
|
20616
20677
|
};
|
|
20617
20678
|
const result = classifyLineage(state, messages, fp);
|
|
@@ -20646,13 +20707,14 @@ function getSessionByClaudeId(claudeSessionId) {
|
|
|
20646
20707
|
messageHashes: shared.messageHashes,
|
|
20647
20708
|
messageBlockHashes: shared.messageBlockHashes,
|
|
20648
20709
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
20649
|
-
|
|
20710
|
+
passthroughToolCallAssistantUuid: shared.passthroughToolCallAssistantUuid,
|
|
20711
|
+
passthroughToolCallIds: shared.passthroughToolCallIds,
|
|
20650
20712
|
contextUsage: shared.contextUsage
|
|
20651
20713
|
});
|
|
20652
20714
|
}
|
|
20653
20715
|
return newest;
|
|
20654
20716
|
}
|
|
20655
|
-
function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sdkMessageUuids, contextUsage,
|
|
20717
|
+
function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sdkMessageUuids, contextUsage, passthroughToolCallAssistantUuid, passthroughToolCallIds) {
|
|
20656
20718
|
if (!claudeSessionId)
|
|
20657
20719
|
return;
|
|
20658
20720
|
const lineageHash = computeLineageHash(messages);
|
|
@@ -20666,7 +20728,8 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
|
|
|
20666
20728
|
messageHashes,
|
|
20667
20729
|
messageBlockHashes,
|
|
20668
20730
|
sdkMessageUuids,
|
|
20669
|
-
...
|
|
20731
|
+
...passthroughToolCallAssistantUuid ? { passthroughToolCallAssistantUuid } : {},
|
|
20732
|
+
...passthroughToolCallIds ? { passthroughToolCallIds } : {},
|
|
20670
20733
|
...contextUsage ? { contextUsage } : {}
|
|
20671
20734
|
};
|
|
20672
20735
|
if (sessionId)
|
|
@@ -20676,7 +20739,7 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
|
|
|
20676
20739
|
fingerprintCache.set(fp, state);
|
|
20677
20740
|
const key = sessionId || fp;
|
|
20678
20741
|
if (key) {
|
|
20679
|
-
storeSharedSession(key, claudeSessionId, state.messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes,
|
|
20742
|
+
storeSharedSession(key, claudeSessionId, state.messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes, passthroughToolCallAssistantUuid ?? null, passthroughToolCallIds ?? null);
|
|
20680
20743
|
}
|
|
20681
20744
|
}
|
|
20682
20745
|
|
|
@@ -20836,21 +20899,21 @@ function stripCacheControlDeep(content) {
|
|
|
20836
20899
|
return rest;
|
|
20837
20900
|
});
|
|
20838
20901
|
}
|
|
20839
|
-
function normalizeStructuredUserContent(content) {
|
|
20902
|
+
function normalizeStructuredUserContent(content, preserveToolResultWrapper = false) {
|
|
20840
20903
|
if (!Array.isArray(content))
|
|
20841
20904
|
return content;
|
|
20842
20905
|
const normalized = [];
|
|
20843
20906
|
for (const block of content) {
|
|
20844
20907
|
if (!block || typeof block !== "object")
|
|
20845
20908
|
continue;
|
|
20846
|
-
if (block.type === "tool_result" && Array.isArray(block.content) && hasMultimodalContent(block.content)) {
|
|
20909
|
+
if (!preserveToolResultWrapper && block.type === "tool_result" && Array.isArray(block.content) && hasMultimodalContent(block.content)) {
|
|
20847
20910
|
normalized.push(...normalizeStructuredUserContent(block.content));
|
|
20848
20911
|
continue;
|
|
20849
20912
|
}
|
|
20850
20913
|
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
20851
20914
|
normalized.push({
|
|
20852
20915
|
...block,
|
|
20853
|
-
content: normalizeStructuredUserContent(block.content)
|
|
20916
|
+
content: normalizeStructuredUserContent(block.content, preserveToolResultWrapper)
|
|
20854
20917
|
});
|
|
20855
20918
|
continue;
|
|
20856
20919
|
}
|
|
@@ -21294,8 +21357,10 @@ data: ${JSON.stringify(lastError)}
|
|
|
21294
21357
|
}
|
|
21295
21358
|
const profile = resolveProfile(finalConfig.profiles, finalConfig.defaultProfile, options.forcedProfileId || c.req.header("x-meridian-profile") || undefined, routingMode === "sticky" ? { routingMode, stickySessionKey: adapter.getSessionId(c, body) } : undefined);
|
|
21296
21359
|
const authStatus = await getClaudeAuthStatusAsync(profile.id !== "default" ? profile.id : undefined, Object.keys(profile.env).length > 0 ? profile.env : undefined);
|
|
21297
|
-
const agentMode = c.req.header("x-opencode-agent-mode") ?? null;
|
|
21298
21360
|
const requestSource = c.req.header("x-meridian-source")?.slice(0, 64) || undefined;
|
|
21361
|
+
const declaredAgentMode = adapter.getAgentMode?.(c, body) ?? c.req.header("x-opencode-agent-mode") ?? null;
|
|
21362
|
+
const isSubagentRequest = declaredAgentMode === "subagent" || requestSource?.startsWith("subagent-") === true;
|
|
21363
|
+
const agentMode = isSubagentRequest ? "subagent" : declaredAgentMode;
|
|
21299
21364
|
const requestedModel = typeof body.model === "string" ? body.model : "sonnet";
|
|
21300
21365
|
let model = mapModelToClaudeModel(requestedModel, authStatus?.subscriptionType, agentMode);
|
|
21301
21366
|
const envOverrides = explicitModelPin(requestedModel);
|
|
@@ -21389,12 +21454,12 @@ data: ${JSON.stringify(lastError)}
|
|
|
21389
21454
|
const lastMessage = Array.isArray(body.messages) ? body.messages[body.messages.length - 1] : undefined;
|
|
21390
21455
|
const lastIsToolResult = Array.isArray(lastMessage?.content) && lastMessage.content.some((b) => b?.type === "tool_result");
|
|
21391
21456
|
const isClientDrivenLoop = adapterBase !== "claude-code" && !agentSessionId && lastIsToolResult;
|
|
21392
|
-
const isIndependentSession = !agentSessionId && (requestSource?.startsWith("fork-") ||
|
|
21457
|
+
const isIndependentSession = !agentSessionId && (requestSource?.startsWith("fork-") || isSubagentRequest) || isClientDrivenLoop || false;
|
|
21393
21458
|
let lineageResult = isIndependentSession ? { type: "diverged", reason: "independent-request" } : lookupSession(profileSessionId, body.messages || [], profileScopedCwd);
|
|
21394
21459
|
if (lineageResult.type === "undo" && adapterBase === "opencode" && !agentSessionId) {
|
|
21395
21460
|
lineageResult = { type: "diverged", reason: "missing-session-header" };
|
|
21396
21461
|
}
|
|
21397
|
-
const declaresConcurrentFlow = requestSource?.startsWith("fork-") === true ||
|
|
21462
|
+
const declaresConcurrentFlow = requestSource?.startsWith("fork-") === true || isSubagentRequest;
|
|
21398
21463
|
if (profileSessionId && !declaresConcurrentFlow && requestMeta.sessionTurnLease?.advancedWhileWaiting(profileSessionId) && lineageResult.type !== "continuation" && lineageResult.type !== "compaction") {
|
|
21399
21464
|
const reason = lineageResult.type === "diverged" ? lineageResult.reason : lineageResult.type;
|
|
21400
21465
|
const message = "This session advanced while the request was waiting. Retry with the latest conversation history or use a distinct session ID.";
|
|
@@ -21457,15 +21522,16 @@ data: ${JSON.stringify(lastError)}
|
|
|
21457
21522
|
} : undefined
|
|
21458
21523
|
}, adapterBase);
|
|
21459
21524
|
}
|
|
21460
|
-
|
|
21525
|
+
let isResume = lineageResult.type === "continuation" || lineageResult.type === "compaction";
|
|
21461
21526
|
const isUndo = lineageResult.type === "undo";
|
|
21462
21527
|
const cachedSession = lineageResult.type !== "diverged" ? lineageResult.session : undefined;
|
|
21463
|
-
|
|
21528
|
+
let resumeSessionId = cachedSession?.claudeSessionId;
|
|
21464
21529
|
const passthrough = adapter.instancePassthrough !== undefined ? adapter.instancePassthrough : pipelineCtx.passthrough !== undefined ? pipelineCtx.passthrough : envBool("PASSTHROUGH");
|
|
21465
21530
|
const resumeFrom = lineageResult.type === "continuation" || lineageResult.type === "compaction" ? lineageResult.resumeFrom : undefined;
|
|
21466
21531
|
const resumeContentFrom = lineageResult.type === "continuation" ? lineageResult.resumeContentFrom : undefined;
|
|
21467
21532
|
const undoRollbackUuid = isUndo && lineageResult.type === "undo" ? lineageResult.rollbackUuid : undefined;
|
|
21468
|
-
|
|
21533
|
+
let passthroughToolCallAssistantUuid = passthrough && isResume ? cachedSession?.passthroughToolCallAssistantUuid : undefined;
|
|
21534
|
+
const passthroughToolCallIds = passthrough && isResume ? cachedSession?.passthroughToolCallIds : undefined;
|
|
21469
21535
|
const msgSummary = body.messages?.map((m) => {
|
|
21470
21536
|
const contentTypes = Array.isArray(m.content) ? m.content.map((b) => b.type).join(",") : "string";
|
|
21471
21537
|
return `${m.role}[${contentTypes}]`;
|
|
@@ -21531,17 +21597,28 @@ data: ${JSON.stringify(lastError)}
|
|
|
21531
21597
|
} else {
|
|
21532
21598
|
messagesToConvert = allMessages;
|
|
21533
21599
|
}
|
|
21600
|
+
if (passthroughToolCallAssistantUuid && !isCompleteToolResultContinuation(messagesToConvert, passthroughToolCallIds ?? [])) {
|
|
21601
|
+
claudeLog("passthrough.checkpoint_replay", {
|
|
21602
|
+
expectedToolIds: passthroughToolCallIds?.length ?? 0,
|
|
21603
|
+
reason: "incomplete_or_mismatched_results"
|
|
21604
|
+
});
|
|
21605
|
+
isResume = false;
|
|
21606
|
+
resumeSessionId = undefined;
|
|
21607
|
+
passthroughToolCallAssistantUuid = undefined;
|
|
21608
|
+
messagesToConvert = allMessages;
|
|
21609
|
+
}
|
|
21534
21610
|
const hasMultimodal = messagesToConvert?.some((m) => hasMultimodalContent(m.content));
|
|
21611
|
+
const hasPassthroughToolResults = Boolean(passthroughToolCallAssistantUuid) && messagesToConvert?.some((m) => m.role === "user" && Array.isArray(m.content) && m.content.some((block) => block?.type === "tool_result"));
|
|
21535
21612
|
let structuredMessages;
|
|
21536
21613
|
let textPrompt;
|
|
21537
|
-
if (hasMultimodal) {
|
|
21614
|
+
if (hasMultimodal || hasPassthroughToolResults) {
|
|
21538
21615
|
structuredMessages = [];
|
|
21539
21616
|
if (isResume) {
|
|
21540
21617
|
for (const m of messagesToConvert) {
|
|
21541
21618
|
if (m.role === "user") {
|
|
21542
21619
|
structuredMessages.push({
|
|
21543
21620
|
type: "user",
|
|
21544
|
-
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
21621
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content), Boolean(passthroughToolCallAssistantUuid)) },
|
|
21545
21622
|
parent_tool_use_id: null
|
|
21546
21623
|
});
|
|
21547
21624
|
}
|
|
@@ -21551,7 +21628,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21551
21628
|
if (m.role === "user") {
|
|
21552
21629
|
structuredMessages.push({
|
|
21553
21630
|
type: "user",
|
|
21554
|
-
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
21631
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content), Boolean(passthroughToolCallAssistantUuid)) },
|
|
21555
21632
|
parent_tool_use_id: null
|
|
21556
21633
|
});
|
|
21557
21634
|
} else {
|
|
@@ -21569,13 +21646,6 @@ data: ${JSON.stringify(lastError)}
|
|
|
21569
21646
|
if (structuredMessages.length > 1) {
|
|
21570
21647
|
structuredMessages = consolidateMultimodalOntoLastUser(structuredMessages);
|
|
21571
21648
|
}
|
|
21572
|
-
if (passthroughResumeUuid && structuredMessages.length > 0) {
|
|
21573
|
-
structuredMessages.unshift({
|
|
21574
|
-
type: "user",
|
|
21575
|
-
message: { role: "user", content: PASSTHROUGH_CONTINUATION_LEAD_IN },
|
|
21576
|
-
parent_tool_use_id: null
|
|
21577
|
-
});
|
|
21578
|
-
}
|
|
21579
21649
|
} else {
|
|
21580
21650
|
const toolIndex = buildToolUseIndex(allMessages ?? messagesToConvert ?? []);
|
|
21581
21651
|
const promptTurns = (messagesToConvert ?? []).map((m) => {
|
|
@@ -21590,7 +21660,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21590
21660
|
const resumeDelta = promptTurns.map((t) => t.text).filter(Boolean).join(`
|
|
21591
21661
|
|
|
21592
21662
|
`) || "";
|
|
21593
|
-
textPrompt = isResume ?
|
|
21663
|
+
textPrompt = isResume ? resumeDelta : frameReplayTurns(promptTurns);
|
|
21594
21664
|
}
|
|
21595
21665
|
const settingSources = envBool("LOAD_CONTEXT") || sdkFeatures.claudeMd === "full" ? ["user", "project"] : sdkFeatures.claudeMd === "project" ? ["project"] : pipelineCtx.settingSources ?? [];
|
|
21596
21666
|
const capturedToolUses = [];
|
|
@@ -21693,11 +21763,15 @@ data: ${JSON.stringify(lastError)}
|
|
|
21693
21763
|
}
|
|
21694
21764
|
const signature = toolUseSignature(toolName, toolInput);
|
|
21695
21765
|
const isExactDuplicate = capturedSignatures.has(signature);
|
|
21766
|
+
const isPostCheckpointCall = earlyStopFired;
|
|
21696
21767
|
const isSameToolRepeat = !earlyStopEnabled && !isExactDuplicate && capturedToolNames.has(toolName);
|
|
21697
21768
|
const exceedsForcedSingle = forceSingleToolUse && capturedToolUses.length >= 1;
|
|
21698
|
-
if (isExactDuplicate) {
|
|
21769
|
+
if (isExactDuplicate || isPostCheckpointCall) {
|
|
21699
21770
|
droppedToolUseIds.add(input.tool_use_id);
|
|
21700
|
-
claudeLog("passthrough.duplicate_tool_use_dropped", {
|
|
21771
|
+
claudeLog("passthrough.duplicate_tool_use_dropped", {
|
|
21772
|
+
name: toolName,
|
|
21773
|
+
reason: isPostCheckpointCall ? "hidden_digest" : "exact_duplicate"
|
|
21774
|
+
});
|
|
21701
21775
|
} else if (isSameToolRepeat || exceedsForcedSingle) {
|
|
21702
21776
|
droppedToolUseIds.add(input.tool_use_id);
|
|
21703
21777
|
sawDuplicateToolUse = true;
|
|
@@ -21718,10 +21792,10 @@ data: ${JSON.stringify(lastError)}
|
|
|
21718
21792
|
if (earlyStopEnabled && turnGenerating && !requestAbort.controller.signal.aborted) {
|
|
21719
21793
|
await holdDenyUntilTurnEnd();
|
|
21720
21794
|
}
|
|
21721
|
-
if (isExactDuplicate) {
|
|
21795
|
+
if (isExactDuplicate || isPostCheckpointCall) {
|
|
21722
21796
|
return {
|
|
21723
21797
|
decision: "block",
|
|
21724
|
-
reason: "This
|
|
21798
|
+
reason: "This tool call has already been handled by the client-facing turn — do not repeat it. " + "Do not call additional tools and do not generate further text — end your turn now."
|
|
21725
21799
|
};
|
|
21726
21800
|
}
|
|
21727
21801
|
if (isSameToolRepeat || exceedsForcedSingle) {
|
|
@@ -21753,13 +21827,15 @@ data: ${JSON.stringify(lastError)}
|
|
|
21753
21827
|
const upstreamStartAt = Date.now();
|
|
21754
21828
|
let firstChunkAt;
|
|
21755
21829
|
let currentSessionId;
|
|
21756
|
-
|
|
21830
|
+
let sdkUuidMap = (isResume || isUndo) && cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] : [];
|
|
21757
21831
|
while (sdkUuidMap.length < allMessages.length)
|
|
21758
21832
|
sdkUuidMap.push(null);
|
|
21759
21833
|
claudeLog("upstream.start", { mode: "non_stream", model });
|
|
21760
21834
|
let lastUsage;
|
|
21761
21835
|
let lastStopReason;
|
|
21762
|
-
let
|
|
21836
|
+
let nextPassthroughToolCallAssistantUuid;
|
|
21837
|
+
let nextPassthroughToolCallIds;
|
|
21838
|
+
let sawCanonicalResult = false;
|
|
21763
21839
|
try {
|
|
21764
21840
|
if (!claudeExecutable) {
|
|
21765
21841
|
claudeExecutable = await resolveClaudeExecutableAsync();
|
|
@@ -21797,8 +21873,8 @@ data: ${JSON.stringify(lastError)}
|
|
|
21797
21873
|
hasDeferredTools,
|
|
21798
21874
|
resumeSessionId,
|
|
21799
21875
|
isUndo,
|
|
21800
|
-
resumeSessionAtUuid: undoRollbackUuid ??
|
|
21801
|
-
forkSession: busySessionFork ||
|
|
21876
|
+
resumeSessionAtUuid: undoRollbackUuid ?? passthroughToolCallAssistantUuid,
|
|
21877
|
+
forkSession: busySessionFork || undefined,
|
|
21802
21878
|
sdkHooks,
|
|
21803
21879
|
blockedTools: pipelineCtx.blockedTools,
|
|
21804
21880
|
incompatibleTools: pipelineCtx.incompatibleTools,
|
|
@@ -22031,25 +22107,33 @@ data: ${JSON.stringify(lastError)}
|
|
|
22031
22107
|
claudeLog("passthrough.loop_break", { mode: "non_stream", assistantMessages, captured: capturedToolUses.length });
|
|
22032
22108
|
break;
|
|
22033
22109
|
}
|
|
22034
|
-
|
|
22035
|
-
|
|
22036
|
-
|
|
22037
|
-
|
|
22038
|
-
|
|
22039
|
-
|
|
22040
|
-
|
|
22041
|
-
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22110
|
+
let assistantAddedForwardedCall = false;
|
|
22111
|
+
if (passthrough && message.type === "assistant" && !earlyStopFired && earlyStop.resolved.size === 0) {
|
|
22112
|
+
const expectedBefore = earlyStop.expected.size;
|
|
22113
|
+
noteAssistantMessage(earlyStop, message);
|
|
22114
|
+
assistantAddedForwardedCall = earlyStop.expected.size > expectedBefore;
|
|
22115
|
+
} else if (passthrough && message.type === "user" && !earlyStopFired) {
|
|
22116
|
+
noteUserContent(earlyStop, message.message?.content);
|
|
22117
|
+
if (earlyStopEnabled && shouldEarlyStop(earlyStop)) {
|
|
22118
|
+
nextPassthroughToolCallAssistantUuid = settledToolCallAssistantUuid(earlyStop);
|
|
22119
|
+
nextPassthroughToolCallIds = [...earlyStop.expected];
|
|
22120
|
+
earlyStopFired = true;
|
|
22121
|
+
for (let i = capturedToolUses.length - 1;i >= 0; i--) {
|
|
22122
|
+
if (!earlyStop.expected.has(capturedToolUses[i].id))
|
|
22123
|
+
capturedToolUses.splice(i, 1);
|
|
22045
22124
|
}
|
|
22125
|
+
claudeLog("passthrough.checkpoint_ready", {
|
|
22126
|
+
mode: "non_stream",
|
|
22127
|
+
captured: capturedToolUses.length,
|
|
22128
|
+
toolCallAssistantUuid: nextPassthroughToolCallAssistantUuid
|
|
22129
|
+
});
|
|
22046
22130
|
}
|
|
22047
22131
|
}
|
|
22048
22132
|
if (message.type === "assistant") {
|
|
22049
22133
|
releaseHeldDenies("assistant_message");
|
|
22050
22134
|
assistantMessages += 1;
|
|
22051
|
-
if (
|
|
22052
|
-
sdkUuidMap.
|
|
22135
|
+
if (!passthrough || earlyStop.expected.size === 0 || assistantAddedForwardedCall) {
|
|
22136
|
+
sdkUuidMap = withClientAssistantUuid(sdkUuidMap, allMessages.length, message.uuid);
|
|
22053
22137
|
}
|
|
22054
22138
|
if (!firstChunkAt) {
|
|
22055
22139
|
firstChunkAt = Date.now();
|
|
@@ -22093,11 +22177,12 @@ data: ${JSON.stringify(lastError)}
|
|
|
22093
22177
|
const msgUsage = message.message.usage;
|
|
22094
22178
|
if (msgUsage)
|
|
22095
22179
|
lastUsage = { ...lastUsage, ...msgUsage };
|
|
22096
|
-
if (typeof message.message.stop_reason === "string") {
|
|
22180
|
+
if (!isPassthroughTurn2 && typeof message.message.stop_reason === "string") {
|
|
22097
22181
|
lastStopReason = message.message.stop_reason;
|
|
22098
22182
|
}
|
|
22099
22183
|
}
|
|
22100
22184
|
if (message.type === "result") {
|
|
22185
|
+
sawCanonicalResult = true;
|
|
22101
22186
|
const resultUsage = message.usage;
|
|
22102
22187
|
if (resultUsage) {
|
|
22103
22188
|
lastUsage = { ...lastUsage, ...resultUsage };
|
|
@@ -22129,6 +22214,10 @@ data: ${JSON.stringify(lastError)}
|
|
|
22129
22214
|
}
|
|
22130
22215
|
} catch (error) {
|
|
22131
22216
|
releaseHeldDenies("non_stream_error");
|
|
22217
|
+
if (passthrough && capturedToolUses.length > 0 && !sawCanonicalResult) {
|
|
22218
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
22219
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "non_stream", reason: "drain_error" });
|
|
22220
|
+
}
|
|
22132
22221
|
const stderrOutput = stderrLines.join(`
|
|
22133
22222
|
`).trim();
|
|
22134
22223
|
if (stderrOutput && error instanceof Error && !error.message.includes(stderrOutput)) {
|
|
@@ -22283,8 +22372,14 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22283
22372
|
]);
|
|
22284
22373
|
}
|
|
22285
22374
|
if (currentSessionId && !isIndependentSession && !sawDuplicateToolUse) {
|
|
22286
|
-
|
|
22287
|
-
|
|
22375
|
+
const checkpointTurn = passthrough && contentBlocks.some((b) => b.type === "tool_use");
|
|
22376
|
+
if (checkpointTurn && (!earlyStopFired || !sawCanonicalResult)) {
|
|
22377
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
22378
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "non_stream" });
|
|
22379
|
+
} else {
|
|
22380
|
+
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, earlyStopFired ? nextPassthroughToolCallAssistantUuid : null, earlyStopFired ? nextPassthroughToolCallIds : null);
|
|
22381
|
+
commitSessionTurn();
|
|
22382
|
+
}
|
|
22288
22383
|
}
|
|
22289
22384
|
const responseSessionId = currentSessionId || resumeSessionId || `session_${Date.now()}`;
|
|
22290
22385
|
return new Response(JSON.stringify({
|
|
@@ -22325,6 +22420,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22325
22420
|
let bytesSent = 0;
|
|
22326
22421
|
let streamClosed = false;
|
|
22327
22422
|
let awaitingEarlyStopDrain = false;
|
|
22423
|
+
let exitedBeforeCanonicalTerminal = false;
|
|
22328
22424
|
claudeLog("upstream.start", { mode: "stream", model });
|
|
22329
22425
|
const safeEnqueue = (payload, source) => {
|
|
22330
22426
|
if (streamClosed)
|
|
@@ -22346,14 +22442,16 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22346
22442
|
throw error;
|
|
22347
22443
|
}
|
|
22348
22444
|
};
|
|
22349
|
-
|
|
22445
|
+
let sdkUuidMap = (isResume || isUndo) && cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] : [];
|
|
22350
22446
|
while (sdkUuidMap.length < allMessages.length)
|
|
22351
22447
|
sdkUuidMap.push(null);
|
|
22352
22448
|
let messageStartEmitted = false;
|
|
22353
22449
|
let lastUsage;
|
|
22354
22450
|
let hasStructuredOutput = false;
|
|
22355
22451
|
let structuredOutput;
|
|
22356
|
-
let
|
|
22452
|
+
let nextPassthroughToolCallAssistantUuid;
|
|
22453
|
+
let nextPassthroughToolCallIds;
|
|
22454
|
+
let sawCanonicalResult = false;
|
|
22357
22455
|
const silentTurnRecoveryEnabled = env("SILENT_TURN_RECOVERY") !== "0";
|
|
22358
22456
|
let silentTurnRecoveryAttempted = false;
|
|
22359
22457
|
let silentTurnRecovered = false;
|
|
@@ -22378,33 +22476,6 @@ data: ${JSON.stringify({
|
|
|
22378
22476
|
eventsForwarded += 1;
|
|
22379
22477
|
};
|
|
22380
22478
|
const openClientBlocks = new Set;
|
|
22381
|
-
let pendingEarlyStop = false;
|
|
22382
|
-
let pendingEarlyStopAt = 0;
|
|
22383
|
-
const fireEarlyStop = (reason) => {
|
|
22384
|
-
earlyStopFired = true;
|
|
22385
|
-
claudeLog("passthrough.early_stop", {
|
|
22386
|
-
mode: "stream",
|
|
22387
|
-
captured: capturedToolUses.length,
|
|
22388
|
-
drained: awaitingEarlyStopDrain,
|
|
22389
|
-
reason,
|
|
22390
|
-
deferredMs: pendingEarlyStopAt ? Date.now() - pendingEarlyStopAt : 0
|
|
22391
|
-
});
|
|
22392
|
-
pendingEarlyStop = false;
|
|
22393
|
-
flushOpenClientBlocks("early_stop");
|
|
22394
|
-
sendTerminalDelta("tool_use");
|
|
22395
|
-
safeEnqueue(encoder.encode(`event: message_stop
|
|
22396
|
-
data: ${JSON.stringify({ type: "message_stop" })}
|
|
22397
|
-
|
|
22398
|
-
`), "early_stop");
|
|
22399
|
-
requestAbort.abort("passthrough turn complete");
|
|
22400
|
-
awaitingEarlyStopDrain = false;
|
|
22401
|
-
if (!streamClosed) {
|
|
22402
|
-
streamClosed = true;
|
|
22403
|
-
try {
|
|
22404
|
-
controller.close();
|
|
22405
|
-
} catch {}
|
|
22406
|
-
}
|
|
22407
|
-
};
|
|
22408
22479
|
const flushOpenClientBlocks = (source) => {
|
|
22409
22480
|
if (openClientBlocks.size === 0)
|
|
22410
22481
|
return;
|
|
@@ -22455,8 +22526,8 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22455
22526
|
hasDeferredTools,
|
|
22456
22527
|
resumeSessionId,
|
|
22457
22528
|
isUndo,
|
|
22458
|
-
resumeSessionAtUuid: undoRollbackUuid ??
|
|
22459
|
-
forkSession: busySessionFork ||
|
|
22529
|
+
resumeSessionAtUuid: undoRollbackUuid ?? passthroughToolCallAssistantUuid,
|
|
22530
|
+
forkSession: busySessionFork || undefined,
|
|
22460
22531
|
sdkHooks,
|
|
22461
22532
|
blockedTools: pipelineCtx.blockedTools,
|
|
22462
22533
|
incompatibleTools: pipelineCtx.incompatibleTools,
|
|
@@ -22716,38 +22787,42 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22716
22787
|
try {
|
|
22717
22788
|
for await (const message of guardedResponse) {
|
|
22718
22789
|
if (streamClosed && !awaitingEarlyStopDrain) {
|
|
22790
|
+
exitedBeforeCanonicalTerminal = true;
|
|
22719
22791
|
break;
|
|
22720
22792
|
}
|
|
22721
22793
|
if (message.session_id) {
|
|
22722
22794
|
currentSessionId = message.session_id;
|
|
22723
22795
|
}
|
|
22724
|
-
|
|
22725
|
-
|
|
22796
|
+
let assistantAddedForwardedCall = false;
|
|
22797
|
+
if (earlyStopEnabled && message.type === "assistant" && !earlyStopFired) {
|
|
22798
|
+
const expectedBefore = earlyStop.expected.size;
|
|
22799
|
+
noteAssistantMessage(earlyStop, message);
|
|
22800
|
+
assistantAddedForwardedCall = earlyStop.expected.size > expectedBefore;
|
|
22801
|
+
} else if (earlyStopEnabled && message.type === "user" && !earlyStopFired) {
|
|
22802
|
+
noteUserContent(earlyStop, message.message?.content);
|
|
22726
22803
|
}
|
|
22727
|
-
|
|
22728
|
-
|
|
22729
|
-
if (
|
|
22730
|
-
|
|
22731
|
-
|
|
22732
|
-
|
|
22733
|
-
|
|
22734
|
-
if (
|
|
22735
|
-
|
|
22736
|
-
pendingEarlyStop = true;
|
|
22737
|
-
pendingEarlyStopAt = Date.now();
|
|
22738
|
-
claudeLog("passthrough.early_stop_deferred", {
|
|
22739
|
-
openBlocks: openClientBlocks.size,
|
|
22740
|
-
captured: capturedToolUses.length
|
|
22741
|
-
});
|
|
22742
|
-
}
|
|
22743
|
-
} else {
|
|
22744
|
-
fireEarlyStop("immediate");
|
|
22745
|
-
break;
|
|
22746
|
-
}
|
|
22804
|
+
if (earlyStopEnabled && !earlyStopFired) {
|
|
22805
|
+
const hasCompleteStreamedSet = streamedToolUseIds.size > 0 && earlyStop.expected.size === streamedToolUseIds.size && [...streamedToolUseIds].every((id) => earlyStop.expected.has(id));
|
|
22806
|
+
if (!turnGenerating && openClientBlocks.size === 0 && hasCompleteStreamedSet && shouldEarlyStop(earlyStop)) {
|
|
22807
|
+
nextPassthroughToolCallAssistantUuid = settledToolCallAssistantUuid(earlyStop);
|
|
22808
|
+
nextPassthroughToolCallIds = [...earlyStop.expected];
|
|
22809
|
+
earlyStopFired = true;
|
|
22810
|
+
for (let i = capturedToolUses.length - 1;i >= 0; i--) {
|
|
22811
|
+
if (!earlyStop.expected.has(capturedToolUses[i].id))
|
|
22812
|
+
capturedToolUses.splice(i, 1);
|
|
22747
22813
|
}
|
|
22814
|
+
claudeLog("passthrough.checkpoint_ready", {
|
|
22815
|
+
mode: "stream",
|
|
22816
|
+
captured: capturedToolUses.length,
|
|
22817
|
+
toolCallAssistantUuid: nextPassthroughToolCallAssistantUuid
|
|
22818
|
+
});
|
|
22748
22819
|
}
|
|
22749
22820
|
}
|
|
22821
|
+
if (message.type === "assistant" && (!passthrough || earlyStop.expected.size === 0 || assistantAddedForwardedCall)) {
|
|
22822
|
+
sdkUuidMap = withClientAssistantUuid(sdkUuidMap, allMessages.length, message.uuid);
|
|
22823
|
+
}
|
|
22750
22824
|
if (message.type === "result") {
|
|
22825
|
+
sawCanonicalResult = true;
|
|
22751
22826
|
const resultUsage = message.usage;
|
|
22752
22827
|
if (resultUsage)
|
|
22753
22828
|
lastUsage = { ...lastUsage, ...resultUsage };
|
|
@@ -22757,6 +22832,8 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22757
22832
|
}
|
|
22758
22833
|
}
|
|
22759
22834
|
if (message.type === "stream_event") {
|
|
22835
|
+
if (streamClosed && awaitingEarlyStopDrain)
|
|
22836
|
+
continue;
|
|
22760
22837
|
streamEventsSeen += 1;
|
|
22761
22838
|
if (!firstChunkAt) {
|
|
22762
22839
|
firstChunkAt = Date.now();
|
|
@@ -22796,16 +22873,19 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22796
22873
|
lastUsage = { ...lastUsage, ...startUsage };
|
|
22797
22874
|
if (messageStartEmitted) {
|
|
22798
22875
|
if (passthrough && streamedToolUseIds.size > 0) {
|
|
22799
|
-
|
|
22800
|
-
|
|
22801
|
-
|
|
22876
|
+
if (!streamClosed) {
|
|
22877
|
+
flushOpenClientBlocks("turn2_suppression");
|
|
22878
|
+
sendTerminalDelta("tool_use");
|
|
22879
|
+
safeEnqueue(encoder.encode(`event: message_stop
|
|
22802
22880
|
data: ${JSON.stringify({ type: "message_stop" })}
|
|
22803
22881
|
|
|
22804
22882
|
`), "passthrough_turn2_stop");
|
|
22883
|
+
streamClosed = true;
|
|
22884
|
+
controller.close();
|
|
22885
|
+
}
|
|
22886
|
+
awaitingEarlyStopDrain = true;
|
|
22805
22887
|
claudeLog("passthrough.turn2_suppressed", { mode: "stream", toolUses: streamedToolUseIds.size });
|
|
22806
|
-
|
|
22807
|
-
controller.close();
|
|
22808
|
-
break;
|
|
22888
|
+
continue;
|
|
22809
22889
|
}
|
|
22810
22890
|
continue;
|
|
22811
22891
|
}
|
|
@@ -22929,10 +23009,6 @@ data: ${JSON.stringify(event)}
|
|
|
22929
23009
|
const idx = event.index;
|
|
22930
23010
|
if (typeof idx === "number")
|
|
22931
23011
|
openClientBlocks.delete(idx);
|
|
22932
|
-
if (pendingEarlyStop && openClientBlocks.size === 0) {
|
|
22933
|
-
fireEarlyStop("blocks_closed");
|
|
22934
|
-
break;
|
|
22935
|
-
}
|
|
22936
23012
|
}
|
|
22937
23013
|
if (passthrough && eventType === "message_delta" && event.delta?.stop_reason === "tool_use" && streamedToolUseIds.size > 0) {
|
|
22938
23014
|
flushOpenClientBlocks("drain_close");
|
|
@@ -22947,6 +23023,7 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
22947
23023
|
awaitingEarlyStopDrain = true;
|
|
22948
23024
|
continue;
|
|
22949
23025
|
}
|
|
23026
|
+
exitedBeforeCanonicalTerminal = true;
|
|
22950
23027
|
break;
|
|
22951
23028
|
}
|
|
22952
23029
|
if (eventType === "content_block_delta") {
|
|
@@ -23042,8 +23119,14 @@ data: ${JSON.stringify({
|
|
|
23042
23119
|
plog(`[PROXY] ${requestMeta.requestId} discovered=${discoveredTools.size} (${newNames}) session_total=${allNames.length}`);
|
|
23043
23120
|
}
|
|
23044
23121
|
if (currentSessionId && !isIndependentSession && !sawDuplicateToolUse) {
|
|
23045
|
-
|
|
23046
|
-
|
|
23122
|
+
const checkpointTurn = passthrough && streamedToolUseIds.size > 0;
|
|
23123
|
+
if (exitedBeforeCanonicalTerminal || checkpointTurn && (!earlyStopFired || !sawCanonicalResult)) {
|
|
23124
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23125
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "stream" });
|
|
23126
|
+
} else {
|
|
23127
|
+
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, earlyStopFired ? nextPassthroughToolCallAssistantUuid : null, earlyStopFired ? nextPassthroughToolCallIds : null);
|
|
23128
|
+
commitSessionTurn();
|
|
23129
|
+
}
|
|
23047
23130
|
}
|
|
23048
23131
|
const classifyNow = () => classifyTurnOutcome({
|
|
23049
23132
|
textEvents: textEventsForwarded,
|
|
@@ -23068,7 +23151,8 @@ data: ${JSON.stringify({
|
|
|
23068
23151
|
});
|
|
23069
23152
|
const recoveryLifter = createRecoveryLifter(() => nextClientBlockIndex++);
|
|
23070
23153
|
let recoverySessionId;
|
|
23071
|
-
let
|
|
23154
|
+
let recoveryToolCallAssistantUuid;
|
|
23155
|
+
const recoveryEarlyStop = createEarlyStopTracker();
|
|
23072
23156
|
try {
|
|
23073
23157
|
for await (const event of runSdkQueryAttempt(buildQueryOptions({
|
|
23074
23158
|
prompt: SILENT_TURN_NUDGE,
|
|
@@ -23086,7 +23170,7 @@ data: ${JSON.stringify({
|
|
|
23086
23170
|
hasDeferredTools,
|
|
23087
23171
|
resumeSessionId: currentSessionId || resumeSessionId,
|
|
23088
23172
|
isUndo: false,
|
|
23089
|
-
resumeSessionAtUuid:
|
|
23173
|
+
resumeSessionAtUuid: nextPassthroughToolCallAssistantUuid,
|
|
23090
23174
|
forkSession: true,
|
|
23091
23175
|
sdkHooks,
|
|
23092
23176
|
blockedTools: pipelineCtx.blockedTools,
|
|
@@ -23116,7 +23200,12 @@ data: ${JSON.stringify({
|
|
|
23116
23200
|
const recoveryMessage = event;
|
|
23117
23201
|
if (recoveryMessage.session_id)
|
|
23118
23202
|
recoverySessionId = recoveryMessage.session_id;
|
|
23119
|
-
|
|
23203
|
+
if (recoveryMessage.type === "assistant") {
|
|
23204
|
+
noteAssistantMessage(recoveryEarlyStop, recoveryMessage);
|
|
23205
|
+
} else if (recoveryMessage.type === "user") {
|
|
23206
|
+
noteUserContent(recoveryEarlyStop, recoveryMessage.message?.content);
|
|
23207
|
+
recoveryToolCallAssistantUuid = settledToolCallAssistantUuid(recoveryEarlyStop);
|
|
23208
|
+
}
|
|
23120
23209
|
if (recoveryMessage.type !== "stream_event")
|
|
23121
23210
|
continue;
|
|
23122
23211
|
const lifted = recoveryLifter.lift(event.event);
|
|
@@ -23145,11 +23234,12 @@ data: ${JSON.stringify(lifted.frame)}
|
|
|
23145
23234
|
}
|
|
23146
23235
|
if (silentTurnRecovered && recoverySessionId && !isIndependentSession && !sawDuplicateToolUse) {
|
|
23147
23236
|
currentSessionId = recoverySessionId;
|
|
23148
|
-
|
|
23237
|
+
nextPassthroughToolCallAssistantUuid = recoveryToolCallAssistantUuid;
|
|
23238
|
+
nextPassthroughToolCallIds = recoveryToolCallAssistantUuid ? [...recoveryEarlyStop.expected] : undefined;
|
|
23149
23239
|
sdkUuidMap.length = 0;
|
|
23150
23240
|
for (let i = 0;i < allMessages.length; i++)
|
|
23151
23241
|
sdkUuidMap.push(null);
|
|
23152
|
-
storeSession(profileSessionId, body.messages || [], recoverySessionId, profileScopedCwd, sdkUuidMap, lastUsage,
|
|
23242
|
+
storeSession(profileSessionId, body.messages || [], recoverySessionId, profileScopedCwd, sdkUuidMap, lastUsage, recoveryToolCallAssistantUuid ?? null, recoveryToolCallAssistantUuid ? [...recoveryEarlyStop.expected] : null);
|
|
23153
23243
|
commitSessionTurn();
|
|
23154
23244
|
}
|
|
23155
23245
|
claudeLog("response.silent_turn_recovery_result", {
|
|
@@ -23327,18 +23417,19 @@ data: {"type":"message_stop"}
|
|
|
23327
23417
|
profileSessionId,
|
|
23328
23418
|
currentSessionId,
|
|
23329
23419
|
sawDuplicateToolUse,
|
|
23330
|
-
|
|
23420
|
+
toolCallAssistantUuid: nextPassthroughToolCallAssistantUuid,
|
|
23331
23421
|
passthrough
|
|
23332
23422
|
});
|
|
23333
|
-
if (disposition.action === "
|
|
23334
|
-
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, disposition.resumeUuid);
|
|
23335
|
-
commitSessionTurn();
|
|
23336
|
-
} else if (disposition.action === "evict") {
|
|
23423
|
+
if (disposition.action === "evict") {
|
|
23337
23424
|
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23338
23425
|
}
|
|
23339
23426
|
claudeLog("passthrough.client_abort_settled", { action: disposition.action });
|
|
23340
23427
|
return;
|
|
23341
23428
|
}
|
|
23429
|
+
if (passthrough && streamedToolUseIds.size > 0 && !sawCanonicalResult) {
|
|
23430
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23431
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "stream", reason: "drain_error" });
|
|
23432
|
+
}
|
|
23342
23433
|
const stderrOutput = stderrLines.join(`
|
|
23343
23434
|
`).trim();
|
|
23344
23435
|
if (stderrOutput && error instanceof Error && !error.message.includes(stderrOutput)) {
|
|
@@ -23366,7 +23457,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
23366
23457
|
reason: sdkTerm.reason,
|
|
23367
23458
|
passthrough,
|
|
23368
23459
|
capturedToolUses: capturedToolUses.length,
|
|
23369
|
-
abortIsOurs: sawDuplicateToolUse
|
|
23460
|
+
abortIsOurs: sawDuplicateToolUse
|
|
23370
23461
|
}) && messageStartEmitted;
|
|
23371
23462
|
if (canRecoverAsToolUse) {
|
|
23372
23463
|
diagnosticLog2.session(`${requestMeta.requestId} sdk_termination_recovered ${formatSdkTermination(sdkTerm, {
|
|
@@ -23549,6 +23640,10 @@ data: ${JSON.stringify({
|
|
|
23549
23640
|
cancel(reason) {
|
|
23550
23641
|
requestAbort.abort(reason);
|
|
23551
23642
|
requestAbort.detach();
|
|
23643
|
+
if (!isIndependentSession) {
|
|
23644
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23645
|
+
claudeLog("passthrough.client_abort_settled", { action: "evict", source: "stream_cancel" });
|
|
23646
|
+
}
|
|
23552
23647
|
}
|
|
23553
23648
|
});
|
|
23554
23649
|
const streamSessionId = resumeSessionId || `session_${Date.now()}`;
|