claude-code-rust 0.14.3 → 0.14.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.
@@ -1,16 +1,16 @@
1
1
  import { asRecordOrNull } from "./shared.js";
2
- import { toPermissionMode, buildModeState, refreshSupportedModesForSession } from "./commands.js";
2
+ import { toPermissionMode, buildModeState, refreshSupportedModesForSession, } from "./commands.js";
3
3
  import { writeEvent, emitSessionUpdate, emitConnectEvent, emitSessionReplacedEvent, } from "./events.js";
4
4
  import { TOOL_RESULT_TYPES, isToolSearchToolName, isToolSearchToolResultType, unwrapToolUseResult, parseToolNonExecutionMetadata, } from "./tooling.js";
5
5
  import { emitToolCall, emitToolCallUpdate, emitToolResultUpdate, finalizeOpenToolCalls, emitToolProgressUpdate, emitToolSummaryUpdate, ensureToolCallVisible, resolveTaskToolUseId, defersTaskNotificationCompletion, toolAcceptsTaskLifecycle, taskProgressText, taskUpdatedFields, } from "./tool_calls.js";
6
- import { applyBackgroundTasksChanged, applyTaskLifecycleState } from "./tasks.js";
6
+ import { applyBackgroundTasksChanged, applyTaskLifecycleState, } from "./tasks.js";
7
7
  import { linkTaskToolUse, unlinkTaskToolUse } from "./task_links.js";
8
8
  import { emitAuthRequired, classifyTurnErrorKind, emitFastModeUpdate, emitFastModeUpdateIfChanged, setFastModeSnapshotIfChanged, } from "./error_classification.js";
9
- import { mapAvailableAgentsFromNames, emitAvailableAgentsIfChanged, refreshAvailableAgents } from "./agents.js";
9
+ import { mapAvailableAgentsFromNames, emitAvailableAgentsIfChanged, refreshAvailableAgents, } from "./agents.js";
10
10
  import { mapInitSlashCommands, mapSdkSlashCommands, updateAvailableCommands, } from "./available_commands.js";
11
11
  import { buildApiRetryUpdate, buildRateLimitUpdate, buildSubagentRetryUpdate, normalizeSettingsParseErrors, nonNegativeIntegerField, numberField, parseApiRetryError, parseRuntimeSessionState, } from "./state_parsing.js";
12
12
  import { looksLikeAuthRequired } from "./auth.js";
13
- import { emitCurrentModelUpdate, refreshCurrentModel, updateSessionId } from "./session_lifecycle.js";
13
+ import { emitCurrentModelUpdate, refreshCurrentModel, updateSessionId, } from "./session_lifecycle.js";
14
14
  import { bridgeLogger, LOG_TARGETS } from "./logger.js";
15
15
  import { emitMcpSnapshotFromStatuses } from "./mcp.js";
16
16
  export function textFromPrompt(command) {
@@ -38,23 +38,41 @@ function sdkCorrelationMetadata(msg) {
38
38
  return {
39
39
  requestId: typeof msg.request_id === "string" ? msg.request_id : undefined,
40
40
  subagentType: typeof msg.subagent_type === "string" ? msg.subagent_type : undefined,
41
- taskDescription: typeof msg.task_description === "string" ? msg.task_description : undefined,
41
+ taskDescription: typeof msg.task_description === "string"
42
+ ? msg.task_description
43
+ : undefined,
42
44
  parentAgentId: typeof msg.parent_agent_id === "string" ? msg.parent_agent_id : undefined,
43
45
  };
44
46
  }
45
47
  function sdkTaskMetadata(msg) {
46
48
  const metadata = sdkCorrelationMetadata(msg);
47
- const taskType = typeof msg.task_type === "string" && msg.task_type.length > 0 ? msg.task_type : undefined;
48
- const workflowName = typeof msg.workflow_name === "string" && msg.workflow_name.length > 0 ? msg.workflow_name : undefined;
49
- const prompt = typeof msg.prompt === "string" && msg.prompt.length > 0 ? msg.prompt : undefined;
50
- const outputFile = typeof msg.output_file === "string" && msg.output_file.length > 0 ? msg.output_file : undefined;
51
- const status = typeof msg.status === "string" && msg.status.length > 0 ? msg.status : undefined;
52
- const summary = status && typeof msg.summary === "string" && msg.summary.length > 0 ? msg.summary : undefined;
49
+ const taskType = typeof msg.task_type === "string" && msg.task_type.length > 0
50
+ ? msg.task_type
51
+ : undefined;
52
+ const workflowName = typeof msg.workflow_name === "string" && msg.workflow_name.length > 0
53
+ ? msg.workflow_name
54
+ : undefined;
55
+ const prompt = typeof msg.prompt === "string" && msg.prompt.length > 0
56
+ ? msg.prompt
57
+ : undefined;
58
+ const outputFile = typeof msg.output_file === "string" && msg.output_file.length > 0
59
+ ? msg.output_file
60
+ : undefined;
61
+ const status = typeof msg.status === "string" && msg.status.length > 0
62
+ ? msg.status
63
+ : undefined;
64
+ const summary = status && typeof msg.summary === "string" && msg.summary.length > 0
65
+ ? msg.summary
66
+ : undefined;
53
67
  const taskMetadata = {
54
68
  ...(metadata.requestId ? { request_id: metadata.requestId } : {}),
55
69
  ...(metadata.subagentType ? { subagent_type: metadata.subagentType } : {}),
56
- ...(metadata.taskDescription ? { task_description: metadata.taskDescription } : {}),
57
- ...(metadata.parentAgentId ? { parent_agent_id: metadata.parentAgentId } : {}),
70
+ ...(metadata.taskDescription
71
+ ? { task_description: metadata.taskDescription }
72
+ : {}),
73
+ ...(metadata.parentAgentId
74
+ ? { parent_agent_id: metadata.parentAgentId }
75
+ : {}),
58
76
  ...(taskType ? { task_type: taskType } : {}),
59
77
  ...(workflowName ? { workflow_name: workflowName } : {}),
60
78
  ...(prompt ? { prompt } : {}),
@@ -66,10 +84,67 @@ function sdkTaskMetadata(msg) {
66
84
  return Object.keys(taskMetadata).length > 0 ? taskMetadata : undefined;
67
85
  }
68
86
  function sdkMessageOriginKind(msg) {
69
- const origin = msg.origin && typeof msg.origin === "object" ? msg.origin : null;
87
+ const origin = msg.origin && typeof msg.origin === "object"
88
+ ? msg.origin
89
+ : null;
70
90
  return typeof origin?.kind === "string" ? origin.kind : undefined;
71
91
  }
92
+ function externalMessageUpdateFromSdkUser(msg) {
93
+ const origin = asRecordOrNull(msg.origin);
94
+ if (!origin) {
95
+ return undefined;
96
+ }
97
+ const kind = typeof origin?.kind === "string" ? origin.kind : undefined;
98
+ if (kind !== "peer" && kind !== "task-notification") {
99
+ return undefined;
100
+ }
101
+ const payload = asRecordOrNull(msg.message);
102
+ const content = payload?.content;
103
+ const contentText = typeof content === "string"
104
+ ? content
105
+ : Array.isArray(content)
106
+ ? content
107
+ .flatMap((block) => {
108
+ const record = asRecordOrNull(block);
109
+ return record?.type === "text" && typeof record.text === "string"
110
+ ? [record.text]
111
+ : [];
112
+ })
113
+ .join("\n")
114
+ : "";
115
+ const text = typeof origin.body === "string" ? origin.body : contentText;
116
+ if (!text.trim()) {
117
+ return undefined;
118
+ }
119
+ return {
120
+ type: "external_message_update",
121
+ content: text,
122
+ ...(sourceMessageUuid(msg)
123
+ ? { source_message_uuid: sourceMessageUuid(msg) }
124
+ : {}),
125
+ origin: {
126
+ kind,
127
+ ...(typeof origin.subkind === "string"
128
+ ? { subkind: origin.subkind }
129
+ : {}),
130
+ ...(typeof origin.from === "string" ? { from: origin.from } : {}),
131
+ ...(typeof origin.name === "string" ? { name: origin.name } : {}),
132
+ ...(typeof origin.fromSession === "string"
133
+ ? { from_session: origin.fromSession }
134
+ : {}),
135
+ ...(typeof origin.senderTaskId === "string"
136
+ ? { sender_task_id: origin.senderTaskId }
137
+ : {}),
138
+ ...(typeof origin.verifiedPeerPid === "number" &&
139
+ Number.isSafeInteger(origin.verifiedPeerPid) &&
140
+ origin.verifiedPeerPid >= 0
141
+ ? { verified_peer_pid: origin.verifiedPeerPid }
142
+ : {}),
143
+ },
144
+ };
145
+ }
72
146
  function logSdkMessageOrigin(session, msg) {
147
+ const origin = asRecordOrNull(msg.origin);
73
148
  const originKind = sdkMessageOriginKind(msg);
74
149
  if (!originKind) {
75
150
  return;
@@ -83,6 +158,16 @@ function logSdkMessageOrigin(session, msg) {
83
158
  fields: {
84
159
  message_type: typeof msg.type === "string" ? msg.type : undefined,
85
160
  origin_kind: originKind,
161
+ origin_subkind: typeof origin?.subkind === "string" ? origin.subkind : undefined,
162
+ origin_from_session: typeof origin?.fromSession === "string"
163
+ ? origin.fromSession
164
+ : undefined,
165
+ origin_sender_task_id: typeof origin?.senderTaskId === "string"
166
+ ? origin.senderTaskId
167
+ : undefined,
168
+ origin_verified_peer_pid: typeof origin?.verifiedPeerPid === "number"
169
+ ? origin.verifiedPeerPid
170
+ : undefined,
86
171
  },
87
172
  });
88
173
  }
@@ -91,7 +176,11 @@ function emitSystemNoticeUpdate(session, severity, message) {
91
176
  if (!trimmed) {
92
177
  return;
93
178
  }
94
- emitSessionUpdate(session.sessionId, { type: "system_notice_update", severity, message: trimmed });
179
+ emitSessionUpdate(session.sessionId, {
180
+ type: "system_notice_update",
181
+ severity,
182
+ message: trimmed,
183
+ });
95
184
  }
96
185
  const MAX_INFORMATIONAL_DEDUP_KEYS = 256;
97
186
  function shouldEmitInformationalMessage(session, level, content, toolUseId) {
@@ -203,7 +292,9 @@ function handleModelRefusalNoFallbackMessage(session, msg) {
203
292
  }
204
293
  function workerShutdownMessage(reason) {
205
294
  const trimmed = reason.trim();
206
- return trimmed ? `Claude worker is shutting down: ${trimmed}` : "Claude worker is shutting down.";
295
+ return trimmed
296
+ ? `Claude worker is shutting down: ${trimmed}`
297
+ : "Claude worker is shutting down.";
207
298
  }
208
299
  function handleWorkerShuttingDownSystemMessage(session, msg) {
209
300
  const reason = typeof msg.reason === "string" ? msg.reason.trim() : "";
@@ -280,7 +371,9 @@ export function contentFromPrompt(command) {
280
371
  }
281
372
  }
282
373
  else if (chunk.kind === "image") {
283
- const val = chunk.value && typeof chunk.value === "object" ? chunk.value : null;
374
+ const val = chunk.value && typeof chunk.value === "object"
375
+ ? chunk.value
376
+ : null;
284
377
  if (!val)
285
378
  continue;
286
379
  const data = typeof val.data === "string" ? val.data : "";
@@ -400,7 +493,9 @@ export function handleTaskSystemMessage(session, subtype, msg) {
400
493
  const fields = {
401
494
  status: "in_progress",
402
495
  raw_output: description,
403
- content: [{ type: "content", content: { type: "text", text: description } }],
496
+ content: [
497
+ { type: "content", content: { type: "text", text: description } },
498
+ ],
404
499
  ...(messageTaskMetadata ? { task_metadata: messageTaskMetadata } : {}),
405
500
  };
406
501
  emitToolCallUpdate(session, toolUseId, fields, "task_started");
@@ -423,7 +518,10 @@ export function handleTaskSystemMessage(session, subtype, msg) {
423
518
  if (subtype === "task_updated") {
424
519
  const fields = taskUpdatedFields(msg);
425
520
  if (messageTaskMetadata) {
426
- fields.task_metadata = { ...(fields.task_metadata ?? {}), ...messageTaskMetadata };
521
+ fields.task_metadata = {
522
+ ...(fields.task_metadata ?? {}),
523
+ ...messageTaskMetadata,
524
+ };
427
525
  }
428
526
  if (Object.keys(fields).length === 0) {
429
527
  return true;
@@ -451,15 +549,23 @@ export function handleTaskSystemMessage(session, subtype, msg) {
451
549
  }
452
550
  const status = typeof msg.status === "string" ? msg.status : "";
453
551
  const summary = typeof msg.summary === "string" ? msg.summary : "";
454
- const finalStatus = status === "completed" ? "completed" : status === "stopped" ? "killed" : "failed";
552
+ const finalStatus = status === "completed"
553
+ ? "completed"
554
+ : status === "stopped"
555
+ ? "killed"
556
+ : "failed";
455
557
  const deferCompletion = finalStatus === "completed" && defersTaskNotificationCompletion(toolCall);
456
- const fields = deferCompletion ? {} : { status: finalStatus };
558
+ const fields = deferCompletion
559
+ ? {}
560
+ : { status: finalStatus };
457
561
  if (messageTaskMetadata) {
458
562
  fields.task_metadata = messageTaskMetadata;
459
563
  }
460
564
  if (summary) {
461
565
  fields.raw_output = summary;
462
- fields.content = [{ type: "content", content: { type: "text", text: summary } }];
566
+ fields.content = [
567
+ { type: "content", content: { type: "text", text: summary } },
568
+ ];
463
569
  }
464
570
  if (Object.keys(fields).length > 0) {
465
571
  emitToolCallUpdate(session, toolUseId, fields, "task_notification");
@@ -510,10 +616,19 @@ function emitTranscriptRetraction(session, messageUuids, reason, metadata = {})
510
616
  ...(metadata.requestId ? { request_id: metadata.requestId } : {}),
511
617
  ...(metadata.trigger ? { trigger: metadata.trigger } : {}),
512
618
  ...(metadata.direction ? { direction: metadata.direction } : {}),
513
- ...(metadata.originalModel ? { original_model: metadata.originalModel } : {}),
514
- ...(metadata.fallbackModel ? { fallback_model: metadata.fallbackModel } : {}),
515
- ...(metadata.apiRefusalCategory ? { api_refusal_category: metadata.apiRefusalCategory } : {}),
516
- ...(metadata.apiRefusalExplanation ? { api_refusal_explanation: metadata.apiRefusalExplanation } : {}),
619
+ ...(metadata.originalModel
620
+ ? { original_model: metadata.originalModel }
621
+ : {}),
622
+ ...(metadata.fallbackModel
623
+ ? { fallback_model: metadata.fallbackModel }
624
+ : {}),
625
+ ...(metadata.scope ? { scope: metadata.scope } : {}),
626
+ ...(metadata.apiRefusalCategory
627
+ ? { api_refusal_category: metadata.apiRefusalCategory }
628
+ : {}),
629
+ ...(metadata.apiRefusalExplanation
630
+ ? { api_refusal_explanation: metadata.apiRefusalExplanation }
631
+ : {}),
517
632
  ...(metadata.content ? { content: metadata.content } : {}),
518
633
  });
519
634
  return true;
@@ -530,6 +645,7 @@ function handleFallbackRetractionMessage(session, subtype, msg) {
530
645
  direction: stringField(msg, "direction"),
531
646
  originalModel: stringField(msg, "original_model"),
532
647
  fallbackModel: stringField(msg, "fallback_model"),
648
+ scope: stringField(msg, "scope") ?? "session",
533
649
  apiRefusalCategory: nullableStringField(msg, "api_refusal_category"),
534
650
  apiRefusalExplanation: nullableStringField(msg, "api_refusal_explanation"),
535
651
  content: stringField(msg, "content"),
@@ -549,6 +665,7 @@ function handleFallbackRetractionMessage(session, subtype, msg) {
549
665
  direction: metadata.direction,
550
666
  original_model: metadata.originalModel,
551
667
  fallback_model: metadata.fallbackModel,
668
+ scope: metadata.scope,
552
669
  api_refusal_category: metadata.apiRefusalCategory,
553
670
  has_api_refusal_explanation: metadata.apiRefusalExplanation !== undefined,
554
671
  has_content: metadata.content !== undefined,
@@ -621,7 +738,9 @@ export function handleContentBlock(session, block, linkage) {
621
738
  emitSessionUpdate(session.sessionId, {
622
739
  type: "agent_message_chunk",
623
740
  content: { type: "text", text },
624
- ...(linkage?.sourceMessageUuid ? { source_message_uuid: linkage.sourceMessageUuid } : {}),
741
+ ...(linkage?.sourceMessageUuid
742
+ ? { source_message_uuid: linkage.sourceMessageUuid }
743
+ : {}),
625
744
  });
626
745
  }
627
746
  return;
@@ -632,15 +751,21 @@ export function handleContentBlock(session, block, linkage) {
632
751
  emitSessionUpdate(session.sessionId, {
633
752
  type: "agent_thought_chunk",
634
753
  content: { type: "text", text },
635
- ...(linkage?.sourceMessageUuid ? { source_message_uuid: linkage.sourceMessageUuid } : {}),
754
+ ...(linkage?.sourceMessageUuid
755
+ ? { source_message_uuid: linkage.sourceMessageUuid }
756
+ : {}),
636
757
  });
637
758
  }
638
759
  return;
639
760
  }
640
- if (blockType === "tool_use" || blockType === "server_tool_use" || blockType === "mcp_tool_use") {
761
+ if (blockType === "tool_use" ||
762
+ blockType === "server_tool_use" ||
763
+ blockType === "mcp_tool_use") {
641
764
  const toolUseId = typeof block.id === "string" ? block.id : "";
642
765
  const name = typeof block.name === "string" ? block.name : "Tool";
643
- const input = block.input && typeof block.input === "object" ? block.input : {};
766
+ const input = block.input && typeof block.input === "object"
767
+ ? block.input
768
+ : {};
644
769
  if (!toolUseId) {
645
770
  return;
646
771
  }
@@ -688,7 +813,9 @@ export function handleStreamEvent(session, event, parentToolUseId, sourceMessage
688
813
  emitSessionUpdate(session.sessionId, {
689
814
  type: "agent_message_chunk",
690
815
  content: { type: "text", text },
691
- ...(sourceMessageUuid ? { source_message_uuid: sourceMessageUuid } : {}),
816
+ ...(sourceMessageUuid
817
+ ? { source_message_uuid: sourceMessageUuid }
818
+ : {}),
692
819
  });
693
820
  }
694
821
  }
@@ -698,7 +825,9 @@ export function handleStreamEvent(session, event, parentToolUseId, sourceMessage
698
825
  emitSessionUpdate(session.sessionId, {
699
826
  type: "agent_thought_chunk",
700
827
  content: { type: "text", text },
701
- ...(sourceMessageUuid ? { source_message_uuid: sourceMessageUuid } : {}),
828
+ ...(sourceMessageUuid
829
+ ? { source_message_uuid: sourceMessageUuid }
830
+ : {}),
702
831
  });
703
832
  }
704
833
  }
@@ -718,7 +847,9 @@ export function handleAssistantMessage(session, message) {
718
847
  if (!messageObject) {
719
848
  return;
720
849
  }
721
- const content = Array.isArray(messageObject.content) ? messageObject.content : [];
850
+ const content = Array.isArray(messageObject.content)
851
+ ? messageObject.content
852
+ : [];
722
853
  for (const block of content) {
723
854
  if (!block || typeof block !== "object") {
724
855
  continue;
@@ -729,7 +860,9 @@ export function handleAssistantMessage(session, message) {
729
860
  blockType === "server_tool_use" ||
730
861
  blockType === "mcp_tool_use" ||
731
862
  TOOL_RESULT_TYPES.has(blockType)) {
732
- const parentToolUseId = typeof message.parent_tool_use_id === "string" ? message.parent_tool_use_id : undefined;
863
+ const parentToolUseId = typeof message.parent_tool_use_id === "string"
864
+ ? message.parent_tool_use_id
865
+ : undefined;
733
866
  handleContentBlock(session, blockRecord, {
734
867
  source: "assistant",
735
868
  parentToolUseId,
@@ -755,7 +888,9 @@ export function handleUserToolResultBlocks(session, message) {
755
888
  if (!messageObject) {
756
889
  return false;
757
890
  }
758
- const content = Array.isArray(messageObject.content) ? messageObject.content : [];
891
+ const content = Array.isArray(messageObject.content)
892
+ ? messageObject.content
893
+ : [];
759
894
  const nonExecutionByToolUseId = parseToolNonExecutionMetadata(message.tool_result_meta);
760
895
  let handled = false;
761
896
  for (const block of content) {
@@ -765,8 +900,12 @@ export function handleUserToolResultBlocks(session, message) {
765
900
  const blockRecord = block;
766
901
  const blockType = typeof blockRecord.type === "string" ? blockRecord.type : "";
767
902
  if (TOOL_RESULT_TYPES.has(blockType)) {
768
- const parentToolUseId = typeof message.parent_tool_use_id === "string" ? message.parent_tool_use_id : undefined;
769
- const toolUseId = typeof blockRecord.tool_use_id === "string" ? blockRecord.tool_use_id : "";
903
+ const parentToolUseId = typeof message.parent_tool_use_id === "string"
904
+ ? message.parent_tool_use_id
905
+ : undefined;
906
+ const toolUseId = typeof blockRecord.tool_use_id === "string"
907
+ ? blockRecord.tool_use_id
908
+ : "";
770
909
  if (!toolUseId) {
771
910
  continue;
772
911
  }
@@ -798,9 +937,30 @@ export function handleResultMessage(session, message) {
798
937
  });
799
938
  return;
800
939
  }
801
- const errors = Array.isArray(message.errors) && message.errors.every((entry) => typeof entry === "string")
940
+ const errors = Array.isArray(message.errors) &&
941
+ message.errors.every((entry) => typeof entry === "string")
802
942
  ? message.errors
803
943
  : [];
944
+ const resumeDropsTurnRefusal = errors.find((entry) => entry.startsWith("Resume rejected by --resume-drops-turn:"));
945
+ if (session.deferConnect &&
946
+ session.resumeDropsTurn &&
947
+ resumeDropsTurnRefusal) {
948
+ session.initializationReady = false;
949
+ session.initializationError = resumeDropsTurnRefusal;
950
+ bridgeLogger.warn({
951
+ target: LOG_TARGETS.APP_SESSION,
952
+ eventName: "session_resume_drops_turn_rejected",
953
+ message: "guarded resume candidate rejected because the source session changed",
954
+ outcome: "failure",
955
+ sessionId: session.sessionId,
956
+ fields: {
957
+ drop_turn_id: session.resumeDropsTurn,
958
+ validation_fence_complete: session.resumeGuardFenceComplete === true,
959
+ error_message: resumeDropsTurnRefusal,
960
+ },
961
+ });
962
+ return;
963
+ }
804
964
  const assistantError = session.lastAssistantError;
805
965
  const authHint = errors.find((entry) => looksLikeAuthRequired(entry));
806
966
  if (authHint) {
@@ -820,7 +980,9 @@ export function handleResultMessage(session, message) {
820
980
  error_kind: errorKind,
821
981
  ...(subtype ? { sdk_result_subtype: subtype } : {}),
822
982
  ...(assistantError ? { assistant_error: assistantError } : {}),
823
- ...(apiErrorStatus !== undefined ? { api_error_status: apiErrorStatus } : {}),
983
+ ...(apiErrorStatus !== undefined
984
+ ? { api_error_status: apiErrorStatus }
985
+ : {}),
824
986
  ...(terminalReason ? { terminal_reason: terminalReason } : {}),
825
987
  });
826
988
  session.lastAssistantError = undefined;
@@ -940,8 +1102,12 @@ export function handleSdkMessage(session, message) {
940
1102
  fields: {
941
1103
  tool_name: typeof msg.tool_name === "string" ? msg.tool_name : undefined,
942
1104
  agent_id: typeof msg.agent_id === "string" ? msg.agent_id : undefined,
943
- decision_reason_type: typeof msg.decision_reason_type === "string" ? msg.decision_reason_type : undefined,
944
- decision_reason: typeof msg.decision_reason === "string" ? msg.decision_reason : undefined,
1105
+ decision_reason_type: typeof msg.decision_reason_type === "string"
1106
+ ? msg.decision_reason_type
1107
+ : undefined,
1108
+ decision_reason: typeof msg.decision_reason === "string"
1109
+ ? msg.decision_reason
1110
+ : undefined,
945
1111
  denial_message: typeof msg.message === "string" ? msg.message : undefined,
946
1112
  },
947
1113
  });
@@ -956,9 +1122,15 @@ export function handleSdkMessage(session, message) {
956
1122
  sessionId: session.sessionId,
957
1123
  fields: {
958
1124
  sdk_subtype: subtype,
959
- memory_count: Array.isArray(msg.memories) ? msg.memories.length : undefined,
960
- estimated_tokens: typeof msg.estimated_tokens === "number" ? msg.estimated_tokens : undefined,
961
- estimated_tokens_delta: typeof msg.estimated_tokens_delta === "number" ? msg.estimated_tokens_delta : undefined,
1125
+ memory_count: Array.isArray(msg.memories)
1126
+ ? msg.memories.length
1127
+ : undefined,
1128
+ estimated_tokens: typeof msg.estimated_tokens === "number"
1129
+ ? msg.estimated_tokens
1130
+ : undefined,
1131
+ estimated_tokens_delta: typeof msg.estimated_tokens_delta === "number"
1132
+ ? msg.estimated_tokens_delta
1133
+ : undefined,
962
1134
  },
963
1135
  });
964
1136
  return;
@@ -987,7 +1159,9 @@ export function handleSdkMessage(session, message) {
987
1159
  const modelName = typeof msg.model === "string" ? msg.model : session.model;
988
1160
  session.model = modelName;
989
1161
  const currentModelChanged = refreshCurrentModel(session, false);
990
- const incomingMode = typeof msg.permissionMode === "string" ? toPermissionMode(msg.permissionMode) : null;
1162
+ const incomingMode = typeof msg.permissionMode === "string"
1163
+ ? toPermissionMode(msg.permissionMode)
1164
+ : null;
991
1165
  if (incomingMode) {
992
1166
  session.mode = incomingMode;
993
1167
  }
@@ -1019,7 +1193,8 @@ export function handleSdkMessage(session, message) {
1019
1193
  if (Array.isArray(msg.mcp_servers)) {
1020
1194
  emitMcpSnapshotFromStatuses(session, msg.mcp_servers, "init");
1021
1195
  }
1022
- if (session.lastAvailableAgentsSignature === undefined && Array.isArray(msg.agents)) {
1196
+ if (session.lastAvailableAgentsSignature === undefined &&
1197
+ Array.isArray(msg.agents)) {
1023
1198
  emitAvailableAgentsIfChanged(session, mapAvailableAgentsFromNames(msg.agents));
1024
1199
  }
1025
1200
  void session.query
@@ -1041,17 +1216,28 @@ export function handleSdkMessage(session, message) {
1041
1216
  return;
1042
1217
  }
1043
1218
  if (subtype === "status") {
1044
- const mode = typeof msg.permissionMode === "string" ? toPermissionMode(msg.permissionMode) : null;
1219
+ const mode = typeof msg.permissionMode === "string"
1220
+ ? toPermissionMode(msg.permissionMode)
1221
+ : null;
1045
1222
  if (mode) {
1046
1223
  session.mode = mode;
1047
1224
  refreshSupportedModesForSession(session);
1048
- emitSessionUpdate(session.sessionId, { type: "current_mode_update", current_mode_id: mode });
1225
+ emitSessionUpdate(session.sessionId, {
1226
+ type: "current_mode_update",
1227
+ current_mode_id: mode,
1228
+ });
1049
1229
  }
1050
1230
  if (msg.status === "compacting") {
1051
- emitSessionUpdate(session.sessionId, { type: "compaction_update", phase: "started" });
1231
+ emitSessionUpdate(session.sessionId, {
1232
+ type: "compaction_update",
1233
+ phase: "started",
1234
+ });
1052
1235
  }
1053
1236
  else if (msg.status === "requesting") {
1054
- emitSessionUpdate(session.sessionId, { type: "session_status_update", status: "requesting" });
1237
+ emitSessionUpdate(session.sessionId, {
1238
+ type: "session_status_update",
1239
+ status: "requesting",
1240
+ });
1055
1241
  }
1056
1242
  else if (msg.status === null) {
1057
1243
  if (msg.compact_result === "success") {
@@ -1062,7 +1248,8 @@ export function handleSdkMessage(session, message) {
1062
1248
  });
1063
1249
  }
1064
1250
  else if (msg.compact_result === "failed") {
1065
- const compactError = typeof msg.compact_error === "string" && msg.compact_error.trim().length > 0
1251
+ const compactError = typeof msg.compact_error === "string" &&
1252
+ msg.compact_error.trim().length > 0
1066
1253
  ? msg.compact_error.trim()
1067
1254
  : undefined;
1068
1255
  emitSessionUpdate(session.sessionId, {
@@ -1073,7 +1260,10 @@ export function handleSdkMessage(session, message) {
1073
1260
  ...(compactError ? { error: compactError } : {}),
1074
1261
  });
1075
1262
  }
1076
- emitSessionUpdate(session.sessionId, { type: "session_status_update", status: "idle" });
1263
+ emitSessionUpdate(session.sessionId, {
1264
+ type: "session_status_update",
1265
+ status: "idle",
1266
+ });
1077
1267
  }
1078
1268
  emitFastModeUpdateIfChanged(session, msg.fast_mode_state, msg.fast_mode_disabled_reason);
1079
1269
  return;
@@ -1087,7 +1277,8 @@ export function handleSdkMessage(session, message) {
1087
1277
  const preTokens = nonNegativeIntegerField(compactMetadata, "pre_tokens", "preTokens");
1088
1278
  const postTokens = nonNegativeIntegerField(compactMetadata, "post_tokens", "postTokens");
1089
1279
  const durationMs = nonNegativeIntegerField(compactMetadata, "duration_ms", "durationMs");
1090
- if ((trigger === "manual" || trigger === "auto") && preTokens !== undefined) {
1280
+ if ((trigger === "manual" || trigger === "auto") &&
1281
+ preTokens !== undefined) {
1091
1282
  emitSessionUpdate(session.sessionId, {
1092
1283
  type: "compaction_update",
1093
1284
  phase: "boundary",
@@ -1105,7 +1296,9 @@ export function handleSdkMessage(session, message) {
1105
1296
  emitSessionUpdate(session.sessionId, {
1106
1297
  type: "agent_message_chunk",
1107
1298
  content: { type: "text", text: content },
1108
- ...(sourceMessageUuid(msg) ? { source_message_uuid: sourceMessageUuid(msg) } : {}),
1299
+ ...(sourceMessageUuid(msg)
1300
+ ? { source_message_uuid: sourceMessageUuid(msg) }
1301
+ : {}),
1109
1302
  });
1110
1303
  }
1111
1304
  return;
@@ -1120,7 +1313,9 @@ export function handleSdkMessage(session, message) {
1120
1313
  session_id: session.sessionId,
1121
1314
  completion: {
1122
1315
  elicitation_id: elicitationId,
1123
- ...(typeof msg.mcp_server_name === "string" ? { server_name: msg.mcp_server_name } : {}),
1316
+ ...(typeof msg.mcp_server_name === "string"
1317
+ ? { server_name: msg.mcp_server_name }
1318
+ : {}),
1124
1319
  },
1125
1320
  });
1126
1321
  return;
@@ -1143,7 +1338,10 @@ export function handleSdkMessage(session, message) {
1143
1338
  if (type === "prompt_suggestion") {
1144
1339
  const suggestion = typeof msg.suggestion === "string" ? msg.suggestion.trim() : "";
1145
1340
  if (suggestion) {
1146
- emitSessionUpdate(session.sessionId, { type: "prompt_suggestion_update", suggestion });
1341
+ emitSessionUpdate(session.sessionId, {
1342
+ type: "prompt_suggestion_update",
1343
+ suggestion,
1344
+ });
1147
1345
  }
1148
1346
  return;
1149
1347
  }
@@ -1158,10 +1356,14 @@ export function handleSdkMessage(session, message) {
1158
1356
  }
1159
1357
  if (type === "auth_status") {
1160
1358
  const output = Array.isArray(msg.output)
1161
- ? msg.output.filter((entry) => typeof entry === "string").join("\n")
1359
+ ? msg.output
1360
+ .filter((entry) => typeof entry === "string")
1361
+ .join("\n")
1162
1362
  : "";
1163
1363
  const errorText = typeof msg.error === "string" ? msg.error : "";
1164
- const combined = [errorText, output].filter((entry) => entry.length > 0).join("\n");
1364
+ const combined = [errorText, output]
1365
+ .filter((entry) => entry.length > 0)
1366
+ .join("\n");
1165
1367
  if (combined && looksLikeAuthRequired(combined)) {
1166
1368
  emitAuthRequired(session, combined);
1167
1369
  }
@@ -1169,7 +1371,9 @@ export function handleSdkMessage(session, message) {
1169
1371
  }
1170
1372
  if (type === "stream_event") {
1171
1373
  if (msg.event && typeof msg.event === "object") {
1172
- const parentToolUseId = typeof msg.parent_tool_use_id === "string" ? msg.parent_tool_use_id : undefined;
1374
+ const parentToolUseId = typeof msg.parent_tool_use_id === "string"
1375
+ ? msg.parent_tool_use_id
1376
+ : undefined;
1173
1377
  handleStreamEvent(session, msg.event, parentToolUseId, sourceMessageUuid(msg));
1174
1378
  }
1175
1379
  return;
@@ -1179,7 +1383,9 @@ export function handleSdkMessage(session, message) {
1179
1383
  const toolName = typeof msg.tool_name === "string" ? msg.tool_name : "Tool";
1180
1384
  const parentToolUseId = typeof msg.parent_tool_use_id === "string" ? msg.parent_tool_use_id : "";
1181
1385
  const taskId = typeof msg.task_id === "string" ? msg.task_id : "";
1182
- const taskToolUseId = taskId ? session.taskToolUseIds.get(taskId) ?? "" : "";
1386
+ const taskToolUseId = taskId
1387
+ ? (session.taskToolUseIds.get(taskId) ?? "")
1388
+ : "";
1183
1389
  if (isHiddenToolUse(session, toolUseId, toolName)) {
1184
1390
  return;
1185
1391
  }
@@ -1204,7 +1410,9 @@ export function handleSdkMessage(session, message) {
1204
1410
  });
1205
1411
  if (resolvedToolUseId) {
1206
1412
  const hasSubagentRetry = Object.hasOwn(msg, "subagent_retry");
1207
- const subagentRetry = hasSubagentRetry ? buildSubagentRetryUpdate(msg) : null;
1413
+ const subagentRetry = hasSubagentRetry
1414
+ ? buildSubagentRetryUpdate(msg)
1415
+ : null;
1208
1416
  if (hasSubagentRetry && !subagentRetry) {
1209
1417
  bridgeLogger.warn({
1210
1418
  target: LOG_TARGETS.APP_TOOL,
@@ -1247,8 +1455,12 @@ export function handleSdkMessage(session, message) {
1247
1455
  if (type === "rate_limit_event") {
1248
1456
  const rateLimitInfo = asRecordOrNull(msg.rate_limit_info);
1249
1457
  const update = buildRateLimitUpdate(msg.rate_limit_info);
1250
- const rawIsUsingOverage = typeof rateLimitInfo?.isUsingOverage === "boolean" ? rateLimitInfo.isUsingOverage : undefined;
1251
- const rawOverageInUse = typeof rateLimitInfo?.overageInUse === "boolean" ? rateLimitInfo.overageInUse : undefined;
1458
+ const rawIsUsingOverage = typeof rateLimitInfo?.isUsingOverage === "boolean"
1459
+ ? rateLimitInfo.isUsingOverage
1460
+ : undefined;
1461
+ const rawOverageInUse = typeof rateLimitInfo?.overageInUse === "boolean"
1462
+ ? rateLimitInfo.overageInUse
1463
+ : undefined;
1252
1464
  if (rawIsUsingOverage !== undefined &&
1253
1465
  rawOverageInUse !== undefined &&
1254
1466
  rawIsUsingOverage !== rawOverageInUse) {
@@ -1271,11 +1483,17 @@ export function handleSdkMessage(session, message) {
1271
1483
  outcome: update ? "success" : "dropped",
1272
1484
  sessionId: session.sessionId,
1273
1485
  fields: {
1274
- raw_status: typeof rateLimitInfo?.status === "string" ? rateLimitInfo.status : undefined,
1275
- raw_rate_limit_type: typeof rateLimitInfo?.rateLimitType === "string" ? rateLimitInfo.rateLimitType : undefined,
1486
+ raw_status: typeof rateLimitInfo?.status === "string"
1487
+ ? rateLimitInfo.status
1488
+ : undefined,
1489
+ raw_rate_limit_type: typeof rateLimitInfo?.rateLimitType === "string"
1490
+ ? rateLimitInfo.rateLimitType
1491
+ : undefined,
1276
1492
  raw_utilization: numberField(rateLimitInfo ?? {}, "utilization"),
1277
1493
  raw_resets_at: numberField(rateLimitInfo ?? {}, "resetsAt"),
1278
- raw_overage_status: typeof rateLimitInfo?.overageStatus === "string" ? rateLimitInfo.overageStatus : undefined,
1494
+ raw_overage_status: typeof rateLimitInfo?.overageStatus === "string"
1495
+ ? rateLimitInfo.overageStatus
1496
+ : undefined,
1279
1497
  raw_overage_resets_at: numberField(rateLimitInfo ?? {}, "overageResetsAt"),
1280
1498
  raw_is_using_overage: rawIsUsingOverage,
1281
1499
  raw_overage_in_use: rawOverageInUse,
@@ -1306,6 +1524,10 @@ export function handleSdkMessage(session, message) {
1306
1524
  return;
1307
1525
  }
1308
1526
  if (type === "user") {
1527
+ const externalMessageUpdate = externalMessageUpdateFromSdkUser(msg);
1528
+ if (externalMessageUpdate) {
1529
+ emitSessionUpdate(session.sessionId, externalMessageUpdate);
1530
+ }
1309
1531
  const handledBlocks = handleUserToolResultBlocks(session, msg);
1310
1532
  const toolUseId = typeof msg.parent_tool_use_id === "string" ? msg.parent_tool_use_id : "";
1311
1533
  const rawToolUseResult = messageToolUseResult(msg);