@kenkaiiii/gg-ai 4.2.90 → 4.2.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -58,44 +58,62 @@ var EventStream = class {
58
58
  }
59
59
  };
60
60
  var StreamResult = class {
61
- events;
62
61
  response;
62
+ buffer = [];
63
+ done = false;
64
+ error = null;
63
65
  resolveResponse;
64
66
  rejectResponse;
65
- hasConsumer = false;
66
- constructor() {
67
- this.events = new EventStream();
67
+ resolveWait = null;
68
+ constructor(generator) {
68
69
  this.response = new Promise((resolve, reject) => {
69
70
  this.resolveResponse = resolve;
70
71
  this.rejectResponse = reject;
71
72
  });
73
+ this.pump(generator);
72
74
  }
73
- push(event) {
74
- this.events.push(event);
75
- }
76
- complete(response) {
77
- this.events.close();
78
- this.resolveResponse(response);
79
- }
80
- abort(error) {
81
- this.events.abort(error);
82
- this.rejectResponse(error);
75
+ async pump(generator) {
76
+ try {
77
+ let next = await generator.next();
78
+ while (!next.done) {
79
+ this.buffer.push(next.value);
80
+ this.resolveWait?.();
81
+ this.resolveWait = null;
82
+ next = await generator.next();
83
+ }
84
+ this.done = true;
85
+ this.resolveResponse(next.value);
86
+ this.resolveWait?.();
87
+ this.resolveWait = null;
88
+ } catch (err) {
89
+ const error = err instanceof Error ? err : new Error(String(err));
90
+ this.error = error;
91
+ this.done = true;
92
+ this.rejectResponse(error);
93
+ this.resolveWait?.();
94
+ this.resolveWait = null;
95
+ }
83
96
  }
84
- [Symbol.asyncIterator]() {
85
- this.hasConsumer = true;
86
- return this.events[Symbol.asyncIterator]();
97
+ async *[Symbol.asyncIterator]() {
98
+ let index = 0;
99
+ while (true) {
100
+ while (index < this.buffer.length) {
101
+ yield this.buffer[index++];
102
+ }
103
+ if (this.error) throw this.error;
104
+ if (this.done) return;
105
+ await new Promise((r) => {
106
+ this.resolveWait = r;
107
+ if (this.buffer.length > index || this.done || this.error) {
108
+ this.resolveWait = null;
109
+ r();
110
+ }
111
+ });
112
+ }
87
113
  }
88
114
  then(onfulfilled, onrejected) {
89
- this.drainEvents().catch(() => {
90
- });
91
115
  return this.response.then(onfulfilled, onrejected);
92
116
  }
93
- async drainEvents() {
94
- if (this.hasConsumer) return;
95
- this.hasConsumer = true;
96
- for await (const _ of this.events) {
97
- }
98
- }
99
117
  };
100
118
 
101
119
  // src/providers/anthropic.ts
@@ -405,11 +423,9 @@ function normalizeOpenAIStopReason(reason) {
405
423
 
406
424
  // src/providers/anthropic.ts
407
425
  function streamAnthropic(options) {
408
- const result = new StreamResult();
409
- runStream(options, result).catch((err) => result.abort(toError(err)));
410
- return result;
426
+ return new StreamResult(runStream(options));
411
427
  }
412
- async function runStream(options, result) {
428
+ async function* runStream(options) {
413
429
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
414
430
  const client = new Anthropic({
415
431
  ...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
@@ -479,116 +495,185 @@ async function runStream(options, result) {
479
495
  ...betaHeaders.length ? { headers: { "anthropic-beta": betaHeaders.join(",") } } : {}
480
496
  });
481
497
  const contentParts = [];
482
- let currentToolId = "";
483
- let currentToolName = "";
484
- stream2.on("text", (text) => {
485
- result.push({ type: "text_delta", text });
486
- });
487
- stream2.on("thinking", (thinkingDelta) => {
488
- result.push({ type: "thinking_delta", text: thinkingDelta });
489
- });
490
- stream2.on("streamEvent", (event) => {
491
- if (event.type === "content_block_start") {
492
- if (event.content_block.type === "tool_use") {
493
- currentToolId = event.content_block.id;
494
- currentToolName = event.content_block.name;
495
- }
496
- if (event.content_block.type === "server_tool_use") {
497
- currentToolId = event.content_block.id;
498
- currentToolName = event.content_block.name;
499
- }
500
- }
501
- });
502
- stream2.on("inputJson", (delta) => {
503
- result.push({
504
- type: "toolcall_delta",
505
- id: currentToolId,
506
- name: currentToolName,
507
- argsJson: delta
508
- });
509
- });
510
- stream2.on("contentBlock", (block) => {
511
- if (block.type === "text") {
512
- contentParts.push({ type: "text", text: block.text });
513
- } else if (block.type === "thinking") {
514
- contentParts.push({ type: "thinking", text: block.thinking, signature: block.signature });
515
- } else if (block.type === "tool_use") {
516
- const tc = {
517
- type: "tool_call",
518
- id: block.id,
519
- name: block.name,
520
- args: block.input
521
- };
522
- contentParts.push(tc);
523
- result.push({
524
- type: "toolcall_done",
525
- id: tc.id,
526
- name: tc.name,
527
- args: tc.args
528
- });
529
- } else if (block.type === "server_tool_use") {
530
- const stc = {
531
- type: "server_tool_call",
532
- id: block.id,
533
- name: block.name,
534
- input: block.input
535
- };
536
- contentParts.push(stc);
537
- result.push({
538
- type: "server_toolcall",
539
- id: stc.id,
540
- name: stc.name,
541
- input: stc.input
542
- });
543
- } else {
544
- const raw = block;
545
- const blockType = raw.type;
546
- if (blockType === "web_search_tool_result") {
547
- const str = {
548
- type: "server_tool_result",
549
- toolUseId: raw.tool_use_id,
550
- resultType: blockType,
551
- data: raw
552
- };
553
- contentParts.push(str);
554
- result.push({
555
- type: "server_toolresult",
556
- toolUseId: str.toolUseId,
557
- resultType: str.resultType,
558
- data: str.data
559
- });
560
- } else {
561
- contentParts.push({ type: "raw", data: raw });
562
- }
563
- }
564
- });
498
+ const blocks = /* @__PURE__ */ new Map();
499
+ let inputTokens = 0;
500
+ let outputTokens = 0;
501
+ let cacheRead;
502
+ let cacheWrite;
503
+ let stopReason = null;
565
504
  try {
566
- const finalMessage = await stream2.finalMessage();
567
- const stopReason = normalizeAnthropicStopReason(finalMessage.stop_reason);
568
- const response = {
569
- message: {
570
- role: "assistant",
571
- content: contentParts.length > 0 ? contentParts : ""
572
- },
573
- stopReason,
574
- usage: {
575
- inputTokens: finalMessage.usage.input_tokens,
576
- outputTokens: finalMessage.usage.output_tokens,
577
- ...finalMessage.usage.cache_read_input_tokens != null && {
578
- cacheRead: finalMessage.usage.cache_read_input_tokens
579
- },
580
- ...finalMessage.usage.cache_creation_input_tokens != null && {
581
- cacheWrite: finalMessage.usage.cache_creation_input_tokens
505
+ for await (const event of stream2) {
506
+ switch (event.type) {
507
+ case "message_start": {
508
+ const usage = event.message.usage;
509
+ inputTokens = usage.input_tokens;
510
+ const usageAny = usage;
511
+ if (usageAny.cache_read_input_tokens != null) {
512
+ cacheRead = usageAny.cache_read_input_tokens;
513
+ }
514
+ if (usageAny.cache_creation_input_tokens != null) {
515
+ cacheWrite = usageAny.cache_creation_input_tokens;
516
+ }
517
+ break;
518
+ }
519
+ case "content_block_start": {
520
+ const block = event.content_block;
521
+ const idx = event.index;
522
+ const accum = {
523
+ type: block.type,
524
+ text: "",
525
+ thinking: "",
526
+ signature: "",
527
+ toolId: "",
528
+ toolName: "",
529
+ argsJson: "",
530
+ input: void 0,
531
+ raw: null
532
+ };
533
+ if (block.type === "tool_use") {
534
+ accum.toolId = block.id;
535
+ accum.toolName = block.name;
536
+ } else if (block.type === "server_tool_use") {
537
+ accum.toolId = block.id;
538
+ accum.toolName = block.name;
539
+ } else if (block.type === "redacted_thinking") {
540
+ accum.raw = block;
541
+ }
542
+ blocks.set(idx, accum);
543
+ break;
544
+ }
545
+ case "content_block_delta": {
546
+ const accum = blocks.get(event.index);
547
+ if (!accum) break;
548
+ const delta = event.delta;
549
+ const deltaType = delta.type;
550
+ if (deltaType === "text_delta") {
551
+ const text = delta.text;
552
+ accum.text += text;
553
+ yield { type: "text_delta", text };
554
+ } else if (deltaType === "thinking_delta") {
555
+ const text = delta.thinking;
556
+ accum.thinking += text;
557
+ yield { type: "thinking_delta", text };
558
+ } else if (deltaType === "input_json_delta") {
559
+ const partialJson = delta.partial_json;
560
+ accum.argsJson += partialJson;
561
+ yield {
562
+ type: "toolcall_delta",
563
+ id: accum.toolId,
564
+ name: accum.toolName,
565
+ argsJson: partialJson
566
+ };
567
+ } else if (deltaType === "signature_delta") {
568
+ accum.signature = delta.signature;
569
+ }
570
+ break;
571
+ }
572
+ case "content_block_stop": {
573
+ const accum = blocks.get(event.index);
574
+ if (!accum) break;
575
+ if (accum.type === "text") {
576
+ contentParts.push({ type: "text", text: accum.text });
577
+ } else if (accum.type === "thinking") {
578
+ contentParts.push({
579
+ type: "thinking",
580
+ text: accum.thinking,
581
+ signature: accum.signature
582
+ });
583
+ } else if (accum.type === "tool_use") {
584
+ let args = {};
585
+ try {
586
+ args = JSON.parse(accum.argsJson);
587
+ } catch {
588
+ }
589
+ const tc = {
590
+ type: "tool_call",
591
+ id: accum.toolId,
592
+ name: accum.toolName,
593
+ args
594
+ };
595
+ contentParts.push(tc);
596
+ yield {
597
+ type: "toolcall_done",
598
+ id: tc.id,
599
+ name: tc.name,
600
+ args: tc.args
601
+ };
602
+ } else if (accum.type === "server_tool_use") {
603
+ const stc = {
604
+ type: "server_tool_call",
605
+ id: accum.toolId,
606
+ name: accum.toolName,
607
+ input: accum.input
608
+ };
609
+ contentParts.push(stc);
610
+ yield {
611
+ type: "server_toolcall",
612
+ id: stc.id,
613
+ name: stc.name,
614
+ input: stc.input
615
+ };
616
+ } else if (accum.type === "redacted_thinking" && accum.raw) {
617
+ contentParts.push({ type: "raw", data: accum.raw });
618
+ } else {
619
+ const msg = stream2.currentMessage;
620
+ const rawBlock = msg?.content[event.index];
621
+ if (rawBlock) {
622
+ const blockType = rawBlock.type;
623
+ if (blockType === "web_search_tool_result") {
624
+ const str = {
625
+ type: "server_tool_result",
626
+ toolUseId: rawBlock.tool_use_id,
627
+ resultType: blockType,
628
+ data: rawBlock
629
+ };
630
+ contentParts.push(str);
631
+ yield {
632
+ type: "server_toolresult",
633
+ toolUseId: str.toolUseId,
634
+ resultType: str.resultType,
635
+ data: str.data
636
+ };
637
+ } else {
638
+ contentParts.push({ type: "raw", data: rawBlock });
639
+ }
640
+ }
641
+ }
642
+ blocks.delete(event.index);
643
+ break;
644
+ }
645
+ case "message_delta": {
646
+ const delta = event.delta;
647
+ if (delta.stop_reason) {
648
+ stopReason = delta.stop_reason;
649
+ }
650
+ const usage = event.usage;
651
+ if (usage?.output_tokens != null) {
652
+ outputTokens = usage.output_tokens;
653
+ }
654
+ break;
582
655
  }
583
656
  }
584
- };
585
- result.push({ type: "done", stopReason });
586
- result.complete(response);
657
+ }
587
658
  } catch (err) {
588
- const error = toError(err);
589
- result.push({ type: "error", error });
590
- result.abort(error);
659
+ throw toError(err);
591
660
  }
661
+ const normalizedStop = normalizeAnthropicStopReason(stopReason);
662
+ const response = {
663
+ message: {
664
+ role: "assistant",
665
+ content: contentParts.length > 0 ? contentParts : ""
666
+ },
667
+ stopReason: normalizedStop,
668
+ usage: {
669
+ inputTokens,
670
+ outputTokens,
671
+ ...cacheRead != null && { cacheRead },
672
+ ...cacheWrite != null && { cacheWrite }
673
+ }
674
+ };
675
+ yield { type: "done", stopReason: normalizedStop };
676
+ return response;
592
677
  }
593
678
  function toError(err) {
594
679
  if (err instanceof Anthropic.APIError) {
@@ -606,12 +691,10 @@ function toError(err) {
606
691
  // src/providers/openai.ts
607
692
  import OpenAI from "openai";
608
693
  function streamOpenAI(options) {
609
- const result = new StreamResult();
610
- const providerName = options.provider ?? "openai";
611
- runStream2(options, result).catch((err) => result.abort(toError2(err, providerName)));
612
- return result;
694
+ return new StreamResult(runStream2(options));
613
695
  }
614
- async function runStream2(options, result) {
696
+ async function* runStream2(options) {
697
+ const providerName = options.provider ?? "openai";
615
698
  const client = new OpenAI({
616
699
  apiKey: options.apiKey,
617
700
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
@@ -645,9 +728,14 @@ async function runStream2(options, result) {
645
728
  if (usesThinkingParam) {
646
729
  params.thinking = options.thinking ? { type: "enabled" } : { type: "disabled" };
647
730
  }
648
- const stream2 = await client.chat.completions.create(params, {
649
- signal: options.signal ?? void 0
650
- });
731
+ let stream2;
732
+ try {
733
+ stream2 = await client.chat.completions.create(params, {
734
+ signal: options.signal ?? void 0
735
+ });
736
+ } catch (err) {
737
+ throw toError2(err, providerName);
738
+ }
651
739
  const contentParts = [];
652
740
  const toolCallAccum = /* @__PURE__ */ new Map();
653
741
  let textAccum = "";
@@ -674,11 +762,11 @@ async function runStream2(options, result) {
674
762
  const reasoningContent = delta.reasoning_content;
675
763
  if (typeof reasoningContent === "string" && reasoningContent) {
676
764
  thinkingAccum += reasoningContent;
677
- result.push({ type: "thinking_delta", text: reasoningContent });
765
+ yield { type: "thinking_delta", text: reasoningContent };
678
766
  }
679
767
  if (delta.content) {
680
768
  textAccum += delta.content;
681
- result.push({ type: "text_delta", text: delta.content });
769
+ yield { type: "text_delta", text: delta.content };
682
770
  }
683
771
  if (delta.tool_calls) {
684
772
  for (const tc of delta.tool_calls) {
@@ -695,12 +783,12 @@ async function runStream2(options, result) {
695
783
  if (tc.function?.name) accum.name = tc.function.name;
696
784
  if (tc.function?.arguments) {
697
785
  accum.argsJson += tc.function.arguments;
698
- result.push({
786
+ yield {
699
787
  type: "toolcall_delta",
700
788
  id: accum.id,
701
789
  name: accum.name,
702
790
  argsJson: tc.function.arguments
703
- });
791
+ };
704
792
  }
705
793
  }
706
794
  }
@@ -724,12 +812,12 @@ async function runStream2(options, result) {
724
812
  args
725
813
  };
726
814
  contentParts.push(toolCall);
727
- result.push({
815
+ yield {
728
816
  type: "toolcall_done",
729
817
  id: tc.id,
730
818
  name: tc.name,
731
819
  args
732
- });
820
+ };
733
821
  }
734
822
  const stopReason = normalizeOpenAIStopReason(finishReason);
735
823
  const response = {
@@ -740,8 +828,8 @@ async function runStream2(options, result) {
740
828
  stopReason,
741
829
  usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
742
830
  };
743
- result.push({ type: "done", stopReason });
744
- result.complete(response);
831
+ yield { type: "done", stopReason };
832
+ return response;
745
833
  }
746
834
  function toError2(err, provider = "openai") {
747
835
  if (err instanceof OpenAI.APIError) {
@@ -765,11 +853,9 @@ function toError2(err, provider = "openai") {
765
853
  import os from "os";
766
854
  var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
767
855
  function streamOpenAICodex(options) {
768
- const result = new StreamResult();
769
- runStream3(options, result).catch((err) => result.abort(toError3(err)));
770
- return result;
856
+ return new StreamResult(runStream3(options));
771
857
  }
772
- async function runStream3(options, result) {
858
+ async function* runStream3(options) {
773
859
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
774
860
  const url = `${baseUrl}/codex/responses`;
775
861
  const { system, input } = toCodexInput(options.messages);
@@ -846,11 +932,11 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
846
932
  if (type === "response.output_text.delta") {
847
933
  const delta = event.delta;
848
934
  textAccum += delta;
849
- result.push({ type: "text_delta", text: delta });
935
+ yield { type: "text_delta", text: delta };
850
936
  }
851
937
  if (type === "response.reasoning_summary_text.delta") {
852
938
  const delta = event.delta;
853
- result.push({ type: "thinking_delta", text: delta });
939
+ yield { type: "thinking_delta", text: delta };
854
940
  }
855
941
  if (type === "response.output_item.added") {
856
942
  const item = event.item;
@@ -868,12 +954,12 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
868
954
  for (const [key, tc] of toolCalls) {
869
955
  if (key.endsWith(`|${itemId}`)) {
870
956
  tc.argsJson += delta;
871
- result.push({
957
+ yield {
872
958
  type: "toolcall_delta",
873
959
  id: tc.id,
874
960
  name: tc.name,
875
961
  argsJson: delta
876
- });
962
+ };
877
963
  break;
878
964
  }
879
965
  }
@@ -901,12 +987,12 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
901
987
  args = JSON.parse(tc.argsJson);
902
988
  } catch {
903
989
  }
904
- result.push({
990
+ yield {
905
991
  type: "toolcall_done",
906
992
  id: tc.id,
907
993
  name: tc.name,
908
994
  args
909
- });
995
+ };
910
996
  }
911
997
  }
912
998
  }
@@ -946,8 +1032,8 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
946
1032
  stopReason,
947
1033
  usage: { inputTokens, outputTokens }
948
1034
  };
949
- result.push({ type: "done", stopReason });
950
- result.complete(streamResponse);
1035
+ yield { type: "done", stopReason };
1036
+ return streamResponse;
951
1037
  }
952
1038
  async function* parseSSE(body) {
953
1039
  const reader = body.getReader();
@@ -1061,13 +1147,6 @@ function toCodexTools(tools) {
1061
1147
  strict: null
1062
1148
  }));
1063
1149
  }
1064
- function toError3(err) {
1065
- if (err instanceof ProviderError) return err;
1066
- if (err instanceof Error) {
1067
- return new ProviderError("openai", err.message, { cause: err });
1068
- }
1069
- return new ProviderError("openai", String(err));
1070
- }
1071
1150
 
1072
1151
  // src/provider-registry.ts
1073
1152
  var ProviderRegistryImpl = class {
@@ -1141,32 +1220,28 @@ function stream(options) {
1141
1220
  return entry.stream(options);
1142
1221
  }
1143
1222
  function streamGLMWithFallback(options) {
1144
- const result = new StreamResult();
1145
- runGLMWithFallback(options, result).catch((err) => {
1146
- result.abort(err instanceof Error ? err : new Error(String(err)));
1147
- });
1148
- return result;
1223
+ return new StreamResult(runGLMWithFallback(options));
1149
1224
  }
1150
- async function runGLMWithFallback(options, result) {
1151
- const codingResult = streamOpenAI({ ...options, baseUrl: GLM_CODING_BASE_URL });
1152
- codingResult.response.catch(() => {
1225
+ async function* runGLMWithFallback(options) {
1226
+ const coding = streamOpenAI({ ...options, baseUrl: GLM_CODING_BASE_URL });
1227
+ coding.response.catch(() => {
1153
1228
  });
1154
1229
  try {
1155
- for await (const event of codingResult) {
1156
- result.push(event);
1230
+ for await (const event of coding) {
1231
+ yield event;
1157
1232
  }
1158
- result.complete(await codingResult.response);
1233
+ return await coding.response;
1159
1234
  } catch {
1160
- const regularResult = streamOpenAI({ ...options, baseUrl: GLM_REGULAR_BASE_URL });
1161
- regularResult.response.catch(() => {
1235
+ const regular = streamOpenAI({ ...options, baseUrl: GLM_REGULAR_BASE_URL });
1236
+ regular.response.catch(() => {
1162
1237
  });
1163
1238
  try {
1164
- for await (const event of regularResult) {
1165
- result.push(event);
1239
+ for await (const event of regular) {
1240
+ yield event;
1166
1241
  }
1167
- result.complete(await regularResult.response);
1242
+ return await regular.response;
1168
1243
  } catch (fallbackErr) {
1169
- result.abort(fallbackErr instanceof Error ? fallbackErr : new Error(String(fallbackErr)));
1244
+ throw fallbackErr instanceof Error ? fallbackErr : new Error(String(fallbackErr));
1170
1245
  }
1171
1246
  }
1172
1247
  }
@@ -1197,31 +1272,29 @@ function chunkText(text, size) {
1197
1272
  }
1198
1273
  return chunks.length > 0 ? chunks : [""];
1199
1274
  }
1200
- function simulateStream(message, stopReason, result, signal, cacheUsage) {
1275
+ async function* simulateStream(message, stopReason, signal, cacheUsage) {
1201
1276
  if (signal?.aborted) {
1202
- result.abort(new Error("aborted"));
1203
- return;
1277
+ throw new Error("aborted");
1204
1278
  }
1205
1279
  const content = typeof message.content === "string" ? message.content ? [{ type: "text", text: message.content }] : [] : message.content;
1206
1280
  let outputChars = 0;
1207
1281
  for (const part of content) {
1208
1282
  if (signal?.aborted) {
1209
- result.abort(new Error("aborted"));
1210
- return;
1283
+ throw new Error("aborted");
1211
1284
  }
1212
1285
  if (part.type === "text") {
1213
1286
  const chunks = chunkText(part.text, DEFAULT_CHUNK_SIZE);
1214
1287
  for (const chunk of chunks) {
1215
- result.push({ type: "text_delta", text: chunk });
1288
+ yield { type: "text_delta", text: chunk };
1216
1289
  outputChars += chunk.length;
1217
1290
  }
1218
1291
  } else if (part.type === "thinking") {
1219
- result.push({ type: "thinking_delta", text: part.text });
1292
+ yield { type: "thinking_delta", text: part.text };
1220
1293
  outputChars += part.text.length;
1221
1294
  } else if (part.type === "tool_call") {
1222
1295
  const argsJson = JSON.stringify(part.args);
1223
- result.push({ type: "toolcall_delta", id: part.id, name: part.name, argsJson });
1224
- result.push({ type: "toolcall_done", id: part.id, name: part.name, args: part.args });
1296
+ yield { type: "toolcall_delta", id: part.id, name: part.name, argsJson };
1297
+ yield { type: "toolcall_done", id: part.id, name: part.name, args: part.args };
1225
1298
  outputChars += argsJson.length;
1226
1299
  }
1227
1300
  }
@@ -1232,8 +1305,8 @@ function simulateStream(message, stopReason, result, signal, cacheUsage) {
1232
1305
  ...cacheUsage?.cacheRead ? { cacheRead: cacheUsage.cacheRead } : {},
1233
1306
  ...cacheUsage?.cacheWrite ? { cacheWrite: cacheUsage.cacheWrite } : {}
1234
1307
  };
1235
- result.push({ type: "done", stopReason });
1236
- result.complete({ message, stopReason, usage });
1308
+ yield { type: "done", stopReason };
1309
+ return { message, stopReason, usage };
1237
1310
  }
1238
1311
  function computeCacheUsage(current, previous) {
1239
1312
  if (!previous) {
@@ -1305,24 +1378,21 @@ function registerPalsuProvider(config) {
1305
1378
  state.callCount++;
1306
1379
  const ms = modelStates.get(options.model);
1307
1380
  const responseDef = (ms && ms.responses.length > 0 ? ms.responses.shift() : void 0) ?? (responses.length > 0 ? responses.shift() : void 0) ?? ms?.defaultResponse ?? defaultResponse;
1308
- const result = new StreamResult();
1309
1381
  let cacheUsage;
1310
1382
  if (enableCache) {
1311
1383
  const serialized = JSON.stringify(options.messages);
1312
1384
  cacheUsage = computeCacheUsage(serialized, lastMessagesSerialized);
1313
1385
  lastMessagesSerialized = serialized;
1314
1386
  }
1315
- const rawMessage = typeof responseDef === "function" ? responseDef(options.messages, options, state) : responseDef;
1316
- Promise.resolve(rawMessage).then(
1317
- (message) => {
1318
- const hasToolCalls = Array.isArray(message.content) && message.content.some((p) => p.type === "tool_call");
1319
- const explicitStop = message._stopReason;
1320
- const stopReason = explicitStop ?? (hasToolCalls ? "tool_use" : "end_turn");
1321
- simulateStream(message, stopReason, result, options.signal, cacheUsage);
1322
- },
1323
- (err) => result.abort(err instanceof Error ? err : new Error(String(err)))
1324
- );
1325
- return result;
1387
+ const gen = (async function* () {
1388
+ const rawMessage = typeof responseDef === "function" ? responseDef(options.messages, options, state) : responseDef;
1389
+ const message = await Promise.resolve(rawMessage);
1390
+ const hasToolCalls = Array.isArray(message.content) && message.content.some((p) => p.type === "tool_call");
1391
+ const explicitStop = message._stopReason;
1392
+ const stopReason = explicitStop ?? (hasToolCalls ? "tool_use" : "end_turn");
1393
+ return yield* simulateStream(message, stopReason, options.signal, cacheUsage);
1394
+ })();
1395
+ return new StreamResult(gen);
1326
1396
  }
1327
1397
  });
1328
1398
  return handle;