@ai-sdk/harness-claude-code 1.0.41 → 1.0.43

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @ai-sdk/harness-claude-code
2
2
 
3
+ ## 1.0.43
4
+
5
+ ### Patch Changes
6
+
7
+ - @ai-sdk/harness@1.0.42
8
+
9
+ ## 1.0.42
10
+
11
+ ### Patch Changes
12
+
13
+ - 07c977a: chore(harness): refactor bridge code to break out stream event emission from launcher to make it testable
14
+ - Updated dependencies [a94425b]
15
+ - Updated dependencies [2de0611]
16
+ - @ai-sdk/harness@1.0.41
17
+
3
18
  ## 1.0.41
4
19
 
5
20
  ### Patch Changes
@@ -513,7 +513,7 @@ function createCompactionLatch(emit) {
513
513
  }
514
514
 
515
515
  // src/bridge/index.ts
516
- import { randomUUID } from "crypto";
516
+ import { randomUUID as randomUUID2 } from "crypto";
517
517
  import { argv, stdout as stdout2 } from "process";
518
518
  import * as claudeAgentSdk from "@anthropic-ai/claude-agent-sdk";
519
519
  import * as mcpServerModule from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -523,6 +523,263 @@ function toClaudeSkillsOption(skills) {
523
523
  return skills && skills.length > 0 ? "all" : void 0;
524
524
  }
525
525
 
526
+ // src/bridge/create-emit-stream-event.ts
527
+ import { randomUUID } from "crypto";
528
+ function createClaudeStreamEventState() {
529
+ return {
530
+ nativeToolCallNames: /* @__PURE__ */ new Map(),
531
+ approvalRequestedToolUseIds: /* @__PURE__ */ new Set(),
532
+ partialBlocks: /* @__PURE__ */ new Map(),
533
+ stepUsage: void 0,
534
+ pendingStepToolUseIds: /* @__PURE__ */ new Set(),
535
+ pendingStepUsage: void 0,
536
+ stepOpen: false,
537
+ mcpToolUseIds: /* @__PURE__ */ new Set(),
538
+ observedTerminalError: void 0
539
+ };
540
+ }
541
+ var UNRECOVERABLE_API_RETRY_STATUSES = /* @__PURE__ */ new Set([401, 403, 404]);
542
+ function createEmitStreamEvent({
543
+ state,
544
+ emit,
545
+ emitWarning,
546
+ emitTerminalError,
547
+ onCompactionBoundary,
548
+ toCommonName: toCommonName2
549
+ }) {
550
+ let streamStarted = false;
551
+ return (msg) => {
552
+ const type = msg.type;
553
+ if (!streamStarted) {
554
+ const initModel = type === "system" && msg.subtype === "init" && typeof msg.model === "string" ? msg.model : void 0;
555
+ emit({
556
+ type: "stream-start",
557
+ ...initModel ? { modelId: initModel } : {}
558
+ });
559
+ streamStarted = true;
560
+ }
561
+ if (type === "system" && msg.subtype === "api_retry") {
562
+ if (typeof msg.error_status === "number" && UNRECOVERABLE_API_RETRY_STATUSES.has(msg.error_status)) {
563
+ emitTerminalError(
564
+ `HTTP ${msg.error_status}: ${msg.error ?? "provider request failed"}`
565
+ );
566
+ return;
567
+ }
568
+ emitWarning({ message: formatApiRetryWarning(msg) });
569
+ return;
570
+ }
571
+ if (typeof msg.error === "string" && msg.error.trim()) {
572
+ state.observedTerminalError = msg.error.trim();
573
+ }
574
+ if (type === "auth_status" && typeof msg.error === "string" && msg.error.trim()) {
575
+ emitTerminalError(msg.error);
576
+ return;
577
+ }
578
+ if (type === "system" && msg.subtype === "task_updated" && msg.patch?.status === "failed" && typeof msg.patch.error === "string") {
579
+ emitTerminalError(msg.patch.error);
580
+ return;
581
+ }
582
+ if (type === "system" && msg.subtype === "compact_boundary") {
583
+ const meta = msg.compact_metadata;
584
+ if (meta) {
585
+ onCompactionBoundary({
586
+ trigger: meta.trigger,
587
+ ...typeof meta.pre_tokens === "number" ? { tokensBefore: meta.pre_tokens } : {},
588
+ ...typeof meta.post_tokens === "number" ? { tokensAfter: meta.post_tokens } : {}
589
+ });
590
+ }
591
+ return;
592
+ }
593
+ if (type === "stream_event") {
594
+ handleStreamEvent(msg.event, state.partialBlocks, emit);
595
+ return;
596
+ }
597
+ if (type === "assistant" && msg.message?.content) {
598
+ const usage = mapUsage(msg.message.usage);
599
+ const toolUseIds = [];
600
+ let opensStep = false;
601
+ for (const block of msg.message.content) {
602
+ if (block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string") {
603
+ toolUseIds.push(block.id);
604
+ const mcpPrefix = "mcp__harness-tools__";
605
+ if (block.name.startsWith(mcpPrefix)) {
606
+ state.pendingStepToolUseIds.add(block.id);
607
+ state.mcpToolUseIds.add(block.id);
608
+ opensStep = true;
609
+ continue;
610
+ }
611
+ state.nativeToolCallNames.set(block.id, block.name);
612
+ if (state.approvalRequestedToolUseIds.has(block.id)) {
613
+ continue;
614
+ }
615
+ state.pendingStepToolUseIds.add(block.id);
616
+ opensStep = true;
617
+ emit({
618
+ type: "tool-call",
619
+ toolCallId: block.id,
620
+ toolName: toCommonName2(block.name),
621
+ nativeName: block.name,
622
+ input: JSON.stringify(block.input ?? {}),
623
+ providerExecuted: true
624
+ });
625
+ }
626
+ }
627
+ if (opensStep || toolUseIds.length === 0) {
628
+ state.stepOpen = true;
629
+ if (usage) state.pendingStepUsage = usage;
630
+ }
631
+ return;
632
+ }
633
+ if (type === "user" && msg.message?.content) {
634
+ for (const block of msg.message.content) {
635
+ if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
636
+ if (state.mcpToolUseIds.has(block.tool_use_id)) {
637
+ state.mcpToolUseIds.delete(block.tool_use_id);
638
+ state.pendingStepToolUseIds.delete(block.tool_use_id);
639
+ continue;
640
+ }
641
+ state.approvalRequestedToolUseIds.delete(block.tool_use_id);
642
+ const nativeName = state.nativeToolCallNames.get(block.tool_use_id) ?? "unknown";
643
+ state.nativeToolCallNames.delete(block.tool_use_id);
644
+ const toolName = toCommonName2(nativeName);
645
+ const isError = !!block.is_error;
646
+ const content = stringifyContent(block.content);
647
+ const result = toolName === "bash" ? { exitCode: isError ? 1 : 0, stdout: content } : content;
648
+ emit({
649
+ type: "tool-result",
650
+ toolCallId: block.tool_use_id,
651
+ toolName,
652
+ result,
653
+ isError
654
+ });
655
+ state.pendingStepToolUseIds.delete(block.tool_use_id);
656
+ }
657
+ }
658
+ closeStepIfReady({ state, emit });
659
+ }
660
+ };
661
+ }
662
+ function finishApprovalStep({
663
+ state,
664
+ emit,
665
+ approvalId
666
+ }) {
667
+ state.stepOpen = true;
668
+ state.pendingStepToolUseIds.delete(approvalId);
669
+ closeStepIfReady({ state, emit });
670
+ }
671
+ function emitFinishStep({
672
+ state,
673
+ emit,
674
+ usage
675
+ }) {
676
+ emit({
677
+ type: "finish-step",
678
+ finishReason: { unified: "stop", raw: "stop" },
679
+ usage: usage ?? defaultUsage()
680
+ });
681
+ state.stepUsage = usage ?? state.stepUsage;
682
+ state.pendingStepUsage = void 0;
683
+ state.pendingStepToolUseIds = /* @__PURE__ */ new Set();
684
+ state.stepOpen = false;
685
+ }
686
+ function closeStepIfReady({
687
+ state,
688
+ emit
689
+ }) {
690
+ if (!state.stepOpen || state.pendingStepToolUseIds.size > 0 || state.partialBlocks.size > 0) {
691
+ return;
692
+ }
693
+ emitFinishStep({ state, emit, usage: state.pendingStepUsage });
694
+ }
695
+ function formatApiRetryWarning(msg) {
696
+ const details = [];
697
+ if (typeof msg.attempt === "number") {
698
+ const maxRetries = typeof msg.max_retries === "number" ? `/${msg.max_retries}` : "";
699
+ details.push(`attempt ${msg.attempt}${maxRetries}`);
700
+ }
701
+ if (typeof msg.error_status === "number") {
702
+ details.push(`HTTP ${msg.error_status}`);
703
+ }
704
+ if (typeof msg.retry_delay_ms === "number") {
705
+ details.push(`retrying in ${msg.retry_delay_ms}ms`);
706
+ }
707
+ if (msg.error) details.push(msg.error);
708
+ return details.length > 0 ? `Claude Code API retry: ${details.join("; ")}` : "Claude Code API retry";
709
+ }
710
+ function handleStreamEvent(event, partialBlocks, send) {
711
+ if (!event || typeof event.index !== "number") return;
712
+ const index = event.index;
713
+ if (event.type === "content_block_start") {
714
+ const blockType = event.content_block?.type;
715
+ if (blockType === "text") {
716
+ const id = randomUUID();
717
+ partialBlocks.set(index, { id, kind: "text" });
718
+ send({ type: "text-start", id });
719
+ } else if (blockType === "thinking") {
720
+ const id = randomUUID();
721
+ partialBlocks.set(index, { id, kind: "thinking" });
722
+ send({ type: "reasoning-start", id });
723
+ }
724
+ return;
725
+ }
726
+ if (event.type === "content_block_delta") {
727
+ const block = partialBlocks.get(index);
728
+ if (!block) return;
729
+ if (block.kind === "text" && event.delta?.type === "text_delta" && typeof event.delta.text === "string") {
730
+ send({ type: "text-delta", id: block.id, delta: event.delta.text });
731
+ } else if (block.kind === "thinking" && event.delta?.type === "thinking_delta" && typeof event.delta.thinking === "string") {
732
+ send({
733
+ type: "reasoning-delta",
734
+ id: block.id,
735
+ delta: event.delta.thinking
736
+ });
737
+ }
738
+ return;
739
+ }
740
+ if (event.type === "content_block_stop") {
741
+ const block = partialBlocks.get(index);
742
+ if (!block) return;
743
+ partialBlocks.delete(index);
744
+ if (block.kind === "text") {
745
+ send({ type: "text-end", id: block.id });
746
+ } else {
747
+ send({ type: "reasoning-end", id: block.id });
748
+ }
749
+ }
750
+ }
751
+ function stringifyContent(content) {
752
+ if (typeof content === "string") return content;
753
+ if (Array.isArray(content)) {
754
+ return content.map(
755
+ (entry) => entry && typeof entry === "object" && "text" in entry ? String(entry.text ?? "") : JSON.stringify(entry)
756
+ ).join("");
757
+ }
758
+ return JSON.stringify(content);
759
+ }
760
+ function mapUsage(usage) {
761
+ if (!usage || typeof usage !== "object") return void 0;
762
+ const u = usage;
763
+ return {
764
+ inputTokens: {
765
+ total: (u.input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0),
766
+ noCache: u.input_tokens ?? 0,
767
+ cacheRead: u.cache_read_input_tokens ?? 0,
768
+ cacheWrite: u.cache_creation_input_tokens ?? 0
769
+ },
770
+ outputTokens: {
771
+ total: u.output_tokens ?? 0,
772
+ text: u.output_tokens ?? 0
773
+ }
774
+ };
775
+ }
776
+ function defaultUsage() {
777
+ return {
778
+ inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
779
+ outputTokens: { total: 0, text: 0 }
780
+ };
781
+ }
782
+
526
783
  // src/bridge/json-schema-to-zod.ts
527
784
  import { z } from "zod/v4";
528
785
  function jsonSchemaToZodShape(input) {
@@ -653,7 +910,6 @@ var PUBLIC_TO_NATIVE = {
653
910
  ToolSearch: "ToolSearch"
654
911
  };
655
912
  var PUBLIC_TOOL_NAMES = Object.keys(PUBLIC_TO_NATIVE);
656
- var UNRECOVERABLE_API_RETRY_STATUSES = /* @__PURE__ */ new Set([401, 403, 404]);
657
913
  var NATIVE_TOOL_KINDS = {
658
914
  Read: "readonly",
659
915
  Glob: "readonly",
@@ -804,31 +1060,7 @@ async function runTurn(start, turn) {
804
1060
  once: true
805
1061
  });
806
1062
  }
807
- const nativeToolCallNames = /* @__PURE__ */ new Map();
808
- const approvalRequestedToolUseIds = /* @__PURE__ */ new Set();
809
- const partialBlocks = /* @__PURE__ */ new Map();
810
- let stepUsage;
811
- let pendingStepToolUseIds = /* @__PURE__ */ new Set();
812
- let pendingStepUsage;
813
- let stepOpen = false;
814
- const emitFinishStep = (usage) => {
815
- emit({
816
- type: "finish-step",
817
- finishReason: { unified: "stop", raw: "stop" },
818
- usage: usage ?? defaultUsage()
819
- });
820
- stepUsage = usage ?? stepUsage;
821
- pendingStepUsage = void 0;
822
- pendingStepToolUseIds = /* @__PURE__ */ new Set();
823
- stepOpen = false;
824
- };
825
- const closeStepIfReady = () => {
826
- if (!stepOpen || pendingStepToolUseIds.size > 0 || partialBlocks.size > 0) {
827
- return;
828
- }
829
- emitFinishStep(pendingStepUsage);
830
- };
831
- const mcpToolUseIds = /* @__PURE__ */ new Set();
1063
+ const streamEventState = createClaudeStreamEventState();
832
1064
  const mcpServers = {};
833
1065
  if (start.tools && start.tools.length > 0) {
834
1066
  const server = new mcpModule.McpServer({
@@ -842,7 +1074,7 @@ async function runTurn(start, turn) {
842
1074
  tool.description ?? "",
843
1075
  shape,
844
1076
  async (input) => {
845
- const toolCallId = randomUUID();
1077
+ const toolCallId = randomUUID2();
846
1078
  emit({
847
1079
  type: "tool-call",
848
1080
  toolCallId,
@@ -886,12 +1118,10 @@ async function runTurn(start, turn) {
886
1118
  turn,
887
1119
  emit,
888
1120
  finishApprovalStep: (approvalId) => {
889
- stepOpen = true;
890
- pendingStepToolUseIds.delete(approvalId);
891
- closeStepIfReady();
1121
+ finishApprovalStep({ state: streamEventState, emit, approvalId });
892
1122
  },
893
- nativeToolCallNames,
894
- approvalRequestedToolUseIds
1123
+ nativeToolCallNames: streamEventState.nativeToolCallNames,
1124
+ approvalRequestedToolUseIds: streamEventState.approvalRequestedToolUseIds
895
1125
  });
896
1126
  const q = claudeSdk.query({
897
1127
  prompt: queryInput.input,
@@ -934,14 +1164,12 @@ async function runTurn(start, turn) {
934
1164
  turn.onInterrupt(() => q.interrupt());
935
1165
  let turnUsage;
936
1166
  let totalCostUsd;
937
- let observedTerminalError;
938
1167
  let emittedTerminalError = false;
939
1168
  let emittedTerminalFinish = false;
940
- let streamStarted = false;
941
1169
  const emitTerminalError = (message) => {
942
1170
  const normalized = message?.trim();
943
1171
  if (!normalized || emittedTerminalError || emittedTerminalFinish) return;
944
- observedTerminalError = normalized;
1172
+ streamEventState.observedTerminalError = normalized;
945
1173
  emittedTerminalError = true;
946
1174
  turn.emitError({
947
1175
  error: normalized,
@@ -950,123 +1178,24 @@ async function runTurn(start, turn) {
950
1178
  queryInput.close();
951
1179
  abortCtl.abort();
952
1180
  };
1181
+ const emitStreamEvent = createEmitStreamEvent({
1182
+ state: streamEventState,
1183
+ emit,
1184
+ emitWarning: turn.emitWarning,
1185
+ emitTerminalError,
1186
+ onCompactionBoundary: (boundary) => compaction.onBoundary(boundary),
1187
+ toCommonName
1188
+ });
953
1189
  try {
954
1190
  for await (const msg of q) {
955
1191
  if (abortCtl.signal.aborted) break;
956
1192
  const type = msg.type;
957
- if (!streamStarted) {
958
- const initModel = type === "system" && msg.subtype === "init" && typeof msg.model === "string" ? msg.model : void 0;
959
- emit({
960
- type: "stream-start",
961
- ...initModel ? { modelId: initModel } : {}
962
- });
963
- streamStarted = true;
964
- }
965
- if (type === "system" && msg.subtype === "api_retry") {
966
- if (typeof msg.error_status === "number" && UNRECOVERABLE_API_RETRY_STATUSES.has(msg.error_status)) {
967
- emitTerminalError(
968
- `HTTP ${msg.error_status}: ${msg.error ?? "provider request failed"}`
969
- );
970
- continue;
971
- }
972
- turn.emitWarning({ message: formatApiRetryWarning(msg) });
973
- continue;
974
- }
975
- if (typeof msg.error === "string" && msg.error.trim()) {
976
- observedTerminalError = msg.error.trim();
977
- }
978
- if (type === "auth_status" && typeof msg.error === "string" && msg.error.trim()) {
979
- emitTerminalError(msg.error);
980
- continue;
981
- }
982
- if (type === "system" && msg.subtype === "task_updated" && msg.patch?.status === "failed" && typeof msg.patch.error === "string") {
983
- emitTerminalError(msg.patch.error);
984
- continue;
985
- }
986
- if (type === "system" && msg.subtype === "compact_boundary") {
987
- const meta = msg.compact_metadata;
988
- if (meta) {
989
- compaction.onBoundary({
990
- trigger: meta.trigger,
991
- ...typeof meta.pre_tokens === "number" ? { tokensBefore: meta.pre_tokens } : {},
992
- ...typeof meta.post_tokens === "number" ? { tokensAfter: meta.post_tokens } : {}
993
- });
994
- }
995
- continue;
996
- }
997
- if (type === "stream_event") {
998
- handleStreamEvent(msg.event, partialBlocks, emit);
999
- continue;
1000
- }
1001
- if (type === "assistant" && msg.message?.content) {
1002
- const usage = mapUsage(msg.message.usage);
1003
- const toolUseIds = [];
1004
- let opensStep = false;
1005
- for (const block of msg.message.content) {
1006
- if (block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string") {
1007
- toolUseIds.push(block.id);
1008
- const mcpPrefix = "mcp__harness-tools__";
1009
- if (block.name.startsWith(mcpPrefix)) {
1010
- pendingStepToolUseIds.add(block.id);
1011
- mcpToolUseIds.add(block.id);
1012
- opensStep = true;
1013
- continue;
1014
- }
1015
- nativeToolCallNames.set(block.id, block.name);
1016
- if (approvalRequestedToolUseIds.has(block.id)) {
1017
- continue;
1018
- }
1019
- pendingStepToolUseIds.add(block.id);
1020
- opensStep = true;
1021
- emit({
1022
- type: "tool-call",
1023
- toolCallId: block.id,
1024
- toolName: toCommonName(block.name),
1025
- nativeName: block.name,
1026
- input: JSON.stringify(block.input ?? {}),
1027
- providerExecuted: true
1028
- });
1029
- }
1030
- }
1031
- if (opensStep || toolUseIds.length === 0) {
1032
- stepOpen = true;
1033
- if (usage) pendingStepUsage = usage;
1034
- }
1035
- continue;
1036
- }
1037
- if (type === "user" && msg.message?.content) {
1038
- for (const block of msg.message.content) {
1039
- if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
1040
- if (mcpToolUseIds.has(block.tool_use_id)) {
1041
- mcpToolUseIds.delete(block.tool_use_id);
1042
- pendingStepToolUseIds.delete(block.tool_use_id);
1043
- continue;
1044
- }
1045
- approvalRequestedToolUseIds.delete(block.tool_use_id);
1046
- const nativeName = nativeToolCallNames.get(block.tool_use_id) ?? "unknown";
1047
- nativeToolCallNames.delete(block.tool_use_id);
1048
- const toolName = toCommonName(nativeName);
1049
- const isError = !!block.is_error;
1050
- const content = stringifyContent(block.content);
1051
- const result = toolName === "bash" ? { exitCode: isError ? 1 : 0, stdout: content } : content;
1052
- emit({
1053
- type: "tool-result",
1054
- toolCallId: block.tool_use_id,
1055
- toolName,
1056
- result,
1057
- isError
1058
- });
1059
- pendingStepToolUseIds.delete(block.tool_use_id);
1060
- }
1061
- }
1062
- closeStepIfReady();
1063
- continue;
1064
- }
1193
+ emitStreamEvent(msg);
1065
1194
  if (type === "result") {
1066
1195
  if (msg.subtype === "success") {
1067
1196
  const emptyResult = !msg.result?.trim?.();
1068
- if (emptyResult && observedTerminalError) {
1069
- emitTerminalError(observedTerminalError);
1197
+ if (emptyResult && streamEventState.observedTerminalError) {
1198
+ emitTerminalError(streamEventState.observedTerminalError);
1070
1199
  continue;
1071
1200
  }
1072
1201
  const usage = msg.usage ?? msg.message?.usage;
@@ -1075,12 +1204,18 @@ async function runTurn(start, turn) {
1075
1204
  if (typeof msg.total_cost_usd === "number") {
1076
1205
  totalCostUsd = (totalCostUsd ?? 0) + msg.total_cost_usd;
1077
1206
  }
1078
- if (stepOpen) emitFinishStep(harnessUsage ?? pendingStepUsage);
1207
+ if (streamEventState.stepOpen) {
1208
+ emitFinishStep({
1209
+ state: streamEventState,
1210
+ emit,
1211
+ usage: harnessUsage ?? streamEventState.pendingStepUsage
1212
+ });
1213
+ }
1079
1214
  queryInput.close();
1080
1215
  break;
1081
1216
  } else {
1082
1217
  emitTerminalError(
1083
- (Array.isArray(msg.errors) ? msg.errors.join("\n") : void 0) || observedTerminalError || msg.result || "Unknown error"
1218
+ (Array.isArray(msg.errors) ? msg.errors.join("\n") : void 0) || streamEventState.observedTerminalError || msg.result || "Unknown error"
1084
1219
  );
1085
1220
  }
1086
1221
  continue;
@@ -1100,66 +1235,10 @@ async function runTurn(start, turn) {
1100
1235
  emit({
1101
1236
  type: "finish",
1102
1237
  finishReason: { unified: "stop", raw: "stop" },
1103
- totalUsage: turnUsage ?? stepUsage ?? defaultUsage(),
1238
+ totalUsage: turnUsage ?? streamEventState.stepUsage ?? defaultUsage(),
1104
1239
  ...totalCostUsd !== void 0 ? { harnessMetadata: { "claude-code": { costUsd: totalCostUsd } } } : {}
1105
1240
  });
1106
1241
  }
1107
- function formatApiRetryWarning(msg) {
1108
- const details = [];
1109
- if (typeof msg.attempt === "number") {
1110
- const maxRetries = typeof msg.max_retries === "number" ? `/${msg.max_retries}` : "";
1111
- details.push(`attempt ${msg.attempt}${maxRetries}`);
1112
- }
1113
- if (typeof msg.error_status === "number") {
1114
- details.push(`HTTP ${msg.error_status}`);
1115
- }
1116
- if (typeof msg.retry_delay_ms === "number") {
1117
- details.push(`retrying in ${msg.retry_delay_ms}ms`);
1118
- }
1119
- if (msg.error) details.push(msg.error);
1120
- return details.length > 0 ? `Claude Code API retry: ${details.join("; ")}` : "Claude Code API retry";
1121
- }
1122
- function handleStreamEvent(event, partialBlocks, send) {
1123
- if (!event || typeof event.index !== "number") return;
1124
- const index = event.index;
1125
- if (event.type === "content_block_start") {
1126
- const blockType = event.content_block?.type;
1127
- if (blockType === "text") {
1128
- const id = randomUUID();
1129
- partialBlocks.set(index, { id, kind: "text" });
1130
- send({ type: "text-start", id });
1131
- } else if (blockType === "thinking") {
1132
- const id = randomUUID();
1133
- partialBlocks.set(index, { id, kind: "thinking" });
1134
- send({ type: "reasoning-start", id });
1135
- }
1136
- return;
1137
- }
1138
- if (event.type === "content_block_delta") {
1139
- const block = partialBlocks.get(index);
1140
- if (!block) return;
1141
- if (block.kind === "text" && event.delta?.type === "text_delta" && typeof event.delta.text === "string") {
1142
- send({ type: "text-delta", id: block.id, delta: event.delta.text });
1143
- } else if (block.kind === "thinking" && event.delta?.type === "thinking_delta" && typeof event.delta.thinking === "string") {
1144
- send({
1145
- type: "reasoning-delta",
1146
- id: block.id,
1147
- delta: event.delta.thinking
1148
- });
1149
- }
1150
- return;
1151
- }
1152
- if (event.type === "content_block_stop") {
1153
- const block = partialBlocks.get(index);
1154
- if (!block) return;
1155
- partialBlocks.delete(index);
1156
- if (block.kind === "text") {
1157
- send({ type: "text-end", id: block.id });
1158
- } else {
1159
- send({ type: "reasoning-end", id: block.id });
1160
- }
1161
- }
1162
- }
1163
1242
  function createQueryInput({
1164
1243
  initialUserMessage,
1165
1244
  pendingUserMessages,
@@ -1211,37 +1290,6 @@ function createQueryInput({
1211
1290
  }
1212
1291
  };
1213
1292
  }
1214
- function stringifyContent(content) {
1215
- if (typeof content === "string") return content;
1216
- if (Array.isArray(content)) {
1217
- return content.map(
1218
- (entry) => entry && typeof entry === "object" && "text" in entry ? String(entry.text ?? "") : JSON.stringify(entry)
1219
- ).join("");
1220
- }
1221
- return JSON.stringify(content);
1222
- }
1223
- function mapUsage(usage) {
1224
- if (!usage || typeof usage !== "object") return void 0;
1225
- const u = usage;
1226
- return {
1227
- inputTokens: {
1228
- total: (u.input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0),
1229
- noCache: u.input_tokens ?? 0,
1230
- cacheRead: u.cache_read_input_tokens ?? 0,
1231
- cacheWrite: u.cache_creation_input_tokens ?? 0
1232
- },
1233
- outputTokens: {
1234
- total: u.output_tokens ?? 0,
1235
- text: u.output_tokens ?? 0
1236
- }
1237
- };
1238
- }
1239
- function defaultUsage() {
1240
- return {
1241
- inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
1242
- outputTokens: { total: 0, text: 0 }
1243
- };
1244
- }
1245
1293
  function parseArgs(args2) {
1246
1294
  const out = {};
1247
1295
  for (let i = 0; i < args2.length; i++) {