claude-code-rust 0.5.1 → 0.7.0

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.
@@ -1,23 +1,26 @@
1
- import { randomUUID } from "node:crypto";
2
- import { spawn as spawnChild } from "node:child_process";
3
- import fs from "node:fs";
4
1
  import { createRequire } from "node:module";
5
2
  import readline from "node:readline";
6
3
  import { pathToFileURL } from "node:url";
7
- import { query, } from "@anthropic-ai/claude-agent-sdk";
8
- import { parseCommandEnvelope, toPermissionMode, buildModeState } from "./bridge/commands.js";
9
- import { asRecordOrNull } from "./bridge/shared.js";
10
- import { looksLikeAuthRequired } from "./bridge/auth.js";
11
- import { TOOL_RESULT_TYPES, buildToolResultFields, createToolCall, normalizeToolKind, normalizeToolResultText, unwrapToolUseResult, } from "./bridge/tooling.js";
12
- import { CACHE_SPLIT_POLICY, previewKilobyteLabel } from "./bridge/cache_policy.js";
13
- import { buildUsageUpdateFromResult, buildUsageUpdateFromResultForSession } from "./bridge/usage.js";
14
- import { formatPermissionUpdates, permissionOptionsFromSuggestions, permissionResultFromOutcome, } from "./bridge/permissions.js";
15
- import { extractSessionHistoryUpdatesFromJsonl, listRecentPersistedSessions, resolvePersistedSessionEntry, } from "./bridge/history.js";
16
- export { CACHE_SPLIT_POLICY, buildToolResultFields, buildUsageUpdateFromResult, createToolCall, extractSessionHistoryUpdatesFromJsonl, looksLikeAuthRequired, normalizeToolKind, normalizeToolResultText, parseCommandEnvelope, permissionOptionsFromSuggestions, permissionResultFromOutcome, previewKilobyteLabel, unwrapToolUseResult, };
17
- const sessions = new Map();
18
- const EXPECTED_AGENT_SDK_VERSION = "0.2.52";
4
+ import { getSessionMessages, listSessions, } from "@anthropic-ai/claude-agent-sdk";
5
+ import { parseCommandEnvelope, toPermissionMode } from "./bridge/commands.js";
6
+ import { writeEvent, failConnection, slashError, emitSessionUpdate, emitSessionsList, } from "./bridge/events.js";
7
+ import { textFromPrompt } from "./bridge/message_handlers.js";
8
+ import { sessions, sessionById, createSession, closeAllSessions, handlePermissionResponse, } from "./bridge/session_lifecycle.js";
9
+ import { mapSessionMessagesToUpdates } from "./bridge/history.js";
10
+ // Re-exports: all symbols that tests and external consumers import from bridge.js.
11
+ export { AsyncQueue, logPermissionDebug } from "./bridge/shared.js";
12
+ export { asRecordOrNull } from "./bridge/shared.js";
13
+ export { CACHE_SPLIT_POLICY, previewKilobyteLabel } from "./bridge/cache_policy.js";
14
+ export { buildToolResultFields, createToolCall, normalizeToolKind, normalizeToolResultText, unwrapToolUseResult, } from "./bridge/tooling.js";
15
+ export { looksLikeAuthRequired } from "./bridge/auth.js";
16
+ export { parseCommandEnvelope } from "./bridge/commands.js";
17
+ export { permissionOptionsFromSuggestions, permissionResultFromOutcome, } from "./bridge/permissions.js";
18
+ export { mapSessionMessagesToUpdates, mapSdkSessions, } from "./bridge/history.js";
19
+ export { mapAvailableAgents } from "./bridge/agents.js";
20
+ export { buildQueryOptions } from "./bridge/session_lifecycle.js";
21
+ export { parseFastModeState, parseRateLimitStatus, buildRateLimitUpdate, } from "./bridge/state_parsing.js";
22
+ const EXPECTED_AGENT_SDK_VERSION = "0.2.63";
19
23
  const require = createRequire(import.meta.url);
20
- const permissionDebugEnabled = process.env.CLAUDE_RS_SDK_PERMISSION_DEBUG === "1" || process.env.CLAUDE_RS_SDK_DEBUG === "1";
21
24
  export function resolveInstalledAgentSdkVersion() {
22
25
  try {
23
26
  const pkg = require("@anthropic-ai/claude-agent-sdk/package.json");
@@ -39,1069 +42,6 @@ export function agentSdkVersionCompatibilityError() {
39
42
  return (`Unsupported @anthropic-ai/claude-agent-sdk version: expected ${EXPECTED_AGENT_SDK_VERSION}, ` +
40
43
  `found ${installed}.`);
41
44
  }
42
- function logPermissionDebug(message) {
43
- if (!permissionDebugEnabled) {
44
- return;
45
- }
46
- console.error(`[perm debug] ${message}`);
47
- }
48
- class AsyncQueue {
49
- items = [];
50
- waiters = [];
51
- closed = false;
52
- enqueue(item) {
53
- if (this.closed) {
54
- return;
55
- }
56
- const waiter = this.waiters.shift();
57
- if (waiter) {
58
- waiter({ value: item, done: false });
59
- return;
60
- }
61
- this.items.push(item);
62
- }
63
- close() {
64
- if (this.closed) {
65
- return;
66
- }
67
- this.closed = true;
68
- while (this.waiters.length > 0) {
69
- const waiter = this.waiters.shift();
70
- waiter?.({ value: undefined, done: true });
71
- }
72
- }
73
- [Symbol.asyncIterator]() {
74
- return {
75
- next: async () => {
76
- if (this.items.length > 0) {
77
- const value = this.items.shift();
78
- return { value: value, done: false };
79
- }
80
- if (this.closed) {
81
- return { value: undefined, done: true };
82
- }
83
- return await new Promise((resolve) => {
84
- this.waiters.push(resolve);
85
- });
86
- },
87
- };
88
- }
89
- }
90
- function writeEvent(event, requestId) {
91
- const envelope = {
92
- ...(requestId ? { request_id: requestId } : {}),
93
- ...event,
94
- };
95
- process.stdout.write(`${JSON.stringify(envelope)}\n`);
96
- }
97
- function failConnection(message, requestId) {
98
- writeEvent({ event: "connection_failed", message }, requestId);
99
- }
100
- function slashError(sessionId, message, requestId) {
101
- writeEvent({ event: "slash_error", session_id: sessionId, message }, requestId);
102
- }
103
- function emitSessionUpdate(sessionId, update) {
104
- writeEvent({ event: "session_update", session_id: sessionId, update });
105
- }
106
- function emitConnectEvent(session) {
107
- const historyUpdates = session.resumeUpdates;
108
- const connectEvent = session.connectEvent === "session_replaced"
109
- ? {
110
- event: "session_replaced",
111
- session_id: session.sessionId,
112
- cwd: session.cwd,
113
- model_name: session.model,
114
- mode: buildModeState(session.mode),
115
- ...(historyUpdates && historyUpdates.length > 0 ? { history_updates: historyUpdates } : {}),
116
- }
117
- : {
118
- event: "connected",
119
- session_id: session.sessionId,
120
- cwd: session.cwd,
121
- model_name: session.model,
122
- mode: buildModeState(session.mode),
123
- ...(historyUpdates && historyUpdates.length > 0 ? { history_updates: historyUpdates } : {}),
124
- };
125
- writeEvent(connectEvent, session.connectRequestId);
126
- session.connectRequestId = undefined;
127
- session.connected = true;
128
- session.authHintSent = false;
129
- session.resumeUpdates = undefined;
130
- const staleSessions = session.sessionsToCloseAfterConnect;
131
- session.sessionsToCloseAfterConnect = undefined;
132
- if (!staleSessions || staleSessions.length === 0) {
133
- return;
134
- }
135
- void (async () => {
136
- for (const stale of staleSessions) {
137
- if (stale === session) {
138
- continue;
139
- }
140
- if (sessions.get(stale.sessionId) === stale) {
141
- sessions.delete(stale.sessionId);
142
- }
143
- await closeSession(stale);
144
- }
145
- })();
146
- }
147
- function textFromPrompt(command) {
148
- const chunks = command.chunks ?? [];
149
- return chunks
150
- .map((chunk) => {
151
- if (chunk.kind !== "text") {
152
- return "";
153
- }
154
- return typeof chunk.value === "string" ? chunk.value : "";
155
- })
156
- .filter((part) => part.length > 0)
157
- .join("");
158
- }
159
- function sessionById(sessionId) {
160
- return sessions.get(sessionId) ?? null;
161
- }
162
- function updateSessionId(session, newSessionId) {
163
- if (session.sessionId === newSessionId) {
164
- return;
165
- }
166
- sessions.delete(session.sessionId);
167
- session.sessionId = newSessionId;
168
- sessions.set(newSessionId, session);
169
- }
170
- function emitToolCall(session, toolUseId, name, input) {
171
- const toolCall = createToolCall(toolUseId, name, input);
172
- const status = "in_progress";
173
- toolCall.status = status;
174
- const existing = session.toolCalls.get(toolUseId);
175
- if (!existing) {
176
- session.toolCalls.set(toolUseId, toolCall);
177
- emitSessionUpdate(session.sessionId, { type: "tool_call", tool_call: toolCall });
178
- return;
179
- }
180
- const fields = {
181
- title: toolCall.title,
182
- kind: toolCall.kind,
183
- status,
184
- raw_input: toolCall.raw_input,
185
- locations: toolCall.locations,
186
- meta: toolCall.meta,
187
- };
188
- if (toolCall.content.length > 0) {
189
- fields.content = toolCall.content;
190
- }
191
- emitSessionUpdate(session.sessionId, {
192
- type: "tool_call_update",
193
- tool_call_update: { tool_call_id: toolUseId, fields },
194
- });
195
- existing.title = toolCall.title;
196
- existing.kind = toolCall.kind;
197
- existing.status = status;
198
- existing.raw_input = toolCall.raw_input;
199
- existing.locations = toolCall.locations;
200
- existing.meta = toolCall.meta;
201
- if (toolCall.content.length > 0) {
202
- existing.content = toolCall.content;
203
- }
204
- }
205
- function ensureToolCallVisible(session, toolUseId, toolName, input) {
206
- const existing = session.toolCalls.get(toolUseId);
207
- if (existing) {
208
- return existing;
209
- }
210
- const toolCall = createToolCall(toolUseId, toolName, input);
211
- session.toolCalls.set(toolUseId, toolCall);
212
- emitSessionUpdate(session.sessionId, { type: "tool_call", tool_call: toolCall });
213
- return toolCall;
214
- }
215
- function emitPlanIfTodoWrite(session, name, input) {
216
- if (name !== "TodoWrite" || !Array.isArray(input.todos)) {
217
- return;
218
- }
219
- const entries = input.todos
220
- .map((todo) => {
221
- if (!todo || typeof todo !== "object") {
222
- return null;
223
- }
224
- const todoObj = todo;
225
- const content = typeof todoObj.content === "string" ? todoObj.content : "";
226
- const status = typeof todoObj.status === "string" ? todoObj.status : "pending";
227
- if (!content) {
228
- return null;
229
- }
230
- return { content, status, active_form: status };
231
- })
232
- .filter((entry) => entry !== null);
233
- if (entries.length > 0) {
234
- emitSessionUpdate(session.sessionId, { type: "plan", entries });
235
- }
236
- }
237
- function emitToolResultUpdate(session, toolUseId, isError, rawContent) {
238
- const base = session.toolCalls.get(toolUseId);
239
- const fields = buildToolResultFields(isError, rawContent, base);
240
- const update = { tool_call_id: toolUseId, fields };
241
- emitSessionUpdate(session.sessionId, { type: "tool_call_update", tool_call_update: update });
242
- if (base) {
243
- base.status = fields.status ?? base.status;
244
- if (fields.raw_output) {
245
- base.raw_output = fields.raw_output;
246
- }
247
- if (fields.content) {
248
- base.content = fields.content;
249
- }
250
- }
251
- }
252
- function finalizeOpenToolCalls(session, status) {
253
- for (const [toolUseId, toolCall] of session.toolCalls) {
254
- if (toolCall.status !== "pending" && toolCall.status !== "in_progress") {
255
- continue;
256
- }
257
- const fields = { status };
258
- emitSessionUpdate(session.sessionId, {
259
- type: "tool_call_update",
260
- tool_call_update: { tool_call_id: toolUseId, fields },
261
- });
262
- toolCall.status = status;
263
- }
264
- }
265
- function emitToolProgressUpdate(session, toolUseId, toolName) {
266
- const existing = session.toolCalls.get(toolUseId);
267
- if (!existing) {
268
- emitToolCall(session, toolUseId, toolName, {});
269
- return;
270
- }
271
- if (existing.status === "in_progress") {
272
- return;
273
- }
274
- const fields = { status: "in_progress" };
275
- emitSessionUpdate(session.sessionId, {
276
- type: "tool_call_update",
277
- tool_call_update: { tool_call_id: toolUseId, fields },
278
- });
279
- existing.status = "in_progress";
280
- }
281
- function emitToolSummaryUpdate(session, toolUseId, summary) {
282
- const base = session.toolCalls.get(toolUseId);
283
- if (!base) {
284
- return;
285
- }
286
- const fields = {
287
- status: base.status === "failed" ? "failed" : "completed",
288
- raw_output: summary,
289
- content: [{ type: "content", content: { type: "text", text: summary } }],
290
- };
291
- emitSessionUpdate(session.sessionId, {
292
- type: "tool_call_update",
293
- tool_call_update: { tool_call_id: toolUseId, fields },
294
- });
295
- base.status = fields.status ?? base.status;
296
- base.raw_output = summary;
297
- }
298
- function setToolCallStatus(session, toolUseId, status, message) {
299
- const base = session.toolCalls.get(toolUseId);
300
- if (!base) {
301
- return;
302
- }
303
- const fields = { status };
304
- if (message && message.length > 0) {
305
- fields.raw_output = message;
306
- fields.content = [{ type: "content", content: { type: "text", text: message } }];
307
- }
308
- emitSessionUpdate(session.sessionId, {
309
- type: "tool_call_update",
310
- tool_call_update: { tool_call_id: toolUseId, fields },
311
- });
312
- base.status = status;
313
- if (fields.raw_output) {
314
- base.raw_output = fields.raw_output;
315
- }
316
- }
317
- function resolveTaskToolUseId(session, msg) {
318
- const direct = typeof msg.tool_use_id === "string" ? msg.tool_use_id : "";
319
- if (direct) {
320
- return direct;
321
- }
322
- const taskId = typeof msg.task_id === "string" ? msg.task_id : "";
323
- if (!taskId) {
324
- return "";
325
- }
326
- return session.taskToolUseIds.get(taskId) ?? "";
327
- }
328
- function taskProgressText(msg) {
329
- const description = typeof msg.description === "string" ? msg.description : "";
330
- const lastTool = typeof msg.last_tool_name === "string" ? msg.last_tool_name : "";
331
- if (description && lastTool) {
332
- return `${description} (last tool: ${lastTool})`;
333
- }
334
- return description || lastTool;
335
- }
336
- function handleTaskSystemMessage(session, subtype, msg) {
337
- if (subtype !== "task_started" && subtype !== "task_progress" && subtype !== "task_notification") {
338
- return;
339
- }
340
- const taskId = typeof msg.task_id === "string" ? msg.task_id : "";
341
- const explicitToolUseId = typeof msg.tool_use_id === "string" ? msg.tool_use_id : "";
342
- if (taskId && explicitToolUseId) {
343
- session.taskToolUseIds.set(taskId, explicitToolUseId);
344
- }
345
- const toolUseId = resolveTaskToolUseId(session, msg);
346
- if (!toolUseId) {
347
- return;
348
- }
349
- const toolCall = ensureToolCallVisible(session, toolUseId, "Task", {});
350
- if (toolCall.status === "pending") {
351
- toolCall.status = "in_progress";
352
- emitSessionUpdate(session.sessionId, {
353
- type: "tool_call_update",
354
- tool_call_update: { tool_call_id: toolUseId, fields: { status: "in_progress" } },
355
- });
356
- }
357
- if (subtype === "task_started") {
358
- const description = typeof msg.description === "string" ? msg.description : "";
359
- if (!description) {
360
- return;
361
- }
362
- emitSessionUpdate(session.sessionId, {
363
- type: "tool_call_update",
364
- tool_call_update: {
365
- tool_call_id: toolUseId,
366
- fields: {
367
- status: "in_progress",
368
- raw_output: description,
369
- content: [{ type: "content", content: { type: "text", text: description } }],
370
- },
371
- },
372
- });
373
- return;
374
- }
375
- if (subtype === "task_progress") {
376
- const progress = taskProgressText(msg);
377
- if (!progress) {
378
- return;
379
- }
380
- emitSessionUpdate(session.sessionId, {
381
- type: "tool_call_update",
382
- tool_call_update: {
383
- tool_call_id: toolUseId,
384
- fields: {
385
- status: "in_progress",
386
- raw_output: progress,
387
- content: [{ type: "content", content: { type: "text", text: progress } }],
388
- },
389
- },
390
- });
391
- return;
392
- }
393
- const status = typeof msg.status === "string" ? msg.status : "";
394
- const summary = typeof msg.summary === "string" ? msg.summary : "";
395
- const finalStatus = status === "completed" ? "completed" : "failed";
396
- const fields = { status: finalStatus };
397
- if (summary) {
398
- fields.raw_output = summary;
399
- fields.content = [{ type: "content", content: { type: "text", text: summary } }];
400
- }
401
- emitSessionUpdate(session.sessionId, {
402
- type: "tool_call_update",
403
- tool_call_update: { tool_call_id: toolUseId, fields },
404
- });
405
- toolCall.status = finalStatus;
406
- if (taskId) {
407
- session.taskToolUseIds.delete(taskId);
408
- }
409
- }
410
- function handleContentBlock(session, block) {
411
- const blockType = typeof block.type === "string" ? block.type : "";
412
- if (blockType === "text") {
413
- const text = typeof block.text === "string" ? block.text : "";
414
- if (text) {
415
- emitSessionUpdate(session.sessionId, { type: "agent_message_chunk", content: { type: "text", text } });
416
- }
417
- return;
418
- }
419
- if (blockType === "thinking") {
420
- const text = typeof block.thinking === "string" ? block.thinking : "";
421
- if (text) {
422
- emitSessionUpdate(session.sessionId, { type: "agent_thought_chunk", content: { type: "text", text } });
423
- }
424
- return;
425
- }
426
- if (blockType === "tool_use" || blockType === "server_tool_use" || blockType === "mcp_tool_use") {
427
- const toolUseId = typeof block.id === "string" ? block.id : "";
428
- const name = typeof block.name === "string" ? block.name : "Tool";
429
- const input = block.input && typeof block.input === "object" ? block.input : {};
430
- if (!toolUseId) {
431
- return;
432
- }
433
- emitPlanIfTodoWrite(session, name, input);
434
- emitToolCall(session, toolUseId, name, input);
435
- return;
436
- }
437
- if (TOOL_RESULT_TYPES.has(blockType)) {
438
- const toolUseId = typeof block.tool_use_id === "string" ? block.tool_use_id : "";
439
- if (!toolUseId) {
440
- return;
441
- }
442
- const isError = Boolean(block.is_error);
443
- emitToolResultUpdate(session, toolUseId, isError, block.content);
444
- }
445
- }
446
- function handleStreamEvent(session, event) {
447
- const eventType = typeof event.type === "string" ? event.type : "";
448
- if (eventType === "content_block_start") {
449
- if (event.content_block && typeof event.content_block === "object") {
450
- handleContentBlock(session, event.content_block);
451
- }
452
- return;
453
- }
454
- if (eventType === "content_block_delta") {
455
- if (!event.delta || typeof event.delta !== "object") {
456
- return;
457
- }
458
- const delta = event.delta;
459
- const deltaType = typeof delta.type === "string" ? delta.type : "";
460
- if (deltaType === "text_delta") {
461
- const text = typeof delta.text === "string" ? delta.text : "";
462
- if (text) {
463
- emitSessionUpdate(session.sessionId, { type: "agent_message_chunk", content: { type: "text", text } });
464
- }
465
- }
466
- else if (deltaType === "thinking_delta") {
467
- const text = typeof delta.thinking === "string" ? delta.thinking : "";
468
- if (text) {
469
- emitSessionUpdate(session.sessionId, { type: "agent_thought_chunk", content: { type: "text", text } });
470
- }
471
- }
472
- }
473
- }
474
- function handleAssistantMessage(session, message) {
475
- const assistantError = typeof message.error === "string" ? message.error : "";
476
- if (assistantError.length > 0) {
477
- session.lastAssistantError = assistantError;
478
- }
479
- const messageObject = message.message && typeof message.message === "object"
480
- ? message.message
481
- : null;
482
- if (!messageObject) {
483
- return;
484
- }
485
- const content = Array.isArray(messageObject.content) ? messageObject.content : [];
486
- for (const block of content) {
487
- if (!block || typeof block !== "object") {
488
- continue;
489
- }
490
- const blockRecord = block;
491
- const blockType = typeof blockRecord.type === "string" ? blockRecord.type : "";
492
- if (blockType === "tool_use" ||
493
- blockType === "server_tool_use" ||
494
- blockType === "mcp_tool_use" ||
495
- TOOL_RESULT_TYPES.has(blockType)) {
496
- handleContentBlock(session, blockRecord);
497
- }
498
- }
499
- }
500
- function handleUserToolResultBlocks(session, message) {
501
- const messageObject = message.message && typeof message.message === "object"
502
- ? message.message
503
- : null;
504
- if (!messageObject) {
505
- return;
506
- }
507
- const content = Array.isArray(messageObject.content) ? messageObject.content : [];
508
- for (const block of content) {
509
- if (!block || typeof block !== "object") {
510
- continue;
511
- }
512
- const blockRecord = block;
513
- const blockType = typeof blockRecord.type === "string" ? blockRecord.type : "";
514
- if (TOOL_RESULT_TYPES.has(blockType)) {
515
- handleContentBlock(session, blockRecord);
516
- }
517
- }
518
- }
519
- function emitAuthRequired(session, detail) {
520
- if (session.authHintSent) {
521
- return;
522
- }
523
- session.authHintSent = true;
524
- writeEvent({
525
- event: "auth_required",
526
- method_name: "Claude Login",
527
- method_description: detail && detail.trim().length > 0
528
- ? detail
529
- : "Run `claude /login` in a terminal, then retry.",
530
- });
531
- }
532
- function looksLikePlanLimitError(input) {
533
- const normalized = input.toLowerCase();
534
- return (normalized.includes("rate limit") ||
535
- normalized.includes("rate-limit") ||
536
- normalized.includes("max turns") ||
537
- normalized.includes("max budget") ||
538
- normalized.includes("quota") ||
539
- normalized.includes("plan limit") ||
540
- normalized.includes("too many requests") ||
541
- normalized.includes("insufficient quota") ||
542
- normalized.includes("429"));
543
- }
544
- function classifyTurnErrorKind(subtype, errors, assistantError) {
545
- const combined = errors.join("\n");
546
- if (subtype === "error_max_turns" ||
547
- subtype === "error_max_budget_usd" ||
548
- assistantError === "billing_error" ||
549
- assistantError === "rate_limit" ||
550
- (combined.length > 0 && looksLikePlanLimitError(combined))) {
551
- return "plan_limit";
552
- }
553
- if (assistantError === "authentication_failed" ||
554
- errors.some((entry) => looksLikeAuthRequired(entry))) {
555
- return "auth_required";
556
- }
557
- if (assistantError === "server_error") {
558
- return "internal";
559
- }
560
- return "other";
561
- }
562
- function numberField(record, ...keys) {
563
- for (const key of keys) {
564
- const value = record[key];
565
- if (typeof value === "number" && Number.isFinite(value)) {
566
- return value;
567
- }
568
- }
569
- return undefined;
570
- }
571
- function handleResultMessage(session, message) {
572
- const usageUpdate = buildUsageUpdateFromResultForSession(session, message);
573
- if (usageUpdate) {
574
- emitSessionUpdate(session.sessionId, usageUpdate);
575
- }
576
- const subtype = typeof message.subtype === "string" ? message.subtype : "";
577
- if (subtype === "success") {
578
- session.lastAssistantError = undefined;
579
- finalizeOpenToolCalls(session, "completed");
580
- writeEvent({ event: "turn_complete", session_id: session.sessionId });
581
- return;
582
- }
583
- const errors = Array.isArray(message.errors) && message.errors.every((entry) => typeof entry === "string")
584
- ? message.errors
585
- : [];
586
- const assistantError = session.lastAssistantError;
587
- const authHint = errors.find((entry) => looksLikeAuthRequired(entry));
588
- if (authHint) {
589
- emitAuthRequired(session, authHint);
590
- }
591
- if (assistantError === "authentication_failed") {
592
- emitAuthRequired(session);
593
- }
594
- finalizeOpenToolCalls(session, "failed");
595
- const errorKind = classifyTurnErrorKind(subtype, errors, assistantError);
596
- const fallback = subtype ? `turn failed: ${subtype}` : "turn failed";
597
- writeEvent({
598
- event: "turn_error",
599
- session_id: session.sessionId,
600
- message: errors.length > 0 ? errors.join("\n") : fallback,
601
- error_kind: errorKind,
602
- ...(subtype ? { sdk_result_subtype: subtype } : {}),
603
- ...(assistantError ? { assistant_error: assistantError } : {}),
604
- });
605
- session.lastAssistantError = undefined;
606
- }
607
- function handleSdkMessage(session, message) {
608
- const msg = message;
609
- const type = typeof msg.type === "string" ? msg.type : "";
610
- if (type === "system") {
611
- const subtype = typeof msg.subtype === "string" ? msg.subtype : "";
612
- if (subtype === "init") {
613
- const previousSessionId = session.sessionId;
614
- const incomingSessionId = typeof msg.session_id === "string" ? msg.session_id : session.sessionId;
615
- updateSessionId(session, incomingSessionId);
616
- const modelName = typeof msg.model === "string" ? msg.model : session.model;
617
- session.model = modelName;
618
- const incomingMode = typeof msg.permissionMode === "string" ? toPermissionMode(msg.permissionMode) : null;
619
- if (incomingMode) {
620
- session.mode = incomingMode;
621
- }
622
- if (!session.connected) {
623
- emitConnectEvent(session);
624
- }
625
- else if (previousSessionId !== session.sessionId) {
626
- const historyUpdates = session.resumeUpdates;
627
- writeEvent({
628
- event: "session_replaced",
629
- session_id: session.sessionId,
630
- cwd: session.cwd,
631
- model_name: session.model,
632
- mode: buildModeState(session.mode),
633
- ...(historyUpdates && historyUpdates.length > 0
634
- ? { history_updates: historyUpdates }
635
- : {}),
636
- });
637
- session.resumeUpdates = undefined;
638
- }
639
- if (Array.isArray(msg.slash_commands)) {
640
- const commands = msg.slash_commands
641
- .filter((entry) => typeof entry === "string")
642
- .map((name) => ({ name, description: "", input_hint: undefined }));
643
- if (commands.length > 0) {
644
- emitSessionUpdate(session.sessionId, { type: "available_commands_update", commands });
645
- }
646
- }
647
- void session.query
648
- .supportedCommands()
649
- .then((commands) => {
650
- const mapped = commands.map((command) => ({
651
- name: command.name,
652
- description: command.description ?? "",
653
- input_hint: command.argumentHint ?? undefined,
654
- }));
655
- emitSessionUpdate(session.sessionId, { type: "available_commands_update", commands: mapped });
656
- })
657
- .catch(() => {
658
- // Best-effort only; slash commands from init were already emitted.
659
- });
660
- return;
661
- }
662
- if (subtype === "status") {
663
- const mode = typeof msg.permissionMode === "string" ? toPermissionMode(msg.permissionMode) : null;
664
- if (mode) {
665
- session.mode = mode;
666
- emitSessionUpdate(session.sessionId, { type: "current_mode_update", current_mode_id: mode });
667
- }
668
- if (msg.status === "compacting") {
669
- emitSessionUpdate(session.sessionId, { type: "session_status_update", status: "compacting" });
670
- }
671
- else if (msg.status === null) {
672
- emitSessionUpdate(session.sessionId, { type: "session_status_update", status: "idle" });
673
- }
674
- return;
675
- }
676
- if (subtype === "compact_boundary") {
677
- const compactMetadata = asRecordOrNull(msg.compact_metadata);
678
- if (!compactMetadata) {
679
- return;
680
- }
681
- const trigger = compactMetadata.trigger;
682
- const preTokens = numberField(compactMetadata, "pre_tokens", "preTokens");
683
- if ((trigger === "manual" || trigger === "auto") && preTokens !== undefined) {
684
- emitSessionUpdate(session.sessionId, {
685
- type: "compaction_boundary",
686
- trigger,
687
- pre_tokens: preTokens,
688
- });
689
- }
690
- return;
691
- }
692
- handleTaskSystemMessage(session, subtype, msg);
693
- return;
694
- }
695
- if (type === "auth_status") {
696
- const output = Array.isArray(msg.output)
697
- ? msg.output.filter((entry) => typeof entry === "string").join("\n")
698
- : "";
699
- const errorText = typeof msg.error === "string" ? msg.error : "";
700
- const combined = [errorText, output].filter((entry) => entry.length > 0).join("\n");
701
- if (combined && looksLikeAuthRequired(combined)) {
702
- emitAuthRequired(session, combined);
703
- }
704
- return;
705
- }
706
- if (type === "stream_event") {
707
- if (msg.event && typeof msg.event === "object") {
708
- handleStreamEvent(session, msg.event);
709
- }
710
- return;
711
- }
712
- if (type === "tool_progress") {
713
- const toolUseId = typeof msg.tool_use_id === "string" ? msg.tool_use_id : "";
714
- const toolName = typeof msg.tool_name === "string" ? msg.tool_name : "Tool";
715
- if (toolUseId) {
716
- emitToolProgressUpdate(session, toolUseId, toolName);
717
- }
718
- return;
719
- }
720
- if (type === "tool_use_summary") {
721
- const summary = typeof msg.summary === "string" ? msg.summary : "";
722
- const toolIds = Array.isArray(msg.preceding_tool_use_ids)
723
- ? msg.preceding_tool_use_ids.filter((id) => typeof id === "string")
724
- : [];
725
- if (summary && toolIds.length > 0) {
726
- for (const toolUseId of toolIds) {
727
- emitToolSummaryUpdate(session, toolUseId, summary);
728
- }
729
- }
730
- return;
731
- }
732
- if (type === "user") {
733
- handleUserToolResultBlocks(session, msg);
734
- const toolUseId = typeof msg.parent_tool_use_id === "string" ? msg.parent_tool_use_id : "";
735
- if (toolUseId && "tool_use_result" in msg) {
736
- const parsed = unwrapToolUseResult(msg.tool_use_result);
737
- emitToolResultUpdate(session, toolUseId, parsed.isError, parsed.content);
738
- }
739
- return;
740
- }
741
- if (type === "assistant") {
742
- if (msg.error === "authentication_failed") {
743
- emitAuthRequired(session);
744
- }
745
- handleAssistantMessage(session, msg);
746
- return;
747
- }
748
- if (type === "result") {
749
- handleResultMessage(session, msg);
750
- }
751
- }
752
- const ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
753
- const QUESTION_CHOICE_KIND = "question_choice";
754
- function parseAskUserQuestionPrompts(inputData) {
755
- const rawQuestions = Array.isArray(inputData.questions) ? inputData.questions : [];
756
- const prompts = [];
757
- for (const rawQuestion of rawQuestions) {
758
- const questionRecord = asRecordOrNull(rawQuestion);
759
- if (!questionRecord) {
760
- continue;
761
- }
762
- const question = typeof questionRecord.question === "string" ? questionRecord.question.trim() : "";
763
- if (!question) {
764
- continue;
765
- }
766
- const headerRaw = typeof questionRecord.header === "string" ? questionRecord.header.trim() : "";
767
- const header = headerRaw || `Q${prompts.length + 1}`;
768
- const multiSelect = Boolean(questionRecord.multiSelect);
769
- const rawOptions = Array.isArray(questionRecord.options) ? questionRecord.options : [];
770
- const options = [];
771
- for (const rawOption of rawOptions) {
772
- const optionRecord = asRecordOrNull(rawOption);
773
- if (!optionRecord) {
774
- continue;
775
- }
776
- const label = typeof optionRecord.label === "string" ? optionRecord.label.trim() : "";
777
- const description = typeof optionRecord.description === "string" ? optionRecord.description.trim() : "";
778
- if (!label) {
779
- continue;
780
- }
781
- options.push({ label, description });
782
- }
783
- if (options.length < 2) {
784
- continue;
785
- }
786
- prompts.push({ question, header, multiSelect, options });
787
- }
788
- return prompts;
789
- }
790
- function askUserQuestionOptions(prompt) {
791
- return prompt.options.map((option, index) => ({
792
- option_id: `question_${index}`,
793
- name: option.label,
794
- description: option.description,
795
- kind: QUESTION_CHOICE_KIND,
796
- }));
797
- }
798
- function askUserQuestionPromptToolCall(base, prompt, index, total) {
799
- return {
800
- ...base,
801
- title: prompt.question,
802
- raw_input: {
803
- questions: [
804
- {
805
- question: prompt.question,
806
- header: prompt.header,
807
- multiSelect: prompt.multiSelect,
808
- options: prompt.options,
809
- },
810
- ],
811
- question_index: index,
812
- total_questions: total,
813
- },
814
- };
815
- }
816
- function askUserQuestionTranscript(answers) {
817
- return answers.map((entry) => `${entry.header}: ${entry.answer}\n ${entry.question}`).join("\n");
818
- }
819
- async function requestAskUserQuestionAnswers(session, toolUseId, toolName, inputData, baseToolCall) {
820
- const prompts = parseAskUserQuestionPrompts(inputData);
821
- if (prompts.length === 0) {
822
- return { behavior: "allow", updatedInput: inputData, toolUseID: toolUseId };
823
- }
824
- const answers = {};
825
- const transcript = [];
826
- for (const [index, prompt] of prompts.entries()) {
827
- const promptToolCall = askUserQuestionPromptToolCall(baseToolCall, prompt, index, prompts.length);
828
- const fields = {
829
- title: promptToolCall.title,
830
- status: "in_progress",
831
- raw_input: promptToolCall.raw_input,
832
- };
833
- emitSessionUpdate(session.sessionId, {
834
- type: "tool_call_update",
835
- tool_call_update: { tool_call_id: toolUseId, fields },
836
- });
837
- const tracked = session.toolCalls.get(toolUseId);
838
- if (tracked) {
839
- tracked.title = promptToolCall.title;
840
- tracked.status = "in_progress";
841
- tracked.raw_input = promptToolCall.raw_input;
842
- }
843
- const request = {
844
- tool_call: promptToolCall,
845
- options: askUserQuestionOptions(prompt),
846
- };
847
- const outcome = await new Promise((resolve) => {
848
- session.pendingPermissions.set(toolUseId, {
849
- onOutcome: resolve,
850
- toolName,
851
- inputData,
852
- });
853
- writeEvent({ event: "permission_request", session_id: session.sessionId, request });
854
- });
855
- if (outcome.outcome !== "selected") {
856
- setToolCallStatus(session, toolUseId, "failed", "Question cancelled");
857
- return { behavior: "deny", message: "Question cancelled", toolUseID: toolUseId };
858
- }
859
- const selected = request.options.find((option) => option.option_id === outcome.option_id);
860
- if (!selected) {
861
- setToolCallStatus(session, toolUseId, "failed", "Question answer was invalid");
862
- return { behavior: "deny", message: "Question answer was invalid", toolUseID: toolUseId };
863
- }
864
- answers[prompt.question] = selected.name;
865
- transcript.push({ header: prompt.header, question: prompt.question, answer: selected.name });
866
- const summary = askUserQuestionTranscript(transcript);
867
- const progressFields = {
868
- status: index + 1 >= prompts.length ? "completed" : "in_progress",
869
- raw_output: summary,
870
- content: [{ type: "content", content: { type: "text", text: summary } }],
871
- };
872
- emitSessionUpdate(session.sessionId, {
873
- type: "tool_call_update",
874
- tool_call_update: { tool_call_id: toolUseId, fields: progressFields },
875
- });
876
- if (tracked) {
877
- tracked.status = progressFields.status ?? tracked.status;
878
- tracked.raw_output = summary;
879
- tracked.content = progressFields.content ?? tracked.content;
880
- }
881
- }
882
- return {
883
- behavior: "allow",
884
- updatedInput: { ...inputData, answers },
885
- toolUseID: toolUseId,
886
- };
887
- }
888
- async function closeSession(session) {
889
- session.input.close();
890
- session.query.close();
891
- for (const pending of session.pendingPermissions.values()) {
892
- pending.resolve?.({ behavior: "deny", message: "Session closed" });
893
- pending.onOutcome?.({ outcome: "cancelled" });
894
- }
895
- session.pendingPermissions.clear();
896
- }
897
- async function closeAllSessions() {
898
- const active = Array.from(sessions.values());
899
- sessions.clear();
900
- await Promise.all(active.map((session) => closeSession(session)));
901
- }
902
- async function createSession(params) {
903
- const input = new AsyncQueue();
904
- const startMode = params.yolo ? "bypassPermissions" : "default";
905
- const provisionalSessionId = params.resume ?? randomUUID();
906
- let session;
907
- const canUseTool = async (toolName, inputData, options) => {
908
- const toolUseId = options.toolUseID;
909
- if (toolName === "ExitPlanMode") {
910
- return { behavior: "allow", toolUseID: toolUseId };
911
- }
912
- logPermissionDebug(`request tool_use_id=${toolUseId} tool=${toolName} blocked_path=${options.blockedPath ?? "<none>"} ` +
913
- `decision_reason=${options.decisionReason ?? "<none>"} suggestions=${formatPermissionUpdates(options.suggestions)}`);
914
- const existing = ensureToolCallVisible(session, toolUseId, toolName, inputData);
915
- if (toolName === ASK_USER_QUESTION_TOOL_NAME) {
916
- return await requestAskUserQuestionAnswers(session, toolUseId, toolName, inputData, existing);
917
- }
918
- const request = {
919
- tool_call: existing,
920
- options: permissionOptionsFromSuggestions(options.suggestions),
921
- };
922
- writeEvent({ event: "permission_request", session_id: session.sessionId, request });
923
- return await new Promise((resolve) => {
924
- session.pendingPermissions.set(toolUseId, {
925
- resolve,
926
- toolName,
927
- inputData: inputData,
928
- suggestions: options.suggestions,
929
- });
930
- });
931
- };
932
- const claudeCodeExecutable = process.env.CLAUDE_CODE_EXECUTABLE;
933
- const sdkDebugFile = process.env.CLAUDE_RS_SDK_DEBUG_FILE;
934
- const enableSdkDebug = process.env.CLAUDE_RS_SDK_DEBUG === "1" || Boolean(sdkDebugFile);
935
- const enableSpawnDebug = process.env.CLAUDE_RS_SDK_SPAWN_DEBUG === "1";
936
- if (claudeCodeExecutable && !fs.existsSync(claudeCodeExecutable)) {
937
- throw new Error(`CLAUDE_CODE_EXECUTABLE does not exist: ${claudeCodeExecutable}`);
938
- }
939
- let queryHandle;
940
- try {
941
- queryHandle = query({
942
- prompt: input,
943
- options: {
944
- cwd: params.cwd,
945
- includePartialMessages: true,
946
- executable: "node",
947
- ...(params.resume ? {} : { sessionId: provisionalSessionId }),
948
- ...(claudeCodeExecutable
949
- ? { pathToClaudeCodeExecutable: claudeCodeExecutable }
950
- : {}),
951
- ...(enableSdkDebug ? { debug: true } : {}),
952
- ...(sdkDebugFile ? { debugFile: sdkDebugFile } : {}),
953
- stderr: (line) => {
954
- if (line.trim().length > 0) {
955
- console.error(`[sdk stderr] ${line}`);
956
- }
957
- },
958
- ...(enableSpawnDebug
959
- ? {
960
- spawnClaudeCodeProcess: (options) => {
961
- console.error(`[sdk spawn] command=${options.command} args=${JSON.stringify(options.args)} cwd=${options.cwd ?? "<none>"}`);
962
- const child = spawnChild(options.command, options.args, {
963
- cwd: options.cwd,
964
- env: options.env,
965
- signal: options.signal,
966
- stdio: ["pipe", "pipe", "pipe"],
967
- windowsHide: true,
968
- });
969
- child.on("error", (error) => {
970
- console.error(`[sdk spawn error] code=${error.code ?? "<none>"} message=${error.message}`);
971
- });
972
- return child;
973
- },
974
- }
975
- : {}),
976
- // Match claude-agent-acp defaults to avoid emitting an empty
977
- // --setting-sources argument.
978
- settingSources: ["user", "project", "local"],
979
- permissionMode: startMode,
980
- allowDangerouslySkipPermissions: params.yolo,
981
- resume: params.resume,
982
- model: params.model,
983
- canUseTool,
984
- },
985
- });
986
- }
987
- catch (error) {
988
- const message = error instanceof Error ? error.message : String(error);
989
- throw new Error(`query() failed: node_executable=${process.execPath}; cwd=${params.cwd}; ` +
990
- `resume=${params.resume ?? "<none>"}; model=${params.model ?? "<none>"}; ` +
991
- `CLAUDE_CODE_EXECUTABLE=${claudeCodeExecutable ?? "<unset>"}; error=${message}`);
992
- }
993
- session = {
994
- sessionId: provisionalSessionId,
995
- cwd: params.cwd,
996
- model: params.model ?? "default",
997
- mode: startMode,
998
- yolo: params.yolo,
999
- query: queryHandle,
1000
- input,
1001
- connected: false,
1002
- connectEvent: params.connectEvent,
1003
- connectRequestId: params.requestId,
1004
- toolCalls: new Map(),
1005
- taskToolUseIds: new Map(),
1006
- pendingPermissions: new Map(),
1007
- authHintSent: false,
1008
- ...(params.resumeUpdates && params.resumeUpdates.length > 0
1009
- ? { resumeUpdates: params.resumeUpdates }
1010
- : {}),
1011
- ...(params.sessionsToCloseAfterConnect
1012
- ? { sessionsToCloseAfterConnect: params.sessionsToCloseAfterConnect }
1013
- : {}),
1014
- };
1015
- sessions.set(provisionalSessionId, session);
1016
- // In stream-input mode the SDK may defer init until input arrives.
1017
- // Trigger initialization explicitly so the Rust UI can receive `connected`
1018
- // before the first user prompt.
1019
- void session.query
1020
- .initializationResult()
1021
- .then((result) => {
1022
- if (!session.connected) {
1023
- emitConnectEvent(session);
1024
- }
1025
- const commands = Array.isArray(result.commands)
1026
- ? result.commands.map((command) => ({
1027
- name: command.name,
1028
- description: command.description ?? "",
1029
- input_hint: command.argumentHint ?? undefined,
1030
- }))
1031
- : [];
1032
- if (commands.length > 0) {
1033
- emitSessionUpdate(session.sessionId, { type: "available_commands_update", commands });
1034
- }
1035
- })
1036
- .catch((error) => {
1037
- if (session.connected) {
1038
- return;
1039
- }
1040
- const message = error instanceof Error ? error.message : String(error);
1041
- failConnection(`agent initialization failed: ${message}`, session.connectRequestId);
1042
- session.connectRequestId = undefined;
1043
- });
1044
- void (async () => {
1045
- try {
1046
- for await (const message of session.query) {
1047
- handleSdkMessage(session, message);
1048
- }
1049
- if (!session.connected) {
1050
- failConnection("agent stream ended before session initialization", params.requestId);
1051
- }
1052
- }
1053
- catch (error) {
1054
- const message = error instanceof Error ? error.message : String(error);
1055
- failConnection(`agent stream failed: ${message}`, params.requestId);
1056
- }
1057
- })();
1058
- }
1059
- function handlePermissionResponse(command) {
1060
- const session = sessionById(command.session_id);
1061
- if (!session) {
1062
- logPermissionDebug(`response dropped: unknown session session_id=${command.session_id} tool_call_id=${command.tool_call_id}`);
1063
- return;
1064
- }
1065
- const resolver = session.pendingPermissions.get(command.tool_call_id);
1066
- if (!resolver) {
1067
- logPermissionDebug(`response dropped: no pending resolver session_id=${command.session_id} tool_call_id=${command.tool_call_id}`);
1068
- return;
1069
- }
1070
- session.pendingPermissions.delete(command.tool_call_id);
1071
- const outcome = command.outcome;
1072
- if (resolver.onOutcome) {
1073
- resolver.onOutcome(outcome);
1074
- return;
1075
- }
1076
- if (!resolver.resolve) {
1077
- logPermissionDebug(`response dropped: resolver missing callback session_id=${command.session_id} tool_call_id=${command.tool_call_id}`);
1078
- return;
1079
- }
1080
- const selectedOption = outcome.outcome === "selected" ? outcome.option_id : "cancelled";
1081
- logPermissionDebug(`response session_id=${command.session_id} tool_call_id=${command.tool_call_id} tool=${resolver.toolName} ` +
1082
- `selected=${selectedOption} suggestions=${formatPermissionUpdates(resolver.suggestions)}`);
1083
- if (outcome.outcome === "selected" &&
1084
- (outcome.option_id === "allow_once" ||
1085
- outcome.option_id === "allow_session" ||
1086
- outcome.option_id === "allow_always")) {
1087
- setToolCallStatus(session, command.tool_call_id, "in_progress");
1088
- }
1089
- else if (outcome.outcome === "selected") {
1090
- setToolCallStatus(session, command.tool_call_id, "failed", "Permission denied");
1091
- }
1092
- else {
1093
- setToolCallStatus(session, command.tool_call_id, "failed", "Permission cancelled");
1094
- }
1095
- const permissionResult = permissionResultFromOutcome(outcome, command.tool_call_id, resolver.inputData, resolver.suggestions, resolver.toolName);
1096
- if (permissionResult.behavior === "allow") {
1097
- logPermissionDebug(`result tool_call_id=${command.tool_call_id} behavior=allow updated_permissions=` +
1098
- `${formatPermissionUpdates(permissionResult.updatedPermissions)}`);
1099
- }
1100
- else {
1101
- logPermissionDebug(`result tool_call_id=${command.tool_call_id} behavior=deny message=${permissionResult.message}`);
1102
- }
1103
- resolver.resolve(permissionResult);
1104
- }
1105
45
  async function handleCommand(command, requestId) {
1106
46
  const sdkVersionError = agentSdkVersionCompatibilityError();
1107
47
  if (sdkVersionError && command.command !== "initialize" && command.command !== "shutdown") {
@@ -1129,46 +69,38 @@ async function handleCommand(command, requestId) {
1129
69
  capabilities: {
1130
70
  prompt_image: false,
1131
71
  prompt_embedded_context: true,
1132
- load_session: true,
1133
- supports_list_sessions: true,
1134
- supports_resume: true,
72
+ supports_session_listing: true,
73
+ supports_resume_session: true,
1135
74
  },
1136
75
  },
1137
76
  }, requestId);
1138
- writeEvent({
1139
- event: "sessions_listed",
1140
- sessions: listRecentPersistedSessions().map((entry) => ({
1141
- session_id: entry.session_id,
1142
- cwd: entry.cwd,
1143
- ...(entry.title ? { title: entry.title } : {}),
1144
- ...(entry.updated_at ? { updated_at: entry.updated_at } : {}),
1145
- })),
1146
- });
77
+ await emitSessionsList(requestId);
1147
78
  return;
1148
79
  case "create_session":
1149
80
  await createSession({
1150
81
  cwd: command.cwd,
1151
- yolo: command.yolo,
1152
- model: command.model,
1153
82
  resume: command.resume,
83
+ launchSettings: command.launch_settings,
1154
84
  connectEvent: "connected",
1155
85
  requestId,
1156
86
  });
1157
87
  return;
1158
- case "load_session": {
1159
- const persisted = resolvePersistedSessionEntry(command.session_id);
1160
- if (!persisted) {
1161
- slashError(command.session_id, `unknown session: ${command.session_id}`, requestId);
1162
- return;
1163
- }
1164
- const resumeUpdates = extractSessionHistoryUpdatesFromJsonl(persisted.file_path);
1165
- const staleSessions = Array.from(sessions.values());
1166
- const hadActiveSession = staleSessions.length > 0;
88
+ case "resume_session": {
1167
89
  try {
90
+ const sdkSessions = await listSessions();
91
+ const matched = sdkSessions.find((entry) => entry.sessionId === command.session_id);
92
+ if (!matched) {
93
+ slashError(command.session_id, `unknown session: ${command.session_id}`, requestId);
94
+ return;
95
+ }
96
+ const historyMessages = await getSessionMessages(command.session_id, matched.cwd ? { dir: matched.cwd } : undefined);
97
+ const resumeUpdates = mapSessionMessagesToUpdates(historyMessages);
98
+ const staleSessions = Array.from(sessions.values());
99
+ const hadActiveSession = staleSessions.length > 0;
1168
100
  await createSession({
1169
- cwd: persisted.cwd,
1170
- yolo: false,
101
+ cwd: matched.cwd ?? process.cwd(),
1171
102
  resume: command.session_id,
103
+ launchSettings: command.launch_settings,
1172
104
  ...(resumeUpdates.length > 0 ? { resumeUpdates } : {}),
1173
105
  connectEvent: hadActiveSession ? "session_replaced" : "connected",
1174
106
  requestId,
@@ -1185,8 +117,7 @@ async function handleCommand(command, requestId) {
1185
117
  await closeAllSessions();
1186
118
  await createSession({
1187
119
  cwd: command.cwd,
1188
- yolo: command.yolo,
1189
- model: command.model,
120
+ launchSettings: command.launch_settings,
1190
121
  connectEvent: "session_replaced",
1191
122
  requestId,
1192
123
  });