claude-code-rust 0.14.1 → 0.14.2
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/agent-sdk/dist/bridge/available_commands.js +1 -1
- package/agent-sdk/dist/bridge/command_interactions.js +16 -0
- package/agent-sdk/dist/bridge/command_lifecycle.js +184 -0
- package/agent-sdk/dist/bridge/command_mcp.js +32 -0
- package/agent-sdk/dist/bridge/command_scheduler.js +136 -0
- package/agent-sdk/dist/bridge/command_session_control.js +269 -0
- package/agent-sdk/dist/bridge/command_session_data.js +203 -0
- package/agent-sdk/dist/bridge/commands.js +6 -0
- package/agent-sdk/dist/bridge/error_classification.js +24 -7
- package/agent-sdk/dist/bridge/events.js +42 -9
- package/agent-sdk/dist/bridge/history.js +7 -3
- package/agent-sdk/dist/bridge/logger.js +2 -0
- package/agent-sdk/dist/bridge/mcp.js +90 -80
- package/agent-sdk/dist/bridge/mcp_auth_adapter.js +67 -0
- package/agent-sdk/dist/bridge/mcp_monitor.js +59 -0
- package/agent-sdk/dist/bridge/message_handlers.js +11 -7
- package/agent-sdk/dist/bridge/session_lifecycle.js +54 -4
- package/agent-sdk/dist/bridge/state_parsing.js +7 -0
- package/agent-sdk/dist/bridge/tool_calls.js +5 -4
- package/agent-sdk/dist/bridge/tooling.js +53 -1
- package/agent-sdk/dist/bridge.js +118 -617
- package/package.json +8 -8
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { getSessionMessages, renameSession, } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { mapSdkAccountInfo } from "./account_metadata.js";
|
|
3
|
+
import { emitSessionsList, setSessionListingDir, slashError, writeEvent, } from "./events.js";
|
|
4
|
+
import { bridgeLogger, LOG_TARGETS } from "./logger.js";
|
|
5
|
+
import { refreshCurrentModel, sessionById, } from "./session_lifecycle.js";
|
|
6
|
+
export async function handleSessionDataCommand(command, requestId, deps) {
|
|
7
|
+
switch (command.command) {
|
|
8
|
+
case "generate_session_title":
|
|
9
|
+
await generateTitle(command, requestId, deps);
|
|
10
|
+
return;
|
|
11
|
+
case "rename_session":
|
|
12
|
+
await rename(command, requestId, deps);
|
|
13
|
+
return;
|
|
14
|
+
case "get_status_snapshot":
|
|
15
|
+
await getStatusSnapshot(command, requestId);
|
|
16
|
+
return;
|
|
17
|
+
case "get_context_usage":
|
|
18
|
+
await getContextUsage(command, requestId);
|
|
19
|
+
return;
|
|
20
|
+
case "get_rewind_targets":
|
|
21
|
+
await getRewindTargets(command, requestId, deps);
|
|
22
|
+
return;
|
|
23
|
+
case "rewind":
|
|
24
|
+
await deps.handleRewind(command, requestId);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function generateTitle(command, requestId, deps) {
|
|
28
|
+
const session = requireSession(command.session_id, requestId);
|
|
29
|
+
if (!session) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
await deps.generatePersistedSessionTitle(session.query, command.description);
|
|
34
|
+
setSessionListingDir(session.cwd);
|
|
35
|
+
await emitSessionsList(requestId);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
slashError(command.session_id, `failed to generate session title: ${message}`, requestId);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function rename(command, requestId, deps) {
|
|
43
|
+
const session = requireSession(command.session_id, requestId);
|
|
44
|
+
if (!session) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await renameSession(command.session_id, command.title, deps.buildSessionMutationOptions(session.cwd));
|
|
49
|
+
setSessionListingDir(session.cwd);
|
|
50
|
+
await emitSessionsList(requestId);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
slashError(command.session_id, `failed to rename session: ${message}`, requestId);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function getStatusSnapshot(command, requestId) {
|
|
58
|
+
const session = requireSession(command.session_id, requestId);
|
|
59
|
+
if (!session) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const account = await session.query.accountInfo();
|
|
64
|
+
bridgeLogger.info({
|
|
65
|
+
target: LOG_TARGETS.APP_AUTH,
|
|
66
|
+
eventName: "status_snapshot_emitted",
|
|
67
|
+
message: "status snapshot emitted",
|
|
68
|
+
outcome: "success",
|
|
69
|
+
...(requestId ? { requestId } : {}),
|
|
70
|
+
sessionId: session.sessionId,
|
|
71
|
+
fields: {
|
|
72
|
+
has_email: typeof account.email === "string" && account.email.trim().length > 0,
|
|
73
|
+
has_organization: account.organization !== undefined,
|
|
74
|
+
subscription_type: account.subscriptionType,
|
|
75
|
+
token_source: account.tokenSource,
|
|
76
|
+
api_key_source: account.apiKeySource,
|
|
77
|
+
api_provider: account.apiProvider,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
writeEvent({
|
|
81
|
+
event: "status_snapshot",
|
|
82
|
+
session_id: session.sessionId,
|
|
83
|
+
account: mapSdkAccountInfo(account),
|
|
84
|
+
}, requestId);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
88
|
+
bridgeLogger.warn({
|
|
89
|
+
target: LOG_TARGETS.APP_AUTH,
|
|
90
|
+
eventName: "status_snapshot_failed",
|
|
91
|
+
message: "failed to build status snapshot",
|
|
92
|
+
outcome: "failure",
|
|
93
|
+
...(requestId ? { requestId } : {}),
|
|
94
|
+
sessionId: session.sessionId,
|
|
95
|
+
fields: { error_message: message },
|
|
96
|
+
});
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function getContextUsage(command, requestId) {
|
|
101
|
+
const session = requireSession(command.session_id, requestId);
|
|
102
|
+
if (!session) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const usage = await session.query.getContextUsage();
|
|
107
|
+
if (typeof usage.model === "string" && usage.model.trim().length > 0) {
|
|
108
|
+
session.resolvedRuntimeModelId = usage.model.trim();
|
|
109
|
+
refreshCurrentModel(session, true);
|
|
110
|
+
}
|
|
111
|
+
const rawPercentage = typeof usage.percentage === "number" ? usage.percentage : undefined;
|
|
112
|
+
const normalizedPercentage = rawPercentage === undefined || !Number.isFinite(rawPercentage)
|
|
113
|
+
? undefined
|
|
114
|
+
: Math.max(0, Math.min(100, Math.round(rawPercentage)));
|
|
115
|
+
bridgeLogger.debug({
|
|
116
|
+
target: LOG_TARGETS.APP_SESSION,
|
|
117
|
+
eventName: "context_usage_succeeded",
|
|
118
|
+
message: "session context usage received from SDK",
|
|
119
|
+
outcome: "success",
|
|
120
|
+
...(requestId ? { requestId } : {}),
|
|
121
|
+
sessionId: session.sessionId,
|
|
122
|
+
fields: {
|
|
123
|
+
raw_percentage: rawPercentage,
|
|
124
|
+
normalized_percentage: normalizedPercentage,
|
|
125
|
+
total_tokens: typeof usage.totalTokens === "number" ? usage.totalTokens : undefined,
|
|
126
|
+
max_tokens: typeof usage.maxTokens === "number" ? usage.maxTokens : undefined,
|
|
127
|
+
raw_max_tokens: typeof usage.rawMaxTokens === "number" ? usage.rawMaxTokens : undefined,
|
|
128
|
+
model: typeof usage.model === "string" ? usage.model : undefined,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
writeEvent({
|
|
132
|
+
event: "context_usage",
|
|
133
|
+
session_id: session.sessionId,
|
|
134
|
+
...(normalizedPercentage !== undefined ? { percentage: normalizedPercentage } : {}),
|
|
135
|
+
}, requestId);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
139
|
+
bridgeLogger.warn({
|
|
140
|
+
target: LOG_TARGETS.APP_SESSION,
|
|
141
|
+
eventName: "context_usage_failed",
|
|
142
|
+
message: "failed to get session context usage",
|
|
143
|
+
outcome: "failure",
|
|
144
|
+
...(requestId ? { requestId } : {}),
|
|
145
|
+
sessionId: session.sessionId,
|
|
146
|
+
fields: { error_message: message },
|
|
147
|
+
});
|
|
148
|
+
writeEvent({
|
|
149
|
+
event: "context_usage",
|
|
150
|
+
session_id: session.sessionId,
|
|
151
|
+
}, requestId);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function getRewindTargets(command, requestId, deps) {
|
|
155
|
+
const session = requireSession(command.session_id, requestId);
|
|
156
|
+
if (!session) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const historyMessages = await getSessionMessages(command.session_id, {
|
|
161
|
+
dir: session.cwd,
|
|
162
|
+
includeSystemMessages: true,
|
|
163
|
+
});
|
|
164
|
+
const targets = deps.rewindTargetsFromSessionMessages(historyMessages);
|
|
165
|
+
bridgeLogger.info({
|
|
166
|
+
target: LOG_TARGETS.APP_SESSION,
|
|
167
|
+
eventName: "rewind_targets_loaded",
|
|
168
|
+
message: "rewind targets loaded from session history",
|
|
169
|
+
outcome: "success",
|
|
170
|
+
...(requestId ? { requestId } : {}),
|
|
171
|
+
sessionId: session.sessionId,
|
|
172
|
+
fields: {
|
|
173
|
+
history_message_count: historyMessages.length,
|
|
174
|
+
target_count: targets.length,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
writeEvent({
|
|
178
|
+
event: "rewind_targets",
|
|
179
|
+
session_id: session.sessionId,
|
|
180
|
+
targets,
|
|
181
|
+
}, requestId);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
bridgeLogger.warn({
|
|
186
|
+
target: LOG_TARGETS.APP_SESSION,
|
|
187
|
+
eventName: "rewind_targets_failed",
|
|
188
|
+
message: "failed to load rewind targets",
|
|
189
|
+
outcome: "failure",
|
|
190
|
+
...(requestId ? { requestId } : {}),
|
|
191
|
+
sessionId: session.sessionId,
|
|
192
|
+
fields: { error_message: message },
|
|
193
|
+
});
|
|
194
|
+
slashError(command.session_id, `failed to load rewind targets: ${message}`, requestId);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function requireSession(sessionId, requestId) {
|
|
198
|
+
const session = sessionById(sessionId);
|
|
199
|
+
if (!session) {
|
|
200
|
+
slashError(sessionId, `unknown session: ${sessionId}`, requestId);
|
|
201
|
+
}
|
|
202
|
+
return session;
|
|
203
|
+
}
|
|
@@ -266,6 +266,12 @@ export function parseCommandEnvelope(line) {
|
|
|
266
266
|
session_id: expectString(raw, "session_id", "set_agent"),
|
|
267
267
|
agent: expectNonEmptyStringOrNull(raw, "agent", "set_agent"),
|
|
268
268
|
};
|
|
269
|
+
case "set_fast_mode":
|
|
270
|
+
return {
|
|
271
|
+
command: "set_fast_mode",
|
|
272
|
+
session_id: expectString(raw, "session_id", "set_fast_mode"),
|
|
273
|
+
enabled: expectBoolean(raw, "enabled", "set_fast_mode"),
|
|
274
|
+
};
|
|
269
275
|
case "generate_session_title":
|
|
270
276
|
return {
|
|
271
277
|
command: "generate_session_title",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { looksLikeAuthRequired } from "./auth.js";
|
|
2
2
|
import { writeEvent } from "./events.js";
|
|
3
3
|
import { emitSessionUpdate } from "./events.js";
|
|
4
|
-
import { parseFastModeState } from "./state_parsing.js";
|
|
4
|
+
import { parseFastModeDisabledReason, parseFastModeState } from "./state_parsing.js";
|
|
5
5
|
export function emitAuthRequired(session, detail) {
|
|
6
6
|
if (session.authHintSent) {
|
|
7
7
|
return;
|
|
@@ -58,11 +58,28 @@ export function classifyTurnErrorKind(subtype, errors, assistantError) {
|
|
|
58
58
|
}
|
|
59
59
|
return "other";
|
|
60
60
|
}
|
|
61
|
-
export function
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
export function setFastModeSnapshotIfChanged(session, stateValue, disabledReasonValue) {
|
|
62
|
+
const nextState = parseFastModeState(stateValue) ?? session.fastModeState;
|
|
63
|
+
const nextDisabledReason = parseFastModeDisabledReason(disabledReasonValue);
|
|
64
|
+
if (nextState === session.fastModeState &&
|
|
65
|
+
nextDisabledReason === session.fastModeDisabledReason) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
session.fastModeState = nextState;
|
|
69
|
+
session.fastModeDisabledReason = nextDisabledReason;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
export function emitFastModeUpdate(session) {
|
|
73
|
+
emitSessionUpdate(session.sessionId, {
|
|
74
|
+
type: "fast_mode_update",
|
|
75
|
+
fast_mode_state: session.fastModeState,
|
|
76
|
+
...(session.fastModeDisabledReason
|
|
77
|
+
? { fast_mode_disabled_reason: session.fastModeDisabledReason }
|
|
78
|
+
: {}),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export function emitFastModeUpdateIfChanged(session, stateValue, disabledReasonValue) {
|
|
82
|
+
if (setFastModeSnapshotIfChanged(session, stateValue, disabledReasonValue)) {
|
|
83
|
+
emitFastModeUpdate(session);
|
|
65
84
|
}
|
|
66
|
-
session.fastModeState = next;
|
|
67
|
-
emitSessionUpdate(session.sessionId, { type: "fast_mode_update", fast_mode_state: next });
|
|
68
85
|
}
|
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
import { listSessions } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { writeSync } from "node:fs";
|
|
2
3
|
import { buildModeState } from "./commands.js";
|
|
3
4
|
import { mapSdkSessions } from "./history.js";
|
|
4
5
|
import { bridgeLogger, LOG_TARGETS, logBridgeEventSent } from "./logger.js";
|
|
5
|
-
import { resolveCurrentModel } from "./session_lifecycle.js";
|
|
6
|
+
import { detachSessionForClose, resolveCurrentModel, trackSessionCloseTask, } from "./session_lifecycle.js";
|
|
6
7
|
const SESSION_LIST_LIMIT = 50;
|
|
7
8
|
let sessionListingDir;
|
|
9
|
+
function writeProtocolEventToStdout(line) {
|
|
10
|
+
const payload = Buffer.from(line);
|
|
11
|
+
let offset = 0;
|
|
12
|
+
while (offset < payload.length) {
|
|
13
|
+
const written = writeSync(process.stdout.fd, payload, offset, payload.length - offset);
|
|
14
|
+
if (written <= 0) {
|
|
15
|
+
throw new Error("bridge stdout write made no progress");
|
|
16
|
+
}
|
|
17
|
+
offset += written;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
let protocolEventWriter = writeProtocolEventToStdout;
|
|
21
|
+
export function replaceProtocolEventWriter(writer) {
|
|
22
|
+
const previous = protocolEventWriter;
|
|
23
|
+
protocolEventWriter = writer;
|
|
24
|
+
return () => {
|
|
25
|
+
protocolEventWriter = previous;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
8
28
|
export function buildSessionListOptions(dir, limit = SESSION_LIST_LIMIT) {
|
|
9
29
|
return dir
|
|
10
30
|
? { dir, includeProgrammatic: true, includeWorktrees: true, limit }
|
|
@@ -23,7 +43,7 @@ export function writeEvent(event, requestId) {
|
|
|
23
43
|
};
|
|
24
44
|
const serialized = JSON.stringify(envelope);
|
|
25
45
|
logBridgeEventSent(event, requestId, Buffer.byteLength(serialized) + 1);
|
|
26
|
-
|
|
46
|
+
protocolEventWriter(`${serialized}\n`);
|
|
27
47
|
}
|
|
28
48
|
export function failConnection(message, requestId) {
|
|
29
49
|
writeEvent({ event: "connection_failed", message }, requestId);
|
|
@@ -112,7 +132,7 @@ export function emitElicitationRequestEvent(sessionId, request) {
|
|
|
112
132
|
});
|
|
113
133
|
writeEvent({ event: "elicitation_request", session_id: sessionId, request });
|
|
114
134
|
}
|
|
115
|
-
function buildConnectBridgeEvent(session, eventName) {
|
|
135
|
+
export function buildConnectBridgeEvent(session, eventName) {
|
|
116
136
|
const historyUpdates = session.resumeUpdates;
|
|
117
137
|
return eventName === "session_replaced"
|
|
118
138
|
? {
|
|
@@ -122,6 +142,10 @@ function buildConnectBridgeEvent(session, eventName) {
|
|
|
122
142
|
current_model: session.currentModel ?? resolveCurrentModel(session),
|
|
123
143
|
available_models: session.availableModels,
|
|
124
144
|
mode: session.mode ? buildModeState(session, session.mode) : null,
|
|
145
|
+
fast_mode_state: session.fastModeState,
|
|
146
|
+
...(session.fastModeDisabledReason
|
|
147
|
+
? { fast_mode_disabled_reason: session.fastModeDisabledReason }
|
|
148
|
+
: {}),
|
|
125
149
|
...(historyUpdates && historyUpdates.length > 0 ? { history_updates: historyUpdates } : {}),
|
|
126
150
|
...(session.restoredInput !== undefined ? { restored_input: session.restoredInput } : {}),
|
|
127
151
|
}
|
|
@@ -132,6 +156,10 @@ function buildConnectBridgeEvent(session, eventName) {
|
|
|
132
156
|
current_model: session.currentModel ?? resolveCurrentModel(session),
|
|
133
157
|
available_models: session.availableModels,
|
|
134
158
|
mode: session.mode ? buildModeState(session, session.mode) : null,
|
|
159
|
+
fast_mode_state: session.fastModeState,
|
|
160
|
+
...(session.fastModeDisabledReason
|
|
161
|
+
? { fast_mode_disabled_reason: session.fastModeDisabledReason }
|
|
162
|
+
: {}),
|
|
135
163
|
...(historyUpdates && historyUpdates.length > 0 ? { history_updates: historyUpdates } : {}),
|
|
136
164
|
};
|
|
137
165
|
}
|
|
@@ -152,6 +180,14 @@ function logConnectEventEmission(session, eventName, requestId) {
|
|
|
152
180
|
});
|
|
153
181
|
}
|
|
154
182
|
export function emitConnectEvent(session) {
|
|
183
|
+
const staleSessions = session.sessionsToCloseAfterConnect;
|
|
184
|
+
if (staleSessions) {
|
|
185
|
+
for (const stale of staleSessions) {
|
|
186
|
+
if (stale !== session) {
|
|
187
|
+
detachSessionForClose(stale);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
155
191
|
const bridgeEvent = buildConnectBridgeEvent(session, session.connectEvent);
|
|
156
192
|
logConnectEventEmission(session, session.connectEvent, session.connectRequestId);
|
|
157
193
|
writeEvent(bridgeEvent, session.connectRequestId);
|
|
@@ -164,26 +200,23 @@ export function emitConnectEvent(session) {
|
|
|
164
200
|
session.authHintSent = false;
|
|
165
201
|
session.resumeUpdates = undefined;
|
|
166
202
|
session.restoredInput = undefined;
|
|
167
|
-
const staleSessions = session.sessionsToCloseAfterConnect;
|
|
168
203
|
session.sessionsToCloseAfterConnect = undefined;
|
|
169
204
|
if (!staleSessions || staleSessions.length === 0) {
|
|
170
205
|
refreshSessionsList();
|
|
171
206
|
return;
|
|
172
207
|
}
|
|
173
|
-
|
|
208
|
+
const closeTask = (async () => {
|
|
174
209
|
// Lazy import to break circular dependency at module-evaluation time.
|
|
175
|
-
const {
|
|
210
|
+
const { closeSessionWithLogging } = await import("./session_lifecycle.js");
|
|
176
211
|
for (const stale of staleSessions) {
|
|
177
212
|
if (stale === session) {
|
|
178
213
|
continue;
|
|
179
214
|
}
|
|
180
|
-
if (sessions.get(stale.sessionId) === stale) {
|
|
181
|
-
sessions.delete(stale.sessionId);
|
|
182
|
-
}
|
|
183
215
|
await closeSessionWithLogging(stale, { reason: "stale_after_connect" });
|
|
184
216
|
}
|
|
185
217
|
refreshSessionsList();
|
|
186
218
|
})();
|
|
219
|
+
trackSessionCloseTask(closeTask);
|
|
187
220
|
}
|
|
188
221
|
export function emitSessionReplacedEvent(session, requestId) {
|
|
189
222
|
const bridgeEvent = buildConnectBridgeEvent(session, "session_replaced");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { asRecordOrNull } from "./shared.js";
|
|
2
|
-
import { TOOL_RESULT_TYPES, buildToolResultFields, createToolCall, isToolSearchToolName, isToolSearchToolResultType, isToolUseBlockType, } from "./tooling.js";
|
|
2
|
+
import { applyToolNonExecutionMetadata, TOOL_RESULT_TYPES, buildToolResultFields, createToolCall, isToolSearchToolName, isToolSearchToolResultType, isToolUseBlockType, parseToolNonExecutionMetadata, } from "./tooling.js";
|
|
3
3
|
function nonEmptyTrimmed(value) {
|
|
4
4
|
if (typeof value !== "string") {
|
|
5
5
|
return undefined;
|
|
@@ -197,7 +197,7 @@ function pushResumeToolUse(updates, toolCalls, hiddenToolUseIds, block, parentTo
|
|
|
197
197
|
toolCalls.set(toolUseId, toolCall);
|
|
198
198
|
updates.push({ type: "tool_call", tool_call: toolCall });
|
|
199
199
|
}
|
|
200
|
-
function pushResumeToolResult(updates, toolCalls, hiddenToolUseIds, block, sourceMessageUuid) {
|
|
200
|
+
function pushResumeToolResult(updates, toolCalls, hiddenToolUseIds, block, nonExecutionByToolUseId, sourceMessageUuid) {
|
|
201
201
|
const toolUseId = typeof block.tool_use_id === "string" ? block.tool_use_id : "";
|
|
202
202
|
if (!toolUseId) {
|
|
203
203
|
return;
|
|
@@ -210,6 +210,7 @@ function pushResumeToolResult(updates, toolCalls, hiddenToolUseIds, block, sourc
|
|
|
210
210
|
const isError = Boolean(block.is_error);
|
|
211
211
|
const base = toolCalls.get(toolUseId);
|
|
212
212
|
const fields = buildToolResultFields(isError, block.content, base, block);
|
|
213
|
+
applyToolNonExecutionMetadata(fields, nonExecutionByToolUseId.get(toolUseId));
|
|
213
214
|
updates.push({
|
|
214
215
|
type: "tool_call_update",
|
|
215
216
|
tool_call_update: {
|
|
@@ -294,6 +295,9 @@ export function mapSessionMessagesToUpdates(messages) {
|
|
|
294
295
|
? message.parent_tool_use_id
|
|
295
296
|
: null;
|
|
296
297
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
298
|
+
const nonExecutionByToolUseId = parseToolNonExecutionMetadata(Object.hasOwn(entry, "tool_result_meta")
|
|
299
|
+
? entry.tool_result_meta
|
|
300
|
+
: message.tool_result_meta);
|
|
297
301
|
for (const item of content) {
|
|
298
302
|
const block = asRecordOrNull(item);
|
|
299
303
|
if (!block) {
|
|
@@ -312,7 +316,7 @@ export function mapSessionMessagesToUpdates(messages) {
|
|
|
312
316
|
continue;
|
|
313
317
|
}
|
|
314
318
|
if (TOOL_RESULT_TYPES.has(blockType)) {
|
|
315
|
-
pushResumeToolResult(updates, toolCalls, hiddenToolUseIds, block, sourceMessageUuid);
|
|
319
|
+
pushResumeToolResult(updates, toolCalls, hiddenToolUseIds, block, nonExecutionByToolUseId, sourceMessageUuid);
|
|
316
320
|
continue;
|
|
317
321
|
}
|
|
318
322
|
if (blockType === "image") {
|
|
@@ -65,6 +65,7 @@ function commandSessionId(command) {
|
|
|
65
65
|
case "cancel_turn":
|
|
66
66
|
case "set_model":
|
|
67
67
|
case "set_mode":
|
|
68
|
+
case "set_fast_mode":
|
|
68
69
|
case "generate_session_title":
|
|
69
70
|
case "rename_session":
|
|
70
71
|
case "permission_response":
|
|
@@ -103,6 +104,7 @@ function commandToolCallId(command) {
|
|
|
103
104
|
case "cancel_turn":
|
|
104
105
|
case "set_model":
|
|
105
106
|
case "set_mode":
|
|
107
|
+
case "set_fast_mode":
|
|
106
108
|
case "generate_session_title":
|
|
107
109
|
case "rename_session":
|
|
108
110
|
case "new_session":
|