@kenkaiiii/gg-ai 4.3.32 → 4.3.33

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.d.ts CHANGED
@@ -174,6 +174,12 @@ interface StreamOptions {
174
174
  * where the default `globalThis.fetch` doesn't support streaming properly.
175
175
  * Passed directly to the underlying provider SDK. */
176
176
  fetch?: typeof globalThis.fetch;
177
+ /** Use streaming transport (default: true). When false, providers issue a
178
+ * single non-streaming request and synthesize events from the full response.
179
+ * The agent loop flips this to `false` as a fallback after repeated stream
180
+ * stalls — broken SSE connections (transient CDN / proxy issues) often
181
+ * recover when the same request is issued over a plain HTTP request/response. */
182
+ streaming?: boolean;
177
183
  }
178
184
 
179
185
  /**
package/dist/index.js CHANGED
@@ -452,6 +452,7 @@ function streamAnthropic(options) {
452
452
  async function* runStream(options) {
453
453
  const client = createClient(options);
454
454
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
455
+ const useStreaming = options.streaming !== false;
455
456
  const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
456
457
  const { system: rawSystem, messages } = toAnthropicMessages(options.messages, cacheControl);
457
458
  const system = isOAuth ? [
@@ -497,7 +498,7 @@ async function* runStream(options) {
497
498
  ];
498
499
  return contextEdits.length ? { context_management: { edits: contextEdits } } : {};
499
500
  })(),
500
- stream: true
501
+ stream: useStreaming
501
502
  };
502
503
  const hasAdaptiveThinking = options.model.includes("opus-4-7") || options.model.includes("opus-4.7") || options.model.includes("opus-4-6") || options.model.includes("opus-4.6") || options.model.includes("sonnet-4-6") || options.model.includes("sonnet-4.6");
503
504
  const betaHeaders = [
@@ -507,10 +508,23 @@ async function* runStream(options) {
507
508
  "fine-grained-tool-streaming-2025-05-14",
508
509
  ...!hasAdaptiveThinking ? ["interleaved-thinking-2025-05-14"] : []
509
510
  ];
510
- const stream2 = client.messages.stream(params, {
511
+ const requestOptions = {
511
512
  signal: options.signal ?? void 0,
512
513
  ...betaHeaders.length ? { headers: { "anthropic-beta": betaHeaders.join(",") } } : {}
513
- });
514
+ };
515
+ if (!useStreaming) {
516
+ try {
517
+ const message = await client.messages.create(
518
+ { ...params, stream: false },
519
+ requestOptions
520
+ );
521
+ yield* synthesizeEventsFromMessage(message);
522
+ return messageToResponse(message);
523
+ } catch (err) {
524
+ throw toError(err);
525
+ }
526
+ }
527
+ const stream2 = client.messages.stream(params, requestOptions);
514
528
  const contentParts = [];
515
529
  const blocks = /* @__PURE__ */ new Map();
516
530
  let inputTokens = 0;
@@ -703,6 +717,105 @@ async function* runStream(options) {
703
717
  yield { type: "done", stopReason: normalizedStop };
704
718
  return response;
705
719
  }
720
+ function* synthesizeEventsFromMessage(message) {
721
+ for (const block of message.content) {
722
+ const blk = block;
723
+ const type = blk.type;
724
+ if (type === "text") {
725
+ const text = blk.text;
726
+ if (text) yield { type: "text_delta", text };
727
+ } else if (type === "thinking") {
728
+ const text = blk.thinking;
729
+ if (text) yield { type: "thinking_delta", text };
730
+ } else if (type === "tool_use") {
731
+ const argsJson = JSON.stringify(blk.input ?? {});
732
+ yield {
733
+ type: "toolcall_delta",
734
+ id: blk.id,
735
+ name: blk.name,
736
+ argsJson
737
+ };
738
+ yield {
739
+ type: "toolcall_done",
740
+ id: blk.id,
741
+ name: blk.name,
742
+ args: blk.input ?? {}
743
+ };
744
+ } else if (type === "server_tool_use") {
745
+ yield {
746
+ type: "server_toolcall",
747
+ id: blk.id,
748
+ name: blk.name,
749
+ input: blk.input
750
+ };
751
+ } else if (type === "web_search_tool_result") {
752
+ yield {
753
+ type: "server_toolresult",
754
+ toolUseId: blk.tool_use_id,
755
+ resultType: type,
756
+ data: blk
757
+ };
758
+ }
759
+ }
760
+ yield { type: "done", stopReason: normalizeAnthropicStopReason(message.stop_reason) };
761
+ }
762
+ function messageToResponse(message) {
763
+ const contentParts = [];
764
+ for (const block of message.content) {
765
+ const blk = block;
766
+ const type = blk.type;
767
+ if (type === "text") {
768
+ contentParts.push({ type: "text", text: blk.text });
769
+ } else if (type === "thinking") {
770
+ contentParts.push({
771
+ type: "thinking",
772
+ text: blk.thinking,
773
+ signature: blk.signature ?? ""
774
+ });
775
+ } else if (type === "tool_use") {
776
+ contentParts.push({
777
+ type: "tool_call",
778
+ id: blk.id,
779
+ name: blk.name,
780
+ args: blk.input ?? {}
781
+ });
782
+ } else if (type === "server_tool_use") {
783
+ contentParts.push({
784
+ type: "server_tool_call",
785
+ id: blk.id,
786
+ name: blk.name,
787
+ input: blk.input
788
+ });
789
+ } else if (type === "web_search_tool_result") {
790
+ contentParts.push({
791
+ type: "server_tool_result",
792
+ toolUseId: blk.tool_use_id,
793
+ resultType: type,
794
+ data: blk
795
+ });
796
+ } else {
797
+ contentParts.push({ type: "raw", data: blk });
798
+ }
799
+ }
800
+ const usage = message.usage;
801
+ const inputTokens = usage.input_tokens ?? 0;
802
+ const outputTokens = usage.output_tokens ?? 0;
803
+ const cacheRead = usage.cache_read_input_tokens;
804
+ const cacheWrite = usage.cache_creation_input_tokens;
805
+ return {
806
+ message: {
807
+ role: "assistant",
808
+ content: contentParts.length > 0 ? contentParts : ""
809
+ },
810
+ stopReason: normalizeAnthropicStopReason(message.stop_reason),
811
+ usage: {
812
+ inputTokens,
813
+ outputTokens,
814
+ ...cacheRead != null && { cacheRead },
815
+ ...cacheWrite != null && { cacheWrite }
816
+ }
817
+ };
818
+ }
706
819
  function toError(err) {
707
820
  if (err instanceof Anthropic.APIError) {
708
821
  return new ProviderError("anthropic", err.message, {
@@ -730,6 +843,7 @@ function streamOpenAI(options) {
730
843
  }
731
844
  async function* runStream2(options) {
732
845
  const providerName = options.provider ?? "openai";
846
+ const useStreaming = options.streaming !== false;
733
847
  const client = createClient2(options);
734
848
  const usesThinkingParam = options.provider === "glm" || options.provider === "moonshot" || options.provider === "xiaomi";
735
849
  const messages = toOpenAIMessages(options.messages, {
@@ -741,7 +855,7 @@ async function* runStream2(options) {
741
855
  const params = {
742
856
  model: options.model,
743
857
  messages,
744
- stream: true,
858
+ stream: useStreaming,
745
859
  ...options.maxTokens ? { max_completion_tokens: options.maxTokens } : {},
746
860
  ...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
747
861
  ...options.topP != null ? { top_p: options.topP } : {},
@@ -749,7 +863,7 @@ async function* runStream2(options) {
749
863
  ...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking) } : {},
750
864
  ...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
751
865
  ...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
752
- stream_options: { include_usage: true }
866
+ ...useStreaming ? { stream_options: { include_usage: true } } : {}
753
867
  };
754
868
  if (options.provider === "openai" || options.provider === "moonshot") {
755
869
  const paramsAny = params;
@@ -777,6 +891,17 @@ async function* runStream2(options) {
777
891
  `
778
892
  );
779
893
  }
894
+ if (!useStreaming) {
895
+ try {
896
+ const completion = await client.chat.completions.create(params, {
897
+ signal: options.signal ?? void 0
898
+ });
899
+ yield* synthesizeEventsFromCompletion(completion, !!options.thinking);
900
+ return completionToResponse(completion);
901
+ } catch (err) {
902
+ throw toError2(err, providerName);
903
+ }
904
+ }
780
905
  let stream2;
781
906
  try {
782
907
  stream2 = await client.chat.completions.create(params, {
@@ -886,6 +1011,102 @@ async function* runStream2(options) {
886
1011
  yield { type: "done", stopReason };
887
1012
  return response;
888
1013
  }
1014
+ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
1015
+ const choice = completion.choices?.[0];
1016
+ if (!choice) {
1017
+ yield { type: "done", stopReason: normalizeOpenAIStopReason(null) };
1018
+ return;
1019
+ }
1020
+ const msg = choice.message;
1021
+ const reasoning = msg.reasoning_content;
1022
+ if (typeof reasoning === "string" && reasoning && thinkingEnabled) {
1023
+ yield { type: "thinking_delta", text: reasoning };
1024
+ }
1025
+ if (typeof msg.content === "string" && msg.content) {
1026
+ yield { type: "text_delta", text: msg.content };
1027
+ }
1028
+ const toolCalls = msg.tool_calls;
1029
+ if (toolCalls) {
1030
+ for (const tc of toolCalls) {
1031
+ const argsJson = tc.function?.arguments ?? "";
1032
+ if (argsJson) {
1033
+ yield {
1034
+ type: "toolcall_delta",
1035
+ id: tc.id,
1036
+ name: tc.function?.name ?? "",
1037
+ argsJson
1038
+ };
1039
+ }
1040
+ let args = {};
1041
+ try {
1042
+ args = JSON.parse(argsJson);
1043
+ } catch {
1044
+ }
1045
+ yield {
1046
+ type: "toolcall_done",
1047
+ id: tc.id,
1048
+ name: tc.function?.name ?? "",
1049
+ args
1050
+ };
1051
+ }
1052
+ }
1053
+ yield { type: "done", stopReason: normalizeOpenAIStopReason(choice.finish_reason ?? null) };
1054
+ }
1055
+ function completionToResponse(completion) {
1056
+ const choice = completion.choices?.[0];
1057
+ const contentParts = [];
1058
+ let textAccum = "";
1059
+ if (choice) {
1060
+ const msg = choice.message;
1061
+ const reasoning = msg.reasoning_content;
1062
+ if (typeof reasoning === "string" && reasoning) {
1063
+ contentParts.push({ type: "thinking", text: reasoning });
1064
+ }
1065
+ if (typeof msg.content === "string" && msg.content) {
1066
+ textAccum = msg.content;
1067
+ contentParts.push({ type: "text", text: msg.content });
1068
+ }
1069
+ const toolCalls = msg.tool_calls;
1070
+ if (toolCalls) {
1071
+ for (const tc of toolCalls) {
1072
+ let args = {};
1073
+ try {
1074
+ args = JSON.parse(tc.function?.arguments ?? "{}");
1075
+ } catch {
1076
+ }
1077
+ const toolCall = {
1078
+ type: "tool_call",
1079
+ id: tc.id,
1080
+ name: tc.function?.name ?? "",
1081
+ args
1082
+ };
1083
+ contentParts.push(toolCall);
1084
+ }
1085
+ }
1086
+ }
1087
+ let inputTokens = 0;
1088
+ let outputTokens = 0;
1089
+ let cacheRead = 0;
1090
+ if (completion.usage) {
1091
+ outputTokens = completion.usage.completion_tokens;
1092
+ const details = completion.usage.prompt_tokens_details;
1093
+ if (details?.cached_tokens) cacheRead = details.cached_tokens;
1094
+ const usageAny = completion.usage;
1095
+ if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
1096
+ cacheRead = usageAny.cached_tokens;
1097
+ }
1098
+ inputTokens = completion.usage.prompt_tokens - cacheRead;
1099
+ }
1100
+ const stopReason = normalizeOpenAIStopReason(choice?.finish_reason ?? null);
1101
+ return {
1102
+ message: {
1103
+ role: "assistant",
1104
+ content: contentParts.length > 0 ? contentParts : textAccum
1105
+ },
1106
+ stopReason,
1107
+ usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
1108
+ };
1109
+ }
889
1110
  function toError2(err, provider = "openai") {
890
1111
  if (err instanceof OpenAI.APIError) {
891
1112
  let msg = err.message;