@kenkaiiii/gg-ai 4.6.0 → 4.6.2

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.cts CHANGED
@@ -255,8 +255,9 @@ declare class StreamResult implements AsyncIterable<StreamEvent> {
255
255
  private resolveResponse;
256
256
  private rejectResponse;
257
257
  private resolveWait;
258
- constructor(generator: AsyncGenerator<StreamEvent, StreamResponse>);
258
+ constructor(generator: AsyncGenerator<StreamEvent, StreamResponse>, signal?: AbortSignal);
259
259
  private pump;
260
+ private _nextWithAbort;
260
261
  [Symbol.asyncIterator](): AsyncIterator<StreamEvent>;
261
262
  then<TResult1 = StreamResponse, TResult2 = never>(onfulfilled?: ((value: StreamResponse) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
262
263
  }
package/dist/index.d.ts CHANGED
@@ -255,8 +255,9 @@ declare class StreamResult implements AsyncIterable<StreamEvent> {
255
255
  private resolveResponse;
256
256
  private rejectResponse;
257
257
  private resolveWait;
258
- constructor(generator: AsyncGenerator<StreamEvent, StreamResponse>);
258
+ constructor(generator: AsyncGenerator<StreamEvent, StreamResponse>, signal?: AbortSignal);
259
259
  private pump;
260
+ private _nextWithAbort;
260
261
  [Symbol.asyncIterator](): AsyncIterator<StreamEvent>;
261
262
  then<TResult1 = StreamResponse, TResult2 = never>(onfulfilled?: ((value: StreamResponse) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
262
263
  }
package/dist/index.js CHANGED
@@ -274,21 +274,21 @@ var StreamResult = class {
274
274
  resolveResponse;
275
275
  rejectResponse;
276
276
  resolveWait = null;
277
- constructor(generator) {
277
+ constructor(generator, signal) {
278
278
  this.response = new Promise((resolve, reject) => {
279
279
  this.resolveResponse = resolve;
280
280
  this.rejectResponse = reject;
281
281
  });
282
- this.pump(generator);
282
+ this.pump(generator, signal);
283
283
  }
284
- async pump(generator) {
284
+ async pump(generator, signal) {
285
285
  try {
286
- let next = await generator.next();
286
+ let next = await this._nextWithAbort(generator, signal);
287
287
  while (!next.done) {
288
288
  this.buffer.push(next.value);
289
289
  this.resolveWait?.();
290
290
  this.resolveWait = null;
291
- next = await generator.next();
291
+ next = await this._nextWithAbort(generator, signal);
292
292
  }
293
293
  this.done = true;
294
294
  this.resolveResponse(next.value);
@@ -303,6 +303,28 @@ var StreamResult = class {
303
303
  this.resolveWait = null;
304
304
  }
305
305
  }
306
+ async _nextWithAbort(generator, signal) {
307
+ if (!signal) {
308
+ return generator.next();
309
+ }
310
+ if (signal.aborted) {
311
+ return Promise.reject(new DOMException("Aborted", "AbortError"));
312
+ }
313
+ let onAbort;
314
+ const abortPromise = new Promise((_, reject) => {
315
+ onAbort = () => {
316
+ generator.return?.(void 0).catch(() => {
317
+ });
318
+ reject(new DOMException("Aborted", "AbortError"));
319
+ };
320
+ signal.addEventListener("abort", onAbort, { once: true });
321
+ });
322
+ try {
323
+ return await Promise.race([generator.next(), abortPromise]);
324
+ } finally {
325
+ if (onAbort) signal.removeEventListener("abort", onAbort);
326
+ }
327
+ }
306
328
  async *[Symbol.asyncIterator]() {
307
329
  let index = 0;
308
330
  while (true) {
@@ -919,10 +941,10 @@ function createClient(options) {
919
941
  ...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
920
942
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
921
943
  ...options.fetch ? { fetch: options.fetch } : {},
922
- // Allow SDK retries for connection-level failures (socket hang up, 500s,
923
- // connection refused). Our stall detection handles abort-initiated retries
924
- // separately SDK retries only fire on genuine transport errors.
925
- maxRetries: 2,
944
+ // Disable SDK retries the agent loop has its own stall/overload retry
945
+ // logic that surfaces errors properly. SDK retries on 429s can cause
946
+ // multi-minute hangs when the provider stops responding mid-retry.
947
+ maxRetries: 0,
926
948
  ...isOAuth ? {
927
949
  defaultHeaders: {
928
950
  // Anthropic's OAuth edge validates the claude-cli version. Callers
@@ -935,7 +957,7 @@ function createClient(options) {
935
957
  });
936
958
  }
937
959
  function streamAnthropic(options) {
938
- return new StreamResult(runStream(options));
960
+ return new StreamResult(runStream(options), options.signal);
939
961
  }
940
962
  async function* runStream(options) {
941
963
  const client = createClient(options);
@@ -1030,7 +1052,6 @@ async function* runStream(options) {
1030
1052
  throw toError(err);
1031
1053
  }
1032
1054
  }
1033
- const stream2 = client.messages.stream(params, requestOptions);
1034
1055
  const contentParts = [];
1035
1056
  const blocks = /* @__PURE__ */ new Map();
1036
1057
  let inputTokens = 0;
@@ -1039,8 +1060,14 @@ async function* runStream(options) {
1039
1060
  let cacheWrite;
1040
1061
  let stopReason = null;
1041
1062
  const keepalive = { type: "keepalive" };
1063
+ let receivedAnyEvent = false;
1042
1064
  try {
1065
+ const stream2 = await client.messages.create(
1066
+ params,
1067
+ requestOptions
1068
+ );
1043
1069
  for await (const event of stream2) {
1070
+ receivedAnyEvent = true;
1044
1071
  switch (event.type) {
1045
1072
  case "message_start": {
1046
1073
  const usage = event.message.usage;
@@ -1077,7 +1104,7 @@ async function* runStream(options) {
1077
1104
  accum.toolId = block.id;
1078
1105
  accum.toolName = block.name;
1079
1106
  accum.input = block.input;
1080
- } else if (block.type === "redacted_thinking") {
1107
+ } else if (block.type !== "text" && block.type !== "thinking") {
1081
1108
  accum.raw = block;
1082
1109
  }
1083
1110
  blocks.set(idx, accum);
@@ -1174,8 +1201,7 @@ async function* runStream(options) {
1174
1201
  contentParts.push({ type: "raw", data: accum.raw });
1175
1202
  yield keepalive;
1176
1203
  } else {
1177
- const msg = stream2.currentMessage;
1178
- const rawBlock = msg?.content[event.index];
1204
+ const rawBlock = accum.raw;
1179
1205
  if (rawBlock) {
1180
1206
  const blockType = rawBlock.type;
1181
1207
  if (blockType === "web_search_tool_result") {
@@ -1221,6 +1247,11 @@ async function* runStream(options) {
1221
1247
  } catch (err) {
1222
1248
  throw toError(err);
1223
1249
  }
1250
+ if (!receivedAnyEvent) {
1251
+ throw new ProviderError("anthropic", "Stream ended without producing any events.", {
1252
+ statusCode: 504
1253
+ });
1254
+ }
1224
1255
  const normalizedStop = normalizeAnthropicStopReason(stopReason);
1225
1256
  const response = {
1226
1257
  message: {
@@ -1512,7 +1543,7 @@ function createClient2(options) {
1512
1543
  });
1513
1544
  }
1514
1545
  function streamOpenAI(options) {
1515
- return new StreamResult(runStream2(options));
1546
+ return new StreamResult(runStream2(options), options.signal);
1516
1547
  }
1517
1548
  async function* runStream2(options) {
1518
1549
  const providerName = options.provider ?? "openai";
@@ -1604,51 +1635,62 @@ async function* runStream2(options) {
1604
1635
  let outputTokens = 0;
1605
1636
  let cacheRead = 0;
1606
1637
  let finishReason = null;
1607
- for await (const chunk of stream2) {
1608
- const choice = chunk.choices?.[0];
1609
- if (chunk.usage) {
1610
- ({ inputTokens, outputTokens, cacheRead } = extractOpenAIUsage(chunk.usage));
1611
- }
1612
- if (!choice) continue;
1613
- if (choice.finish_reason) {
1614
- finishReason = choice.finish_reason;
1615
- }
1616
- const delta = choice.delta;
1617
- const reasoningContent = delta.reasoning_content;
1618
- if (typeof reasoningContent === "string" && reasoningContent) {
1619
- thinkingAccum += reasoningContent;
1620
- if (options.thinking) {
1621
- yield { type: "thinking_delta", text: reasoningContent };
1638
+ let receivedAnyChunk = false;
1639
+ try {
1640
+ for await (const chunk of stream2) {
1641
+ receivedAnyChunk = true;
1642
+ const choice = chunk.choices?.[0];
1643
+ if (chunk.usage) {
1644
+ ({ inputTokens, outputTokens, cacheRead } = extractOpenAIUsage(chunk.usage));
1622
1645
  }
1623
- }
1624
- if (delta.content) {
1625
- textAccum += delta.content;
1626
- yield { type: "text_delta", text: delta.content };
1627
- }
1628
- if (delta.tool_calls) {
1629
- for (const tc of delta.tool_calls) {
1630
- let accum = toolCallAccum.get(tc.index);
1631
- if (!accum) {
1632
- accum = {
1633
- id: tc.id ?? "",
1634
- name: tc.function?.name ?? "",
1635
- argsJson: ""
1636
- };
1637
- toolCallAccum.set(tc.index, accum);
1646
+ if (!choice) continue;
1647
+ if (choice.finish_reason) {
1648
+ finishReason = choice.finish_reason;
1649
+ }
1650
+ const delta = choice.delta;
1651
+ const reasoningContent = delta.reasoning_content;
1652
+ if (typeof reasoningContent === "string" && reasoningContent) {
1653
+ thinkingAccum += reasoningContent;
1654
+ if (options.thinking) {
1655
+ yield { type: "thinking_delta", text: reasoningContent };
1638
1656
  }
1639
- if (tc.id) accum.id = tc.id;
1640
- if (tc.function?.name) accum.name = tc.function.name;
1641
- if (tc.function?.arguments) {
1642
- accum.argsJson += tc.function.arguments;
1643
- yield {
1644
- type: "toolcall_delta",
1645
- id: accum.id,
1646
- name: accum.name,
1647
- argsJson: tc.function.arguments
1648
- };
1657
+ }
1658
+ if (delta.content) {
1659
+ textAccum += delta.content;
1660
+ yield { type: "text_delta", text: delta.content };
1661
+ }
1662
+ if (delta.tool_calls) {
1663
+ for (const tc of delta.tool_calls) {
1664
+ let accum = toolCallAccum.get(tc.index);
1665
+ if (!accum) {
1666
+ accum = {
1667
+ id: tc.id ?? "",
1668
+ name: tc.function?.name ?? "",
1669
+ argsJson: ""
1670
+ };
1671
+ toolCallAccum.set(tc.index, accum);
1672
+ }
1673
+ if (tc.id) accum.id = tc.id;
1674
+ if (tc.function?.name) accum.name = tc.function.name;
1675
+ if (tc.function?.arguments) {
1676
+ accum.argsJson += tc.function.arguments;
1677
+ yield {
1678
+ type: "toolcall_delta",
1679
+ id: accum.id,
1680
+ name: accum.name,
1681
+ argsJson: tc.function.arguments
1682
+ };
1683
+ }
1649
1684
  }
1650
1685
  }
1651
1686
  }
1687
+ } catch (err) {
1688
+ throw toError2(err, providerName);
1689
+ }
1690
+ if (!receivedAnyChunk) {
1691
+ throw new ProviderError(providerName, "Stream ended without producing any chunks.", {
1692
+ statusCode: 504
1693
+ });
1652
1694
  }
1653
1695
  if (thinkingAccum) {
1654
1696
  contentParts.push({ type: "thinking", text: thinkingAccum });
@@ -1891,7 +1933,7 @@ function isVisibleOutputItem(itemType) {
1891
1933
  return itemType === "message";
1892
1934
  }
1893
1935
  function streamOpenAICodex(options) {
1894
- return new StreamResult(runStream3(options));
1936
+ return new StreamResult(runStream3(options), options.signal);
1895
1937
  }
1896
1938
  async function* runStream3(options) {
1897
1939
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
@@ -2221,10 +2263,16 @@ async function* parseSSE(body) {
2221
2263
  }
2222
2264
  }
2223
2265
  function remapCodexId(id, idMap) {
2224
- if (id.startsWith("fc_") || id.startsWith("fc-")) return id;
2225
2266
  const existing = idMap.get(id);
2226
2267
  if (existing) return existing;
2227
- const mapped = `fc_${id.replace(/^toolu_/, "")}`;
2268
+ const withPrefix = id.startsWith("fc_") || id.startsWith("fc-") ? id : `fc_${id.replace(/^toolu_/, "")}`;
2269
+ const sanitized = withPrefix.replace(/[^A-Za-z0-9_-]/g, "_");
2270
+ let mapped = sanitized;
2271
+ let suffix = 2;
2272
+ const used = new Set(idMap.values());
2273
+ while (used.has(mapped)) {
2274
+ mapped = `${sanitized}_${suffix++}`;
2275
+ }
2228
2276
  idMap.set(id, mapped);
2229
2277
  return mapped;
2230
2278
  }
@@ -2747,7 +2795,7 @@ async function fetchCodeAssistWithRetry(plan, options) {
2747
2795
  throw lastError ?? new ProviderError("gemini", "Gemini Code Assist request failed.");
2748
2796
  }
2749
2797
  function streamGemini(options) {
2750
- return new StreamResult(runStream4(options));
2798
+ return new StreamResult(runStream4(options), options.signal);
2751
2799
  }
2752
2800
  async function* runStream4(options) {
2753
2801
  const useStreaming = options.streaming !== false;
@@ -3203,7 +3251,7 @@ function registerPalsuProvider(config) {
3203
3251
  const stopReason = explicitStop ?? (hasToolCalls ? "tool_use" : "end_turn");
3204
3252
  return yield* simulateStream(message, stopReason, options.signal, cacheUsage);
3205
3253
  })();
3206
- return new StreamResult(gen);
3254
+ return new StreamResult(gen, options.signal);
3207
3255
  }
3208
3256
  });
3209
3257
  return handle;