@rynfar/meridian 1.62.2 → 1.62.4
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-7jgse65q.js → cli-n1jsth00.js} +262 -166
- package/dist/cli.js +1 -1
- package/dist/proxy/concurrency.d.ts +19 -2
- package/dist/proxy/concurrency.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
|
@@ -1974,13 +1974,6 @@ ${history}
|
|
|
1974
1974
|
|
|
1975
1975
|
` + last.text;
|
|
1976
1976
|
}
|
|
1977
|
-
function framePassthroughContinuation(delta) {
|
|
1978
|
-
if (!delta)
|
|
1979
|
-
return delta;
|
|
1980
|
-
return `${PASSTHROUGH_CONTINUATION_LEAD_IN}
|
|
1981
|
-
|
|
1982
|
-
${delta}`;
|
|
1983
|
-
}
|
|
1984
1977
|
function stripNonStandardStreamFields(event) {
|
|
1985
1978
|
if (event && typeof event === "object") {
|
|
1986
1979
|
const e = event;
|
|
@@ -2119,7 +2112,7 @@ function extractSystemText(system) {
|
|
|
2119
2112
|
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
2113
|
`);
|
|
2121
2114
|
}
|
|
2122
|
-
var HASH_IGNORED_BLOCK_TYPES, HASH_HANDLED_BLOCK_TYPES, HASH_SERIALIZED_BLOCK_TYPES,
|
|
2115
|
+
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
2116
|
var init_messages = __esm(() => {
|
|
2124
2117
|
HASH_IGNORED_BLOCK_TYPES = new Set(["thinking", "redacted_thinking"]);
|
|
2125
2118
|
HASH_HANDLED_BLOCK_TYPES = new Set(["text", "tool_use", "tool_result"]);
|
|
@@ -2136,7 +2129,6 @@ var init_messages = __esm(() => {
|
|
|
2136
2129
|
"tool_search_tool_result",
|
|
2137
2130
|
"container_upload"
|
|
2138
2131
|
]);
|
|
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
2132
|
MULTIMODAL_TYPES = new Set(["image", "document", "file"]);
|
|
2141
2133
|
TOOL_TARGET_KEYS = ["filePath", "file_path", "path", "command", "code", "pattern", "query", "url"];
|
|
2142
2134
|
TRANSPORT_HEADER_BLOCK = /^\s*x-anthropic-[a-z0-9-]*header\s*:/i;
|
|
@@ -6516,19 +6508,34 @@ function resolveMaxConcurrent(source = process.env, warn = console.warn) {
|
|
|
6516
6508
|
}
|
|
6517
6509
|
return DEFAULT_MAX_CONCURRENT;
|
|
6518
6510
|
}
|
|
6511
|
+
function assertPositiveLimit(limit) {
|
|
6512
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) {
|
|
6513
|
+
throw new RangeError("Semaphore limit must be a positive integer");
|
|
6514
|
+
}
|
|
6515
|
+
return limit;
|
|
6516
|
+
}
|
|
6519
6517
|
|
|
6520
6518
|
class AbortableSemaphore {
|
|
6521
|
-
limit;
|
|
6522
6519
|
activeCount = 0;
|
|
6520
|
+
currentLimit;
|
|
6523
6521
|
waiters = [];
|
|
6524
6522
|
constructor(limit) {
|
|
6525
|
-
this.
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6523
|
+
this.currentLimit = assertPositiveLimit(limit);
|
|
6524
|
+
}
|
|
6525
|
+
get limit() {
|
|
6526
|
+
return this.currentLimit;
|
|
6527
|
+
}
|
|
6528
|
+
setLimit(next) {
|
|
6529
|
+
const limit = assertPositiveLimit(next);
|
|
6530
|
+
if (limit === this.currentLimit)
|
|
6531
|
+
return;
|
|
6532
|
+
const raised = limit > this.currentLimit;
|
|
6533
|
+
this.currentLimit = limit;
|
|
6534
|
+
if (raised)
|
|
6535
|
+
this.grantNext();
|
|
6529
6536
|
}
|
|
6530
6537
|
get snapshot() {
|
|
6531
|
-
return { active: this.activeCount, queued: this.waiters.length, limit: this.
|
|
6538
|
+
return { active: this.activeCount, queued: this.waiters.length, limit: this.currentLimit };
|
|
6532
6539
|
}
|
|
6533
6540
|
acquire(signal) {
|
|
6534
6541
|
if (signal?.aborted)
|
|
@@ -6584,7 +6591,12 @@ class AbortableSemaphore {
|
|
|
6584
6591
|
}
|
|
6585
6592
|
}
|
|
6586
6593
|
function getProcessSdkSemaphore() {
|
|
6587
|
-
|
|
6594
|
+
const limit = resolveMaxConcurrent();
|
|
6595
|
+
if (!processSdkSemaphore) {
|
|
6596
|
+
processSdkSemaphore = new AbortableSemaphore(limit);
|
|
6597
|
+
return processSdkSemaphore;
|
|
6598
|
+
}
|
|
6599
|
+
processSdkSemaphore.setLimit(limit);
|
|
6588
6600
|
return processSdkSemaphore;
|
|
6589
6601
|
}
|
|
6590
6602
|
|
|
@@ -11091,6 +11103,17 @@ function noteAssistantContent(tracker, content) {
|
|
|
11091
11103
|
}
|
|
11092
11104
|
}
|
|
11093
11105
|
}
|
|
11106
|
+
function noteAssistantMessage(tracker, message) {
|
|
11107
|
+
const m = message;
|
|
11108
|
+
if (m?.type !== "assistant")
|
|
11109
|
+
return;
|
|
11110
|
+
const content = m.message?.content;
|
|
11111
|
+
const before = tracker.expected.size;
|
|
11112
|
+
noteAssistantContent(tracker, content);
|
|
11113
|
+
if (tracker.expected.size > before) {
|
|
11114
|
+
tracker.toolCallAssistantUuid = typeof m.uuid === "string" && m.uuid.length > 0 ? m.uuid : undefined;
|
|
11115
|
+
}
|
|
11116
|
+
}
|
|
11094
11117
|
function noteUserContent(tracker, content) {
|
|
11095
11118
|
if (!Array.isArray(content))
|
|
11096
11119
|
return;
|
|
@@ -11101,43 +11124,69 @@ function noteUserContent(tracker, content) {
|
|
|
11101
11124
|
}
|
|
11102
11125
|
}
|
|
11103
11126
|
}
|
|
11104
|
-
function
|
|
11105
|
-
if (tracker.fired)
|
|
11106
|
-
return false;
|
|
11127
|
+
function allForwardedCallsResolved(tracker) {
|
|
11107
11128
|
if (tracker.expected.size === 0)
|
|
11108
11129
|
return false;
|
|
11109
11130
|
for (const id of tracker.expected) {
|
|
11110
11131
|
if (!tracker.resolved.has(id))
|
|
11111
11132
|
return false;
|
|
11112
11133
|
}
|
|
11134
|
+
return true;
|
|
11135
|
+
}
|
|
11136
|
+
function isCompleteToolResultContinuation(messages, expectedIds) {
|
|
11137
|
+
if (expectedIds.length === 0 || messages.length === 0)
|
|
11138
|
+
return false;
|
|
11139
|
+
const expected = new Set(expectedIds);
|
|
11140
|
+
const actual = new Set;
|
|
11141
|
+
const echoedCalls = new Set;
|
|
11142
|
+
let sawUser = false;
|
|
11143
|
+
let sawNonToolResult = false;
|
|
11144
|
+
for (const message of messages) {
|
|
11145
|
+
if (message.role === "assistant" && !sawUser) {
|
|
11146
|
+
if (Array.isArray(message.content)) {
|
|
11147
|
+
for (const rawBlock of message.content) {
|
|
11148
|
+
const block = rawBlock;
|
|
11149
|
+
if (block?.type !== "tool_use")
|
|
11150
|
+
continue;
|
|
11151
|
+
if (typeof block.id !== "string" || !expected.has(block.id) || echoedCalls.has(block.id))
|
|
11152
|
+
return false;
|
|
11153
|
+
echoedCalls.add(block.id);
|
|
11154
|
+
}
|
|
11155
|
+
}
|
|
11156
|
+
continue;
|
|
11157
|
+
}
|
|
11158
|
+
if (message.role !== "user" || !Array.isArray(message.content) || sawUser)
|
|
11159
|
+
return false;
|
|
11160
|
+
sawUser = true;
|
|
11161
|
+
for (const rawBlock of message.content) {
|
|
11162
|
+
const block = rawBlock;
|
|
11163
|
+
if (block?.type === "tool_result") {
|
|
11164
|
+
if (sawNonToolResult || typeof block.tool_use_id !== "string")
|
|
11165
|
+
return false;
|
|
11166
|
+
if (!expected.has(block.tool_use_id) || actual.has(block.tool_use_id))
|
|
11167
|
+
return false;
|
|
11168
|
+
actual.add(block.tool_use_id);
|
|
11169
|
+
} else {
|
|
11170
|
+
sawNonToolResult = true;
|
|
11171
|
+
}
|
|
11172
|
+
}
|
|
11173
|
+
}
|
|
11174
|
+
return actual.size === expected.size && (echoedCalls.size === 0 || echoedCalls.size === expected.size);
|
|
11175
|
+
}
|
|
11176
|
+
function settledToolCallAssistantUuid(tracker) {
|
|
11177
|
+
return allForwardedCallsResolved(tracker) ? tracker.toolCallAssistantUuid : undefined;
|
|
11178
|
+
}
|
|
11179
|
+
function shouldEarlyStop(tracker) {
|
|
11180
|
+
if (tracker.fired || !settledToolCallAssistantUuid(tracker))
|
|
11181
|
+
return false;
|
|
11113
11182
|
tracker.fired = true;
|
|
11114
11183
|
return true;
|
|
11115
11184
|
}
|
|
11116
11185
|
function clientAbortDisposition(input) {
|
|
11117
11186
|
if (input.isIndependentSession || !input.profileSessionId)
|
|
11118
11187
|
return { action: "none" };
|
|
11119
|
-
if (!input.passthrough)
|
|
11120
|
-
return { action: "evict" };
|
|
11121
|
-
if (input.currentSessionId && !input.sawDuplicateToolUse && input.resumeBoundaryUuid) {
|
|
11122
|
-
return { action: "store", resumeUuid: input.resumeBoundaryUuid };
|
|
11123
|
-
}
|
|
11124
11188
|
return { action: "evict" };
|
|
11125
11189
|
}
|
|
11126
|
-
function resumeBoundaryUuid(message) {
|
|
11127
|
-
const m = message;
|
|
11128
|
-
if (m?.type !== "user")
|
|
11129
|
-
return;
|
|
11130
|
-
if (typeof m.uuid !== "string" || m.uuid.length === 0)
|
|
11131
|
-
return;
|
|
11132
|
-
const content = m.message?.content;
|
|
11133
|
-
if (!Array.isArray(content))
|
|
11134
|
-
return;
|
|
11135
|
-
const hasResult = content.some((block) => {
|
|
11136
|
-
const b = block;
|
|
11137
|
-
return b?.type === "tool_result";
|
|
11138
|
-
});
|
|
11139
|
-
return hasResult ? m.uuid : undefined;
|
|
11140
|
-
}
|
|
11141
11190
|
|
|
11142
11191
|
// src/proxy/envelopeIntegrity.ts
|
|
11143
11192
|
function checkEmptyToolInputs(contentBlocks, tools) {
|
|
@@ -20012,6 +20061,13 @@ function normalizeContextUsage(usage) {
|
|
|
20012
20061
|
return lastIteration ?? usage;
|
|
20013
20062
|
}
|
|
20014
20063
|
var MIN_SUFFIX_FOR_COMPACTION = 2;
|
|
20064
|
+
function withClientAssistantUuid(existing, clientMessageCount, uuid) {
|
|
20065
|
+
const next = existing.slice(0, clientMessageCount + 1);
|
|
20066
|
+
while (next.length < clientMessageCount)
|
|
20067
|
+
next.push(null);
|
|
20068
|
+
next[clientMessageCount] = typeof uuid === "string" && uuid.length > 0 ? uuid : null;
|
|
20069
|
+
return next;
|
|
20070
|
+
}
|
|
20015
20071
|
function computeLineageHash(messages) {
|
|
20016
20072
|
if (!messages || messages.length === 0)
|
|
20017
20073
|
return "";
|
|
@@ -20327,15 +20383,20 @@ function writeStore(store) {
|
|
|
20327
20383
|
}
|
|
20328
20384
|
}
|
|
20329
20385
|
}
|
|
20386
|
+
function hasLegacyUserDenialBoundary(session) {
|
|
20387
|
+
const legacy = session.passthroughResumeUuid;
|
|
20388
|
+
return typeof legacy === "string" && legacy.length > 0 && !session.passthroughToolCallAssistantUuid;
|
|
20389
|
+
}
|
|
20330
20390
|
function lookupSharedSession(key) {
|
|
20331
20391
|
const store = readStore();
|
|
20332
|
-
|
|
20392
|
+
const session = store[key];
|
|
20393
|
+
return session && !hasLegacyUserDenialBoundary(session) ? session : undefined;
|
|
20333
20394
|
}
|
|
20334
20395
|
function lookupSharedSessionByClaudeId(claudeSessionId) {
|
|
20335
20396
|
const sessions = Object.values(readStore());
|
|
20336
20397
|
let newest;
|
|
20337
20398
|
for (const session of sessions) {
|
|
20338
|
-
if (session.claudeSessionId !== claudeSessionId)
|
|
20399
|
+
if (session.claudeSessionId !== claudeSessionId || hasLegacyUserDenialBoundary(session))
|
|
20339
20400
|
continue;
|
|
20340
20401
|
if (!newest || session.lastUsedAt > newest.lastUsedAt) {
|
|
20341
20402
|
newest = session;
|
|
@@ -20343,7 +20404,7 @@ function lookupSharedSessionByClaudeId(claudeSessionId) {
|
|
|
20343
20404
|
}
|
|
20344
20405
|
return newest;
|
|
20345
20406
|
}
|
|
20346
|
-
function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes,
|
|
20407
|
+
function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes, passthroughToolCallAssistantUuid, passthroughToolCallIds) {
|
|
20347
20408
|
const path3 = getStorePath();
|
|
20348
20409
|
const lockPath = `${path3}.lock`;
|
|
20349
20410
|
const hasLock = skipLocking ? false : acquireLock(lockPath);
|
|
@@ -20363,7 +20424,8 @@ function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, mes
|
|
|
20363
20424
|
messageHashes: messageHashes ?? existing?.messageHashes,
|
|
20364
20425
|
messageBlockHashes: messageBlockHashes ?? existing?.messageBlockHashes,
|
|
20365
20426
|
sdkMessageUuids: sdkMessageUuids ?? existing?.sdkMessageUuids,
|
|
20366
|
-
|
|
20427
|
+
passthroughToolCallAssistantUuid: passthroughToolCallAssistantUuid === undefined ? existing?.passthroughToolCallAssistantUuid : passthroughToolCallAssistantUuid ?? undefined,
|
|
20428
|
+
passthroughToolCallIds: passthroughToolCallIds === undefined ? existing?.passthroughToolCallIds : passthroughToolCallIds ?? undefined,
|
|
20367
20429
|
contextUsage: contextUsage ?? existing?.contextUsage,
|
|
20368
20430
|
...previousClaudeSessionId ? { previousClaudeSessionId } : {}
|
|
20369
20431
|
};
|
|
@@ -20561,7 +20623,8 @@ function lookupSession(sessionId, messages, workingDirectory) {
|
|
|
20561
20623
|
messageHashes: shared.messageHashes,
|
|
20562
20624
|
messageBlockHashes: shared.messageBlockHashes,
|
|
20563
20625
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
20564
|
-
|
|
20626
|
+
passthroughToolCallAssistantUuid: shared.passthroughToolCallAssistantUuid,
|
|
20627
|
+
passthroughToolCallIds: shared.passthroughToolCallIds,
|
|
20565
20628
|
contextUsage: shared.contextUsage
|
|
20566
20629
|
};
|
|
20567
20630
|
const result = classifyLineage(state, messages, sessionId);
|
|
@@ -20591,7 +20654,8 @@ function lookupSession(sessionId, messages, workingDirectory) {
|
|
|
20591
20654
|
messageHashes: shared.messageHashes,
|
|
20592
20655
|
messageBlockHashes: shared.messageBlockHashes,
|
|
20593
20656
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
20594
|
-
|
|
20657
|
+
passthroughToolCallAssistantUuid: shared.passthroughToolCallAssistantUuid,
|
|
20658
|
+
passthroughToolCallIds: shared.passthroughToolCallIds,
|
|
20595
20659
|
contextUsage: shared.contextUsage
|
|
20596
20660
|
};
|
|
20597
20661
|
const result = classifyLineage(state, messages, fp);
|
|
@@ -20626,13 +20690,14 @@ function getSessionByClaudeId(claudeSessionId) {
|
|
|
20626
20690
|
messageHashes: shared.messageHashes,
|
|
20627
20691
|
messageBlockHashes: shared.messageBlockHashes,
|
|
20628
20692
|
sdkMessageUuids: shared.sdkMessageUuids,
|
|
20629
|
-
|
|
20693
|
+
passthroughToolCallAssistantUuid: shared.passthroughToolCallAssistantUuid,
|
|
20694
|
+
passthroughToolCallIds: shared.passthroughToolCallIds,
|
|
20630
20695
|
contextUsage: shared.contextUsage
|
|
20631
20696
|
});
|
|
20632
20697
|
}
|
|
20633
20698
|
return newest;
|
|
20634
20699
|
}
|
|
20635
|
-
function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sdkMessageUuids, contextUsage,
|
|
20700
|
+
function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sdkMessageUuids, contextUsage, passthroughToolCallAssistantUuid, passthroughToolCallIds) {
|
|
20636
20701
|
if (!claudeSessionId)
|
|
20637
20702
|
return;
|
|
20638
20703
|
const lineageHash = computeLineageHash(messages);
|
|
@@ -20646,7 +20711,8 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
|
|
|
20646
20711
|
messageHashes,
|
|
20647
20712
|
messageBlockHashes,
|
|
20648
20713
|
sdkMessageUuids,
|
|
20649
|
-
...
|
|
20714
|
+
...passthroughToolCallAssistantUuid ? { passthroughToolCallAssistantUuid } : {},
|
|
20715
|
+
...passthroughToolCallIds ? { passthroughToolCallIds } : {},
|
|
20650
20716
|
...contextUsage ? { contextUsage } : {}
|
|
20651
20717
|
};
|
|
20652
20718
|
if (sessionId)
|
|
@@ -20656,7 +20722,7 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
|
|
|
20656
20722
|
fingerprintCache.set(fp, state);
|
|
20657
20723
|
const key = sessionId || fp;
|
|
20658
20724
|
if (key) {
|
|
20659
|
-
storeSharedSession(key, claudeSessionId, state.messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes,
|
|
20725
|
+
storeSharedSession(key, claudeSessionId, state.messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes, passthroughToolCallAssistantUuid ?? null, passthroughToolCallIds ?? null);
|
|
20660
20726
|
}
|
|
20661
20727
|
}
|
|
20662
20728
|
|
|
@@ -20816,21 +20882,21 @@ function stripCacheControlDeep(content) {
|
|
|
20816
20882
|
return rest;
|
|
20817
20883
|
});
|
|
20818
20884
|
}
|
|
20819
|
-
function normalizeStructuredUserContent(content) {
|
|
20885
|
+
function normalizeStructuredUserContent(content, preserveToolResultWrapper = false) {
|
|
20820
20886
|
if (!Array.isArray(content))
|
|
20821
20887
|
return content;
|
|
20822
20888
|
const normalized = [];
|
|
20823
20889
|
for (const block of content) {
|
|
20824
20890
|
if (!block || typeof block !== "object")
|
|
20825
20891
|
continue;
|
|
20826
|
-
if (block.type === "tool_result" && Array.isArray(block.content) && hasMultimodalContent(block.content)) {
|
|
20892
|
+
if (!preserveToolResultWrapper && block.type === "tool_result" && Array.isArray(block.content) && hasMultimodalContent(block.content)) {
|
|
20827
20893
|
normalized.push(...normalizeStructuredUserContent(block.content));
|
|
20828
20894
|
continue;
|
|
20829
20895
|
}
|
|
20830
20896
|
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
20831
20897
|
normalized.push({
|
|
20832
20898
|
...block,
|
|
20833
|
-
content: normalizeStructuredUserContent(block.content)
|
|
20899
|
+
content: normalizeStructuredUserContent(block.content, preserveToolResultWrapper)
|
|
20834
20900
|
});
|
|
20835
20901
|
continue;
|
|
20836
20902
|
}
|
|
@@ -21437,15 +21503,16 @@ data: ${JSON.stringify(lastError)}
|
|
|
21437
21503
|
} : undefined
|
|
21438
21504
|
}, adapterBase);
|
|
21439
21505
|
}
|
|
21440
|
-
|
|
21506
|
+
let isResume = lineageResult.type === "continuation" || lineageResult.type === "compaction";
|
|
21441
21507
|
const isUndo = lineageResult.type === "undo";
|
|
21442
21508
|
const cachedSession = lineageResult.type !== "diverged" ? lineageResult.session : undefined;
|
|
21443
|
-
|
|
21509
|
+
let resumeSessionId = cachedSession?.claudeSessionId;
|
|
21444
21510
|
const passthrough = adapter.instancePassthrough !== undefined ? adapter.instancePassthrough : pipelineCtx.passthrough !== undefined ? pipelineCtx.passthrough : envBool("PASSTHROUGH");
|
|
21445
21511
|
const resumeFrom = lineageResult.type === "continuation" || lineageResult.type === "compaction" ? lineageResult.resumeFrom : undefined;
|
|
21446
21512
|
const resumeContentFrom = lineageResult.type === "continuation" ? lineageResult.resumeContentFrom : undefined;
|
|
21447
21513
|
const undoRollbackUuid = isUndo && lineageResult.type === "undo" ? lineageResult.rollbackUuid : undefined;
|
|
21448
|
-
|
|
21514
|
+
let passthroughToolCallAssistantUuid = passthrough && isResume ? cachedSession?.passthroughToolCallAssistantUuid : undefined;
|
|
21515
|
+
const passthroughToolCallIds = passthrough && isResume ? cachedSession?.passthroughToolCallIds : undefined;
|
|
21449
21516
|
const msgSummary = body.messages?.map((m) => {
|
|
21450
21517
|
const contentTypes = Array.isArray(m.content) ? m.content.map((b) => b.type).join(",") : "string";
|
|
21451
21518
|
return `${m.role}[${contentTypes}]`;
|
|
@@ -21511,17 +21578,28 @@ data: ${JSON.stringify(lastError)}
|
|
|
21511
21578
|
} else {
|
|
21512
21579
|
messagesToConvert = allMessages;
|
|
21513
21580
|
}
|
|
21581
|
+
if (passthroughToolCallAssistantUuid && !isCompleteToolResultContinuation(messagesToConvert, passthroughToolCallIds ?? [])) {
|
|
21582
|
+
claudeLog("passthrough.checkpoint_replay", {
|
|
21583
|
+
expectedToolIds: passthroughToolCallIds?.length ?? 0,
|
|
21584
|
+
reason: "incomplete_or_mismatched_results"
|
|
21585
|
+
});
|
|
21586
|
+
isResume = false;
|
|
21587
|
+
resumeSessionId = undefined;
|
|
21588
|
+
passthroughToolCallAssistantUuid = undefined;
|
|
21589
|
+
messagesToConvert = allMessages;
|
|
21590
|
+
}
|
|
21514
21591
|
const hasMultimodal = messagesToConvert?.some((m) => hasMultimodalContent(m.content));
|
|
21592
|
+
const hasPassthroughToolResults = Boolean(passthroughToolCallAssistantUuid) && messagesToConvert?.some((m) => m.role === "user" && Array.isArray(m.content) && m.content.some((block) => block?.type === "tool_result"));
|
|
21515
21593
|
let structuredMessages;
|
|
21516
21594
|
let textPrompt;
|
|
21517
|
-
if (hasMultimodal) {
|
|
21595
|
+
if (hasMultimodal || hasPassthroughToolResults) {
|
|
21518
21596
|
structuredMessages = [];
|
|
21519
21597
|
if (isResume) {
|
|
21520
21598
|
for (const m of messagesToConvert) {
|
|
21521
21599
|
if (m.role === "user") {
|
|
21522
21600
|
structuredMessages.push({
|
|
21523
21601
|
type: "user",
|
|
21524
|
-
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
21602
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content), Boolean(passthroughToolCallAssistantUuid)) },
|
|
21525
21603
|
parent_tool_use_id: null
|
|
21526
21604
|
});
|
|
21527
21605
|
}
|
|
@@ -21531,7 +21609,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21531
21609
|
if (m.role === "user") {
|
|
21532
21610
|
structuredMessages.push({
|
|
21533
21611
|
type: "user",
|
|
21534
|
-
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
21612
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content), Boolean(passthroughToolCallAssistantUuid)) },
|
|
21535
21613
|
parent_tool_use_id: null
|
|
21536
21614
|
});
|
|
21537
21615
|
} else {
|
|
@@ -21549,13 +21627,6 @@ data: ${JSON.stringify(lastError)}
|
|
|
21549
21627
|
if (structuredMessages.length > 1) {
|
|
21550
21628
|
structuredMessages = consolidateMultimodalOntoLastUser(structuredMessages);
|
|
21551
21629
|
}
|
|
21552
|
-
if (passthroughResumeUuid && structuredMessages.length > 0) {
|
|
21553
|
-
structuredMessages.unshift({
|
|
21554
|
-
type: "user",
|
|
21555
|
-
message: { role: "user", content: PASSTHROUGH_CONTINUATION_LEAD_IN },
|
|
21556
|
-
parent_tool_use_id: null
|
|
21557
|
-
});
|
|
21558
|
-
}
|
|
21559
21630
|
} else {
|
|
21560
21631
|
const toolIndex = buildToolUseIndex(allMessages ?? messagesToConvert ?? []);
|
|
21561
21632
|
const promptTurns = (messagesToConvert ?? []).map((m) => {
|
|
@@ -21570,7 +21641,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21570
21641
|
const resumeDelta = promptTurns.map((t) => t.text).filter(Boolean).join(`
|
|
21571
21642
|
|
|
21572
21643
|
`) || "";
|
|
21573
|
-
textPrompt = isResume ?
|
|
21644
|
+
textPrompt = isResume ? resumeDelta : frameReplayTurns(promptTurns);
|
|
21574
21645
|
}
|
|
21575
21646
|
const settingSources = envBool("LOAD_CONTEXT") || sdkFeatures.claudeMd === "full" ? ["user", "project"] : sdkFeatures.claudeMd === "project" ? ["project"] : pipelineCtx.settingSources ?? [];
|
|
21576
21647
|
const capturedToolUses = [];
|
|
@@ -21673,11 +21744,15 @@ data: ${JSON.stringify(lastError)}
|
|
|
21673
21744
|
}
|
|
21674
21745
|
const signature = toolUseSignature(toolName, toolInput);
|
|
21675
21746
|
const isExactDuplicate = capturedSignatures.has(signature);
|
|
21747
|
+
const isPostCheckpointCall = earlyStopFired;
|
|
21676
21748
|
const isSameToolRepeat = !earlyStopEnabled && !isExactDuplicate && capturedToolNames.has(toolName);
|
|
21677
21749
|
const exceedsForcedSingle = forceSingleToolUse && capturedToolUses.length >= 1;
|
|
21678
|
-
if (isExactDuplicate) {
|
|
21750
|
+
if (isExactDuplicate || isPostCheckpointCall) {
|
|
21679
21751
|
droppedToolUseIds.add(input.tool_use_id);
|
|
21680
|
-
claudeLog("passthrough.duplicate_tool_use_dropped", {
|
|
21752
|
+
claudeLog("passthrough.duplicate_tool_use_dropped", {
|
|
21753
|
+
name: toolName,
|
|
21754
|
+
reason: isPostCheckpointCall ? "hidden_digest" : "exact_duplicate"
|
|
21755
|
+
});
|
|
21681
21756
|
} else if (isSameToolRepeat || exceedsForcedSingle) {
|
|
21682
21757
|
droppedToolUseIds.add(input.tool_use_id);
|
|
21683
21758
|
sawDuplicateToolUse = true;
|
|
@@ -21698,10 +21773,10 @@ data: ${JSON.stringify(lastError)}
|
|
|
21698
21773
|
if (earlyStopEnabled && turnGenerating && !requestAbort.controller.signal.aborted) {
|
|
21699
21774
|
await holdDenyUntilTurnEnd();
|
|
21700
21775
|
}
|
|
21701
|
-
if (isExactDuplicate) {
|
|
21776
|
+
if (isExactDuplicate || isPostCheckpointCall) {
|
|
21702
21777
|
return {
|
|
21703
21778
|
decision: "block",
|
|
21704
|
-
reason: "This
|
|
21779
|
+
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."
|
|
21705
21780
|
};
|
|
21706
21781
|
}
|
|
21707
21782
|
if (isSameToolRepeat || exceedsForcedSingle) {
|
|
@@ -21733,13 +21808,15 @@ data: ${JSON.stringify(lastError)}
|
|
|
21733
21808
|
const upstreamStartAt = Date.now();
|
|
21734
21809
|
let firstChunkAt;
|
|
21735
21810
|
let currentSessionId;
|
|
21736
|
-
|
|
21811
|
+
let sdkUuidMap = (isResume || isUndo) && cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] : [];
|
|
21737
21812
|
while (sdkUuidMap.length < allMessages.length)
|
|
21738
21813
|
sdkUuidMap.push(null);
|
|
21739
21814
|
claudeLog("upstream.start", { mode: "non_stream", model });
|
|
21740
21815
|
let lastUsage;
|
|
21741
21816
|
let lastStopReason;
|
|
21742
|
-
let
|
|
21817
|
+
let nextPassthroughToolCallAssistantUuid;
|
|
21818
|
+
let nextPassthroughToolCallIds;
|
|
21819
|
+
let sawCanonicalResult = false;
|
|
21743
21820
|
try {
|
|
21744
21821
|
if (!claudeExecutable) {
|
|
21745
21822
|
claudeExecutable = await resolveClaudeExecutableAsync();
|
|
@@ -21777,8 +21854,8 @@ data: ${JSON.stringify(lastError)}
|
|
|
21777
21854
|
hasDeferredTools,
|
|
21778
21855
|
resumeSessionId,
|
|
21779
21856
|
isUndo,
|
|
21780
|
-
resumeSessionAtUuid: undoRollbackUuid ??
|
|
21781
|
-
forkSession: busySessionFork ||
|
|
21857
|
+
resumeSessionAtUuid: undoRollbackUuid ?? passthroughToolCallAssistantUuid,
|
|
21858
|
+
forkSession: busySessionFork || undefined,
|
|
21782
21859
|
sdkHooks,
|
|
21783
21860
|
blockedTools: pipelineCtx.blockedTools,
|
|
21784
21861
|
incompatibleTools: pipelineCtx.incompatibleTools,
|
|
@@ -22011,25 +22088,33 @@ data: ${JSON.stringify(lastError)}
|
|
|
22011
22088
|
claudeLog("passthrough.loop_break", { mode: "non_stream", assistantMessages, captured: capturedToolUses.length });
|
|
22012
22089
|
break;
|
|
22013
22090
|
}
|
|
22014
|
-
|
|
22015
|
-
|
|
22016
|
-
|
|
22017
|
-
|
|
22018
|
-
|
|
22019
|
-
|
|
22020
|
-
|
|
22021
|
-
|
|
22022
|
-
|
|
22023
|
-
|
|
22024
|
-
|
|
22091
|
+
let assistantAddedForwardedCall = false;
|
|
22092
|
+
if (passthrough && message.type === "assistant" && !earlyStopFired && earlyStop.resolved.size === 0) {
|
|
22093
|
+
const expectedBefore = earlyStop.expected.size;
|
|
22094
|
+
noteAssistantMessage(earlyStop, message);
|
|
22095
|
+
assistantAddedForwardedCall = earlyStop.expected.size > expectedBefore;
|
|
22096
|
+
} else if (passthrough && message.type === "user" && !earlyStopFired) {
|
|
22097
|
+
noteUserContent(earlyStop, message.message?.content);
|
|
22098
|
+
if (earlyStopEnabled && shouldEarlyStop(earlyStop)) {
|
|
22099
|
+
nextPassthroughToolCallAssistantUuid = settledToolCallAssistantUuid(earlyStop);
|
|
22100
|
+
nextPassthroughToolCallIds = [...earlyStop.expected];
|
|
22101
|
+
earlyStopFired = true;
|
|
22102
|
+
for (let i = capturedToolUses.length - 1;i >= 0; i--) {
|
|
22103
|
+
if (!earlyStop.expected.has(capturedToolUses[i].id))
|
|
22104
|
+
capturedToolUses.splice(i, 1);
|
|
22025
22105
|
}
|
|
22106
|
+
claudeLog("passthrough.checkpoint_ready", {
|
|
22107
|
+
mode: "non_stream",
|
|
22108
|
+
captured: capturedToolUses.length,
|
|
22109
|
+
toolCallAssistantUuid: nextPassthroughToolCallAssistantUuid
|
|
22110
|
+
});
|
|
22026
22111
|
}
|
|
22027
22112
|
}
|
|
22028
22113
|
if (message.type === "assistant") {
|
|
22029
22114
|
releaseHeldDenies("assistant_message");
|
|
22030
22115
|
assistantMessages += 1;
|
|
22031
|
-
if (
|
|
22032
|
-
sdkUuidMap.
|
|
22116
|
+
if (!passthrough || earlyStop.expected.size === 0 || assistantAddedForwardedCall) {
|
|
22117
|
+
sdkUuidMap = withClientAssistantUuid(sdkUuidMap, allMessages.length, message.uuid);
|
|
22033
22118
|
}
|
|
22034
22119
|
if (!firstChunkAt) {
|
|
22035
22120
|
firstChunkAt = Date.now();
|
|
@@ -22073,11 +22158,12 @@ data: ${JSON.stringify(lastError)}
|
|
|
22073
22158
|
const msgUsage = message.message.usage;
|
|
22074
22159
|
if (msgUsage)
|
|
22075
22160
|
lastUsage = { ...lastUsage, ...msgUsage };
|
|
22076
|
-
if (typeof message.message.stop_reason === "string") {
|
|
22161
|
+
if (!isPassthroughTurn2 && typeof message.message.stop_reason === "string") {
|
|
22077
22162
|
lastStopReason = message.message.stop_reason;
|
|
22078
22163
|
}
|
|
22079
22164
|
}
|
|
22080
22165
|
if (message.type === "result") {
|
|
22166
|
+
sawCanonicalResult = true;
|
|
22081
22167
|
const resultUsage = message.usage;
|
|
22082
22168
|
if (resultUsage) {
|
|
22083
22169
|
lastUsage = { ...lastUsage, ...resultUsage };
|
|
@@ -22109,6 +22195,10 @@ data: ${JSON.stringify(lastError)}
|
|
|
22109
22195
|
}
|
|
22110
22196
|
} catch (error) {
|
|
22111
22197
|
releaseHeldDenies("non_stream_error");
|
|
22198
|
+
if (passthrough && capturedToolUses.length > 0 && !sawCanonicalResult) {
|
|
22199
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
22200
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "non_stream", reason: "drain_error" });
|
|
22201
|
+
}
|
|
22112
22202
|
const stderrOutput = stderrLines.join(`
|
|
22113
22203
|
`).trim();
|
|
22114
22204
|
if (stderrOutput && error instanceof Error && !error.message.includes(stderrOutput)) {
|
|
@@ -22263,8 +22353,14 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22263
22353
|
]);
|
|
22264
22354
|
}
|
|
22265
22355
|
if (currentSessionId && !isIndependentSession && !sawDuplicateToolUse) {
|
|
22266
|
-
|
|
22267
|
-
|
|
22356
|
+
const checkpointTurn = passthrough && contentBlocks.some((b) => b.type === "tool_use");
|
|
22357
|
+
if (checkpointTurn && (!earlyStopFired || !sawCanonicalResult)) {
|
|
22358
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
22359
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "non_stream" });
|
|
22360
|
+
} else {
|
|
22361
|
+
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, earlyStopFired ? nextPassthroughToolCallAssistantUuid : null, earlyStopFired ? nextPassthroughToolCallIds : null);
|
|
22362
|
+
commitSessionTurn();
|
|
22363
|
+
}
|
|
22268
22364
|
}
|
|
22269
22365
|
const responseSessionId = currentSessionId || resumeSessionId || `session_${Date.now()}`;
|
|
22270
22366
|
return new Response(JSON.stringify({
|
|
@@ -22305,6 +22401,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22305
22401
|
let bytesSent = 0;
|
|
22306
22402
|
let streamClosed = false;
|
|
22307
22403
|
let awaitingEarlyStopDrain = false;
|
|
22404
|
+
let exitedBeforeCanonicalTerminal = false;
|
|
22308
22405
|
claudeLog("upstream.start", { mode: "stream", model });
|
|
22309
22406
|
const safeEnqueue = (payload, source) => {
|
|
22310
22407
|
if (streamClosed)
|
|
@@ -22326,14 +22423,16 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22326
22423
|
throw error;
|
|
22327
22424
|
}
|
|
22328
22425
|
};
|
|
22329
|
-
|
|
22426
|
+
let sdkUuidMap = (isResume || isUndo) && cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] : [];
|
|
22330
22427
|
while (sdkUuidMap.length < allMessages.length)
|
|
22331
22428
|
sdkUuidMap.push(null);
|
|
22332
22429
|
let messageStartEmitted = false;
|
|
22333
22430
|
let lastUsage;
|
|
22334
22431
|
let hasStructuredOutput = false;
|
|
22335
22432
|
let structuredOutput;
|
|
22336
|
-
let
|
|
22433
|
+
let nextPassthroughToolCallAssistantUuid;
|
|
22434
|
+
let nextPassthroughToolCallIds;
|
|
22435
|
+
let sawCanonicalResult = false;
|
|
22337
22436
|
const silentTurnRecoveryEnabled = env("SILENT_TURN_RECOVERY") !== "0";
|
|
22338
22437
|
let silentTurnRecoveryAttempted = false;
|
|
22339
22438
|
let silentTurnRecovered = false;
|
|
@@ -22358,33 +22457,6 @@ data: ${JSON.stringify({
|
|
|
22358
22457
|
eventsForwarded += 1;
|
|
22359
22458
|
};
|
|
22360
22459
|
const openClientBlocks = new Set;
|
|
22361
|
-
let pendingEarlyStop = false;
|
|
22362
|
-
let pendingEarlyStopAt = 0;
|
|
22363
|
-
const fireEarlyStop = (reason) => {
|
|
22364
|
-
earlyStopFired = true;
|
|
22365
|
-
claudeLog("passthrough.early_stop", {
|
|
22366
|
-
mode: "stream",
|
|
22367
|
-
captured: capturedToolUses.length,
|
|
22368
|
-
drained: awaitingEarlyStopDrain,
|
|
22369
|
-
reason,
|
|
22370
|
-
deferredMs: pendingEarlyStopAt ? Date.now() - pendingEarlyStopAt : 0
|
|
22371
|
-
});
|
|
22372
|
-
pendingEarlyStop = false;
|
|
22373
|
-
flushOpenClientBlocks("early_stop");
|
|
22374
|
-
sendTerminalDelta("tool_use");
|
|
22375
|
-
safeEnqueue(encoder.encode(`event: message_stop
|
|
22376
|
-
data: ${JSON.stringify({ type: "message_stop" })}
|
|
22377
|
-
|
|
22378
|
-
`), "early_stop");
|
|
22379
|
-
requestAbort.abort("passthrough turn complete");
|
|
22380
|
-
awaitingEarlyStopDrain = false;
|
|
22381
|
-
if (!streamClosed) {
|
|
22382
|
-
streamClosed = true;
|
|
22383
|
-
try {
|
|
22384
|
-
controller.close();
|
|
22385
|
-
} catch {}
|
|
22386
|
-
}
|
|
22387
|
-
};
|
|
22388
22460
|
const flushOpenClientBlocks = (source) => {
|
|
22389
22461
|
if (openClientBlocks.size === 0)
|
|
22390
22462
|
return;
|
|
@@ -22435,8 +22507,8 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22435
22507
|
hasDeferredTools,
|
|
22436
22508
|
resumeSessionId,
|
|
22437
22509
|
isUndo,
|
|
22438
|
-
resumeSessionAtUuid: undoRollbackUuid ??
|
|
22439
|
-
forkSession: busySessionFork ||
|
|
22510
|
+
resumeSessionAtUuid: undoRollbackUuid ?? passthroughToolCallAssistantUuid,
|
|
22511
|
+
forkSession: busySessionFork || undefined,
|
|
22440
22512
|
sdkHooks,
|
|
22441
22513
|
blockedTools: pipelineCtx.blockedTools,
|
|
22442
22514
|
incompatibleTools: pipelineCtx.incompatibleTools,
|
|
@@ -22696,38 +22768,42 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22696
22768
|
try {
|
|
22697
22769
|
for await (const message of guardedResponse) {
|
|
22698
22770
|
if (streamClosed && !awaitingEarlyStopDrain) {
|
|
22771
|
+
exitedBeforeCanonicalTerminal = true;
|
|
22699
22772
|
break;
|
|
22700
22773
|
}
|
|
22701
22774
|
if (message.session_id) {
|
|
22702
22775
|
currentSessionId = message.session_id;
|
|
22703
22776
|
}
|
|
22704
|
-
|
|
22705
|
-
|
|
22777
|
+
let assistantAddedForwardedCall = false;
|
|
22778
|
+
if (earlyStopEnabled && message.type === "assistant" && !earlyStopFired) {
|
|
22779
|
+
const expectedBefore = earlyStop.expected.size;
|
|
22780
|
+
noteAssistantMessage(earlyStop, message);
|
|
22781
|
+
assistantAddedForwardedCall = earlyStop.expected.size > expectedBefore;
|
|
22782
|
+
} else if (earlyStopEnabled && message.type === "user" && !earlyStopFired) {
|
|
22783
|
+
noteUserContent(earlyStop, message.message?.content);
|
|
22706
22784
|
}
|
|
22707
|
-
|
|
22708
|
-
|
|
22709
|
-
if (
|
|
22710
|
-
|
|
22711
|
-
|
|
22712
|
-
|
|
22713
|
-
|
|
22714
|
-
if (
|
|
22715
|
-
|
|
22716
|
-
pendingEarlyStop = true;
|
|
22717
|
-
pendingEarlyStopAt = Date.now();
|
|
22718
|
-
claudeLog("passthrough.early_stop_deferred", {
|
|
22719
|
-
openBlocks: openClientBlocks.size,
|
|
22720
|
-
captured: capturedToolUses.length
|
|
22721
|
-
});
|
|
22722
|
-
}
|
|
22723
|
-
} else {
|
|
22724
|
-
fireEarlyStop("immediate");
|
|
22725
|
-
break;
|
|
22726
|
-
}
|
|
22785
|
+
if (earlyStopEnabled && !earlyStopFired) {
|
|
22786
|
+
const hasCompleteStreamedSet = streamedToolUseIds.size > 0 && earlyStop.expected.size === streamedToolUseIds.size && [...streamedToolUseIds].every((id) => earlyStop.expected.has(id));
|
|
22787
|
+
if (!turnGenerating && openClientBlocks.size === 0 && hasCompleteStreamedSet && shouldEarlyStop(earlyStop)) {
|
|
22788
|
+
nextPassthroughToolCallAssistantUuid = settledToolCallAssistantUuid(earlyStop);
|
|
22789
|
+
nextPassthroughToolCallIds = [...earlyStop.expected];
|
|
22790
|
+
earlyStopFired = true;
|
|
22791
|
+
for (let i = capturedToolUses.length - 1;i >= 0; i--) {
|
|
22792
|
+
if (!earlyStop.expected.has(capturedToolUses[i].id))
|
|
22793
|
+
capturedToolUses.splice(i, 1);
|
|
22727
22794
|
}
|
|
22795
|
+
claudeLog("passthrough.checkpoint_ready", {
|
|
22796
|
+
mode: "stream",
|
|
22797
|
+
captured: capturedToolUses.length,
|
|
22798
|
+
toolCallAssistantUuid: nextPassthroughToolCallAssistantUuid
|
|
22799
|
+
});
|
|
22728
22800
|
}
|
|
22729
22801
|
}
|
|
22802
|
+
if (message.type === "assistant" && (!passthrough || earlyStop.expected.size === 0 || assistantAddedForwardedCall)) {
|
|
22803
|
+
sdkUuidMap = withClientAssistantUuid(sdkUuidMap, allMessages.length, message.uuid);
|
|
22804
|
+
}
|
|
22730
22805
|
if (message.type === "result") {
|
|
22806
|
+
sawCanonicalResult = true;
|
|
22731
22807
|
const resultUsage = message.usage;
|
|
22732
22808
|
if (resultUsage)
|
|
22733
22809
|
lastUsage = { ...lastUsage, ...resultUsage };
|
|
@@ -22737,6 +22813,8 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22737
22813
|
}
|
|
22738
22814
|
}
|
|
22739
22815
|
if (message.type === "stream_event") {
|
|
22816
|
+
if (streamClosed && awaitingEarlyStopDrain)
|
|
22817
|
+
continue;
|
|
22740
22818
|
streamEventsSeen += 1;
|
|
22741
22819
|
if (!firstChunkAt) {
|
|
22742
22820
|
firstChunkAt = Date.now();
|
|
@@ -22776,16 +22854,19 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22776
22854
|
lastUsage = { ...lastUsage, ...startUsage };
|
|
22777
22855
|
if (messageStartEmitted) {
|
|
22778
22856
|
if (passthrough && streamedToolUseIds.size > 0) {
|
|
22779
|
-
|
|
22780
|
-
|
|
22781
|
-
|
|
22857
|
+
if (!streamClosed) {
|
|
22858
|
+
flushOpenClientBlocks("turn2_suppression");
|
|
22859
|
+
sendTerminalDelta("tool_use");
|
|
22860
|
+
safeEnqueue(encoder.encode(`event: message_stop
|
|
22782
22861
|
data: ${JSON.stringify({ type: "message_stop" })}
|
|
22783
22862
|
|
|
22784
22863
|
`), "passthrough_turn2_stop");
|
|
22864
|
+
streamClosed = true;
|
|
22865
|
+
controller.close();
|
|
22866
|
+
}
|
|
22867
|
+
awaitingEarlyStopDrain = true;
|
|
22785
22868
|
claudeLog("passthrough.turn2_suppressed", { mode: "stream", toolUses: streamedToolUseIds.size });
|
|
22786
|
-
|
|
22787
|
-
controller.close();
|
|
22788
|
-
break;
|
|
22869
|
+
continue;
|
|
22789
22870
|
}
|
|
22790
22871
|
continue;
|
|
22791
22872
|
}
|
|
@@ -22909,10 +22990,6 @@ data: ${JSON.stringify(event)}
|
|
|
22909
22990
|
const idx = event.index;
|
|
22910
22991
|
if (typeof idx === "number")
|
|
22911
22992
|
openClientBlocks.delete(idx);
|
|
22912
|
-
if (pendingEarlyStop && openClientBlocks.size === 0) {
|
|
22913
|
-
fireEarlyStop("blocks_closed");
|
|
22914
|
-
break;
|
|
22915
|
-
}
|
|
22916
22993
|
}
|
|
22917
22994
|
if (passthrough && eventType === "message_delta" && event.delta?.stop_reason === "tool_use" && streamedToolUseIds.size > 0) {
|
|
22918
22995
|
flushOpenClientBlocks("drain_close");
|
|
@@ -22927,6 +23004,7 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
22927
23004
|
awaitingEarlyStopDrain = true;
|
|
22928
23005
|
continue;
|
|
22929
23006
|
}
|
|
23007
|
+
exitedBeforeCanonicalTerminal = true;
|
|
22930
23008
|
break;
|
|
22931
23009
|
}
|
|
22932
23010
|
if (eventType === "content_block_delta") {
|
|
@@ -23022,8 +23100,14 @@ data: ${JSON.stringify({
|
|
|
23022
23100
|
plog(`[PROXY] ${requestMeta.requestId} discovered=${discoveredTools.size} (${newNames}) session_total=${allNames.length}`);
|
|
23023
23101
|
}
|
|
23024
23102
|
if (currentSessionId && !isIndependentSession && !sawDuplicateToolUse) {
|
|
23025
|
-
|
|
23026
|
-
|
|
23103
|
+
const checkpointTurn = passthrough && streamedToolUseIds.size > 0;
|
|
23104
|
+
if (exitedBeforeCanonicalTerminal || checkpointTurn && (!earlyStopFired || !sawCanonicalResult)) {
|
|
23105
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23106
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "stream" });
|
|
23107
|
+
} else {
|
|
23108
|
+
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, earlyStopFired ? nextPassthroughToolCallAssistantUuid : null, earlyStopFired ? nextPassthroughToolCallIds : null);
|
|
23109
|
+
commitSessionTurn();
|
|
23110
|
+
}
|
|
23027
23111
|
}
|
|
23028
23112
|
const classifyNow = () => classifyTurnOutcome({
|
|
23029
23113
|
textEvents: textEventsForwarded,
|
|
@@ -23048,7 +23132,8 @@ data: ${JSON.stringify({
|
|
|
23048
23132
|
});
|
|
23049
23133
|
const recoveryLifter = createRecoveryLifter(() => nextClientBlockIndex++);
|
|
23050
23134
|
let recoverySessionId;
|
|
23051
|
-
let
|
|
23135
|
+
let recoveryToolCallAssistantUuid;
|
|
23136
|
+
const recoveryEarlyStop = createEarlyStopTracker();
|
|
23052
23137
|
try {
|
|
23053
23138
|
for await (const event of runSdkQueryAttempt(buildQueryOptions({
|
|
23054
23139
|
prompt: SILENT_TURN_NUDGE,
|
|
@@ -23066,7 +23151,7 @@ data: ${JSON.stringify({
|
|
|
23066
23151
|
hasDeferredTools,
|
|
23067
23152
|
resumeSessionId: currentSessionId || resumeSessionId,
|
|
23068
23153
|
isUndo: false,
|
|
23069
|
-
resumeSessionAtUuid:
|
|
23154
|
+
resumeSessionAtUuid: nextPassthroughToolCallAssistantUuid,
|
|
23070
23155
|
forkSession: true,
|
|
23071
23156
|
sdkHooks,
|
|
23072
23157
|
blockedTools: pipelineCtx.blockedTools,
|
|
@@ -23096,7 +23181,12 @@ data: ${JSON.stringify({
|
|
|
23096
23181
|
const recoveryMessage = event;
|
|
23097
23182
|
if (recoveryMessage.session_id)
|
|
23098
23183
|
recoverySessionId = recoveryMessage.session_id;
|
|
23099
|
-
|
|
23184
|
+
if (recoveryMessage.type === "assistant") {
|
|
23185
|
+
noteAssistantMessage(recoveryEarlyStop, recoveryMessage);
|
|
23186
|
+
} else if (recoveryMessage.type === "user") {
|
|
23187
|
+
noteUserContent(recoveryEarlyStop, recoveryMessage.message?.content);
|
|
23188
|
+
recoveryToolCallAssistantUuid = settledToolCallAssistantUuid(recoveryEarlyStop);
|
|
23189
|
+
}
|
|
23100
23190
|
if (recoveryMessage.type !== "stream_event")
|
|
23101
23191
|
continue;
|
|
23102
23192
|
const lifted = recoveryLifter.lift(event.event);
|
|
@@ -23125,11 +23215,12 @@ data: ${JSON.stringify(lifted.frame)}
|
|
|
23125
23215
|
}
|
|
23126
23216
|
if (silentTurnRecovered && recoverySessionId && !isIndependentSession && !sawDuplicateToolUse) {
|
|
23127
23217
|
currentSessionId = recoverySessionId;
|
|
23128
|
-
|
|
23218
|
+
nextPassthroughToolCallAssistantUuid = recoveryToolCallAssistantUuid;
|
|
23219
|
+
nextPassthroughToolCallIds = recoveryToolCallAssistantUuid ? [...recoveryEarlyStop.expected] : undefined;
|
|
23129
23220
|
sdkUuidMap.length = 0;
|
|
23130
23221
|
for (let i = 0;i < allMessages.length; i++)
|
|
23131
23222
|
sdkUuidMap.push(null);
|
|
23132
|
-
storeSession(profileSessionId, body.messages || [], recoverySessionId, profileScopedCwd, sdkUuidMap, lastUsage,
|
|
23223
|
+
storeSession(profileSessionId, body.messages || [], recoverySessionId, profileScopedCwd, sdkUuidMap, lastUsage, recoveryToolCallAssistantUuid ?? null, recoveryToolCallAssistantUuid ? [...recoveryEarlyStop.expected] : null);
|
|
23133
23224
|
commitSessionTurn();
|
|
23134
23225
|
}
|
|
23135
23226
|
claudeLog("response.silent_turn_recovery_result", {
|
|
@@ -23307,18 +23398,19 @@ data: {"type":"message_stop"}
|
|
|
23307
23398
|
profileSessionId,
|
|
23308
23399
|
currentSessionId,
|
|
23309
23400
|
sawDuplicateToolUse,
|
|
23310
|
-
|
|
23401
|
+
toolCallAssistantUuid: nextPassthroughToolCallAssistantUuid,
|
|
23311
23402
|
passthrough
|
|
23312
23403
|
});
|
|
23313
|
-
if (disposition.action === "
|
|
23314
|
-
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, disposition.resumeUuid);
|
|
23315
|
-
commitSessionTurn();
|
|
23316
|
-
} else if (disposition.action === "evict") {
|
|
23404
|
+
if (disposition.action === "evict") {
|
|
23317
23405
|
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23318
23406
|
}
|
|
23319
23407
|
claudeLog("passthrough.client_abort_settled", { action: disposition.action });
|
|
23320
23408
|
return;
|
|
23321
23409
|
}
|
|
23410
|
+
if (passthrough && streamedToolUseIds.size > 0 && !sawCanonicalResult) {
|
|
23411
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23412
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "stream", reason: "drain_error" });
|
|
23413
|
+
}
|
|
23322
23414
|
const stderrOutput = stderrLines.join(`
|
|
23323
23415
|
`).trim();
|
|
23324
23416
|
if (stderrOutput && error instanceof Error && !error.message.includes(stderrOutput)) {
|
|
@@ -23346,7 +23438,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
23346
23438
|
reason: sdkTerm.reason,
|
|
23347
23439
|
passthrough,
|
|
23348
23440
|
capturedToolUses: capturedToolUses.length,
|
|
23349
|
-
abortIsOurs: sawDuplicateToolUse
|
|
23441
|
+
abortIsOurs: sawDuplicateToolUse
|
|
23350
23442
|
}) && messageStartEmitted;
|
|
23351
23443
|
if (canRecoverAsToolUse) {
|
|
23352
23444
|
diagnosticLog2.session(`${requestMeta.requestId} sdk_termination_recovered ${formatSdkTermination(sdkTerm, {
|
|
@@ -23529,6 +23621,10 @@ data: ${JSON.stringify({
|
|
|
23529
23621
|
cancel(reason) {
|
|
23530
23622
|
requestAbort.abort(reason);
|
|
23531
23623
|
requestAbort.detach();
|
|
23624
|
+
if (!isIndependentSession) {
|
|
23625
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23626
|
+
claudeLog("passthrough.client_abort_settled", { action: "evict", source: "stream_cancel" });
|
|
23627
|
+
}
|
|
23532
23628
|
}
|
|
23533
23629
|
});
|
|
23534
23630
|
const streamSessionId = resumeSessionId || `session_${Date.now()}`;
|