@kenkaiiii/gg-agent 5.4.0 → 5.4.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.js CHANGED
@@ -6,6 +6,7 @@ import { ZodError, prettifyError } from "zod";
6
6
  import {
7
7
  stream,
8
8
  EventStream,
9
+ GGAIError,
9
10
  isHardBillingMessage
10
11
  } from "@kenkaiiii/gg-ai";
11
12
  var DEFAULT_MAX_TURNS = 300;
@@ -198,6 +199,7 @@ async function* agentLoop(messages, options) {
198
199
  let overflowCompactionAttempts = 0;
199
200
  let toolResultTruncationAttempted = false;
200
201
  const invalidToolArgumentCounts = /* @__PURE__ */ new Map();
202
+ let toolArgumentAutoContinueUsed = false;
201
203
  let useNonStreamingFallback = false;
202
204
  const MAX_OVERLOAD_RETRIES = 10;
203
205
  const MAX_EMPTY_RESPONSE_RETRIES = 2;
@@ -764,8 +766,12 @@ async function* agentLoop(messages, options) {
764
766
  }
765
767
  }
766
768
  let fatalToolArgumentError = null;
767
- const markFatalToolArgumentError = (error) => {
769
+ let fatalToolArgumentRecoverable = false;
770
+ let fatalToolArgumentToolName = "";
771
+ const markFatalToolArgumentError = (error, recoverable, toolName) => {
768
772
  fatalToolArgumentError = error;
773
+ fatalToolArgumentRecoverable = recoverable;
774
+ fatalToolArgumentToolName = toolName;
769
775
  };
770
776
  const executionOptions = {
771
777
  signal: options.signal,
@@ -781,8 +787,24 @@ async function* agentLoop(messages, options) {
781
787
  messages.push({ role: "tool", content: executionResult.toolResults });
782
788
  const toolsAborted = executionResult.aborted;
783
789
  if (fatalToolArgumentError) {
784
- yield { type: "error", error: fatalToolArgumentError };
785
- break;
790
+ if (fatalToolArgumentRecoverable && !toolArgumentAutoContinueUsed) {
791
+ toolArgumentAutoContinueUsed = true;
792
+ for (const key of invalidToolArgumentCounts.keys()) {
793
+ if (key.startsWith(`${fatalToolArgumentToolName}:`))
794
+ invalidToolArgumentCounts.delete(key);
795
+ }
796
+ yield {
797
+ type: "retry",
798
+ reason: "tool_argument_glitch",
799
+ attempt: 1,
800
+ maxAttempts: 1,
801
+ delayMs: 0,
802
+ silent: false
803
+ };
804
+ } else {
805
+ yield { type: "error", error: fatalToolArgumentError };
806
+ break;
807
+ }
786
808
  }
787
809
  if (toolsAborted) break;
788
810
  if (options.getSteeringMessages) {
@@ -867,10 +889,17 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
867
889
  resultContent = `Invalid arguments for tool \`${toolCall.name}\`:
868
890
  ` + prettyError + "\nRe-issue the call with each field as the correct type.";
869
891
  if (failureCount >= 3) {
892
+ const recoverable = Object.keys(toolCall.args ?? {}).length === 0;
870
893
  options.markFatalToolArgumentError(
871
- new Error(
872
- `The model repeatedly issued invalid arguments for tool \`${toolCall.name}\`. This is usually an upstream model/tool-calling bug. Your conversation is preserved; send another message or switch models to continue.`
873
- )
894
+ new GGAIError(
895
+ `The model repeatedly issued invalid arguments for tool \`${toolCall.name}\`. This is usually an upstream model/tool-calling bug` + (recoverable ? " (the provider's stream returned empty tool-call arguments)" : "") + `. Your conversation is preserved; send another message or switch models to continue.`,
896
+ {
897
+ source: "provider",
898
+ hint: "This is the model/provider's fault, not a ggcoder bug. " + (recoverable ? "ggcoder already retried automatically once; if it recurs, send another message or switch models." : "Send another message or switch models to continue.")
899
+ }
900
+ ),
901
+ recoverable,
902
+ toolCall.name
874
903
  );
875
904
  }
876
905
  } else {