@kenkaiiii/gg-agent 5.22.2 → 5.22.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.
package/dist/index.d.cts CHANGED
@@ -102,7 +102,7 @@ interface AgentTruncatedEvent {
102
102
  }
103
103
  interface AgentRetryEvent {
104
104
  type: "retry";
105
- reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact" | "tool_argument_glitch";
105
+ reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact" | "tool_argument_glitch" | "runaway_toolcall";
106
106
  attempt: number;
107
107
  maxAttempts: number;
108
108
  delayMs: number;
package/dist/index.d.ts CHANGED
@@ -102,7 +102,7 @@ interface AgentTruncatedEvent {
102
102
  }
103
103
  interface AgentRetryEvent {
104
104
  type: "retry";
105
- reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact" | "tool_argument_glitch";
105
+ reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact" | "tool_argument_glitch" | "runaway_toolcall";
106
106
  attempt: number;
107
107
  maxAttempts: number;
108
108
  delayMs: number;
package/dist/index.js CHANGED
@@ -200,6 +200,7 @@ async function* agentLoop(messages, options) {
200
200
  let overloadRetries = 0;
201
201
  let emptyResponseRetries = 0;
202
202
  let stallRetries = 0;
203
+ let runawayToolcallRetries = 0;
203
204
  let overflowCompactionAttempts = 0;
204
205
  let toolResultTruncationAttempted = false;
205
206
  const invalidToolArgumentCounts = /* @__PURE__ */ new Map();
@@ -208,6 +209,8 @@ async function* agentLoop(messages, options) {
208
209
  const MAX_OVERLOAD_RETRIES = 10;
209
210
  const MAX_EMPTY_RESPONSE_RETRIES = 2;
210
211
  const MAX_STALL_RETRIES = 5;
212
+ const MAX_RUNAWAY_TOOLCALL_RETRIES = 2;
213
+ const RUNAWAY_TOOLCALL_RETRY_DELAY_MS = 1e3;
211
214
  const MAX_OVERFLOW_COMPACTIONS = 2;
212
215
  const STALL_RETRIES_BEFORE_NON_STREAMING = 2;
213
216
  const STALL_DELAY_MS = 1e3;
@@ -225,9 +228,9 @@ async function* agentLoop(messages, options) {
225
228
  const STREAM_THINKING_IDLE_TIMEOUT_MS = 3e5;
226
229
  const STREAM_THINKING_HARD_TIMEOUT_MS = 6e5;
227
230
  const NON_STREAMING_HARD_TIMEOUT_MS = 3e5;
228
- const isSakana = options.provider === "sakana";
229
- const firstEventTimeoutMs = isSakana ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
230
- const initialHardTimeoutMs = isSakana ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
231
+ const usesSilentReasoningBudget = options.provider === "sakana" || options.provider === "openai" && options.thinking != null;
232
+ const firstEventTimeoutMs = usesSilentReasoningBudget ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
233
+ const initialHardTimeoutMs = usesSilentReasoningBudget ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
231
234
  const MAX_TOOLCALL_DELTA_CHARS = 1e6;
232
235
  const MAX_TOOLCALL_DELTA_EVENTS = 2e4;
233
236
  let logicalTurnStartedAt = 0;
@@ -255,7 +258,10 @@ async function* agentLoop(messages, options) {
255
258
  messages: messages.length,
256
259
  chars: msgChars,
257
260
  provider: options.provider,
258
- model: options.model
261
+ model: options.model,
262
+ thinking: options.thinking ?? "off",
263
+ firstEventTimeoutMs,
264
+ initialHardTimeoutMs
259
265
  });
260
266
  }
261
267
  if (firstTurn && options.getSteeringMessages) {
@@ -612,11 +618,33 @@ async function* agentLoop(messages, options) {
612
618
  provider: options.provider,
613
619
  model: options.model
614
620
  });
621
+ if (runawayToolcallRetries < MAX_RUNAWAY_TOOLCALL_RETRIES) {
622
+ runawayToolcallRetries++;
623
+ const delayMs = RUNAWAY_TOOLCALL_RETRY_DELAY_MS * runawayToolcallRetries;
624
+ diag("retry", {
625
+ reason: "runaway_toolcall",
626
+ attempt: runawayToolcallRetries,
627
+ maxAttempts: MAX_RUNAWAY_TOOLCALL_RETRIES,
628
+ delayMs,
629
+ ...runawayDetected
630
+ });
631
+ yield {
632
+ type: "retry",
633
+ reason: "runaway_toolcall",
634
+ attempt: runawayToolcallRetries,
635
+ maxAttempts: MAX_RUNAWAY_TOOLCALL_RETRIES,
636
+ delayMs,
637
+ silent: true
638
+ };
639
+ await abortableSleep(delayMs, options.signal);
640
+ turn--;
641
+ continue;
642
+ }
615
643
  const detail = runawayDetected.kind === "chars" ? `${(runawayDetected.chars / 1024).toFixed(0)} KB of tool-call arguments` : `${runawayDetected.events} tool-call delta events`;
616
644
  yield {
617
645
  type: "error",
618
646
  error: new Error(
619
- `The model glitched mid-tool-call and produced ${detail} without closing the call. This is usually an upstream model bug \u2014 try the same request again or switch models. Your conversation is preserved.`
647
+ `The model repeatedly failed to close a tool call after ${MAX_RUNAWAY_TOOLCALL_RETRIES} automatic retries (${detail}). Switch models and retry; your conversation is preserved.`
620
648
  )
621
649
  };
622
650
  break;
@@ -669,15 +697,29 @@ async function* agentLoop(messages, options) {
669
697
  continue;
670
698
  }
671
699
  if (transportFailure) {
700
+ const cause = malformed ? "malformed_stream" : socketDrop ? "socket_drop" : "stream_stall";
672
701
  diag("stall_exhausted", {
673
702
  stallRetries: MAX_STALL_RETRIES,
674
703
  provider: options.provider,
675
- model: options.model
704
+ model: options.model,
705
+ cause,
706
+ nonStreaming: useNonStreamingFallback,
707
+ events: streamEventCount,
708
+ eventTypes: eventTypeCounts,
709
+ lastEventType,
710
+ sinceLastEventMs: Date.now() - lastEventTime,
711
+ attemptDurationMs: Date.now() - streamCallStart,
712
+ maxConsumerLagMs
676
713
  });
677
714
  yield {
678
715
  type: "error",
679
- error: new Error(
680
- `The API provider's stream stalled ${MAX_STALL_RETRIES} times \u2014 the provider may be experiencing capacity issues. Your conversation is preserved. Send another message to retry.`
716
+ error: new GGAIError(
717
+ `The connection to the API provider stopped responding after ${MAX_STALL_RETRIES} automatic retries. Your conversation is preserved.`,
718
+ {
719
+ source: "network",
720
+ hint: "Retry once. If it keeps happening on this device, disable any VPN or proxy and allow GG Coder through firewall or antivirus web protection.",
721
+ cause: err
722
+ }
681
723
  )
682
724
  };
683
725
  break;
@@ -717,6 +759,7 @@ async function* agentLoop(messages, options) {
717
759
  }
718
760
  overloadRetries = 0;
719
761
  stallRetries = 0;
762
+ runawayToolcallRetries = 0;
720
763
  const contentArr = Array.isArray(response.message.content) ? response.message.content : null;
721
764
  const hasActionableContent = response.message.content !== "" && contentArr !== null && contentArr.some(
722
765
  (p) => p.type === "text" || p.type === "tool_call" || p.type === "server_tool_call"