@kenkaiiii/gg-agent 4.3.199 → 4.3.201

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.cjs CHANGED
@@ -740,136 +740,23 @@ async function* agentLoop(messages, options) {
740
740
  toolCalls.push(tc);
741
741
  }
742
742
  }
743
- const eventStream = new import_gg_ai.EventStream();
744
743
  let fatalToolArgumentError = null;
745
- const executions = toolCalls.map(async (toolCall) => {
746
- const startTime = Date.now();
747
- eventStream.push({
748
- type: "tool_call_start",
749
- toolCallId: toolCall.id,
750
- name: toolCall.name,
751
- args: toolCall.args
752
- });
753
- let resultContent;
754
- let details;
755
- let isError = false;
756
- const tool = toolMap.get(toolCall.name);
757
- if (!tool) {
758
- resultContent = `Unknown tool: ${toolCall.name}`;
759
- isError = true;
760
- } else {
761
- try {
762
- const parsed = tool.parameters.parse(toolCall.args);
763
- const ctx = {
764
- signal: options.signal ?? AbortSignal.timeout(3e5),
765
- toolCallId: toolCall.id,
766
- onUpdate: (update) => {
767
- eventStream.push({
768
- type: "tool_call_update",
769
- toolCallId: toolCall.id,
770
- update
771
- });
772
- }
773
- };
774
- const raw = await tool.execute(parsed, ctx);
775
- const normalized = normalizeToolResult(raw);
776
- resultContent = normalized.content;
777
- details = normalized.details;
778
- for (const key of invalidToolArgumentCounts.keys()) {
779
- if (key.startsWith(`${toolCall.name}:`)) invalidToolArgumentCounts.delete(key);
780
- }
781
- } catch (err) {
782
- isError = true;
783
- if (err instanceof import_zod.ZodError) {
784
- const prettyError = (0, import_zod.prettifyError)(err);
785
- const failureKey = `${toolCall.name}:${prettyError}`;
786
- const failureCount = (invalidToolArgumentCounts.get(failureKey) ?? 0) + 1;
787
- invalidToolArgumentCounts.set(failureKey, failureCount);
788
- resultContent = `Invalid arguments for tool \`${toolCall.name}\`:
789
- ` + prettyError + "\nRe-issue the call with each field as the correct type.";
790
- if (failureCount >= 3) {
791
- fatalToolArgumentError = new Error(
792
- `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.`
793
- );
794
- }
795
- } else {
796
- resultContent = err instanceof Error ? err.message : String(err);
797
- }
798
- }
799
- }
800
- const durationMs = Date.now() - startTime;
801
- eventStream.push({
802
- type: "tool_call_end",
803
- toolCallId: toolCall.id,
804
- result: toolResultPreview(resultContent),
805
- details,
806
- isError,
807
- durationMs
808
- });
809
- return { toolCallId: toolCall.id, content: resultContent, isError };
810
- });
811
- const abortHandler = () => eventStream.abort(new Error("aborted"));
812
- options.signal?.addEventListener("abort", abortHandler, { once: true });
813
- let toolResultsFinalized = false;
814
- Promise.all(executions).then((results) => {
815
- if (toolResultsFinalized) return;
816
- const resultsMap = new Map(results.map((r) => [r.toolCallId, r]));
817
- for (const tc of toolCalls) {
818
- const r = resultsMap.get(tc.id);
819
- toolResults.push({
820
- type: "tool_result",
821
- toolCallId: tc.id,
822
- content: r.content,
823
- isError: r.isError || void 0
824
- });
825
- }
826
- eventStream.close();
827
- }).catch((err) => eventStream.abort(err instanceof Error ? err : new Error(String(err))));
828
- let toolsAborted = false;
829
- try {
830
- for await (const event of eventStream) {
831
- yield event;
832
- }
833
- } catch (err) {
834
- if (isAbortError(err) || options.signal?.aborted) {
835
- toolsAborted = true;
836
- } else {
837
- throw err;
838
- }
839
- } finally {
840
- options.signal?.removeEventListener("abort", abortHandler);
841
- toolResultsFinalized = true;
842
- const resolvedIds = new Set(toolResults.map((r) => r.toolCallId));
843
- for (const tc of toolCalls) {
844
- if (!resolvedIds.has(tc.id)) {
845
- toolResults.push({
846
- type: "tool_result",
847
- toolCallId: tc.id,
848
- content: "Tool execution was aborted.",
849
- isError: true
850
- });
851
- }
852
- }
853
- if (options.maxToolResultChars) {
854
- const HARD_MAX = 4e5;
855
- const max = Math.min(options.maxToolResultChars, HARD_MAX);
856
- for (const tr of toolResults) {
857
- if (typeof tr.content === "string" && tr.content.length > max) {
858
- const headChars = Math.floor(max * 0.7);
859
- const tailChars = max - headChars;
860
- const head = tr.content.slice(0, headChars);
861
- const tail = tr.content.slice(-tailChars);
862
- const omitted = tr.content.length - headChars - tailChars;
863
- tr.content = head + `
864
-
865
- [... ${omitted} characters omitted ...]
866
-
867
- ` + tail;
868
- }
869
- }
870
- }
871
- messages.push({ role: "tool", content: toolResults });
872
- }
744
+ const markFatalToolArgumentError = (error) => {
745
+ fatalToolArgumentError = error;
746
+ };
747
+ const executionOptions = {
748
+ signal: options.signal,
749
+ maxToolResultChars: options.maxToolResultChars,
750
+ toolMap,
751
+ invalidToolArgumentCounts,
752
+ markFatalToolArgumentError
753
+ };
754
+ const hasSequentialToolCall = toolCalls.some(
755
+ (toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
756
+ );
757
+ const executionResult = hasSequentialToolCall ? yield* executeToolCallsSequential(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
758
+ messages.push({ role: "tool", content: executionResult.toolResults });
759
+ const toolsAborted = executionResult.aborted;
873
760
  if (fatalToolArgumentError) {
874
761
  yield { type: "error", error: fatalToolArgumentError };
875
762
  break;
@@ -906,6 +793,197 @@ async function* agentLoop(messages, options) {
906
793
  totalUsage: { ...totalUsage }
907
794
  };
908
795
  }
796
+ function pushToolEvent(eventStream, state, event) {
797
+ if (!state.finalized) eventStream.push(event);
798
+ }
799
+ async function executeSingleToolCall(toolCall, options, pushEvent) {
800
+ const startTime = Date.now();
801
+ pushEvent({
802
+ type: "tool_call_start",
803
+ toolCallId: toolCall.id,
804
+ name: toolCall.name,
805
+ args: toolCall.args
806
+ });
807
+ let resultContent;
808
+ let details;
809
+ let isError = false;
810
+ const tool = options.toolMap.get(toolCall.name);
811
+ if (!tool) {
812
+ resultContent = `Unknown tool: ${toolCall.name}`;
813
+ isError = true;
814
+ } else {
815
+ try {
816
+ const parsed = tool.parameters.parse(toolCall.args);
817
+ const ctx = {
818
+ signal: options.signal ?? AbortSignal.timeout(3e5),
819
+ toolCallId: toolCall.id,
820
+ onUpdate: (update) => {
821
+ pushEvent({
822
+ type: "tool_call_update",
823
+ toolCallId: toolCall.id,
824
+ update
825
+ });
826
+ }
827
+ };
828
+ const raw = await tool.execute(parsed, ctx);
829
+ const normalized = normalizeToolResult(raw);
830
+ resultContent = normalized.content;
831
+ details = normalized.details;
832
+ for (const key of options.invalidToolArgumentCounts.keys()) {
833
+ if (key.startsWith(`${toolCall.name}:`)) options.invalidToolArgumentCounts.delete(key);
834
+ }
835
+ } catch (err) {
836
+ isError = true;
837
+ if (err instanceof import_zod.ZodError) {
838
+ const prettyError = (0, import_zod.prettifyError)(err);
839
+ const failureKey = `${toolCall.name}:${prettyError}`;
840
+ const failureCount = (options.invalidToolArgumentCounts.get(failureKey) ?? 0) + 1;
841
+ options.invalidToolArgumentCounts.set(failureKey, failureCount);
842
+ resultContent = `Invalid arguments for tool \`${toolCall.name}\`:
843
+ ` + prettyError + "\nRe-issue the call with each field as the correct type.";
844
+ if (failureCount >= 3) {
845
+ options.markFatalToolArgumentError(
846
+ new Error(
847
+ `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.`
848
+ )
849
+ );
850
+ }
851
+ } else {
852
+ resultContent = err instanceof Error ? err.message : String(err);
853
+ }
854
+ }
855
+ }
856
+ const durationMs = Date.now() - startTime;
857
+ pushEvent({
858
+ type: "tool_call_end",
859
+ toolCallId: toolCall.id,
860
+ result: toolResultPreview(resultContent),
861
+ details,
862
+ isError,
863
+ durationMs
864
+ });
865
+ return { toolCallId: toolCall.id, content: resultContent, isError };
866
+ }
867
+ async function* executeToolCallsSequential(toolCalls, initialToolResults, options) {
868
+ const eventStream = new import_gg_ai.EventStream();
869
+ const state = { finalized: false };
870
+ const resultsById = /* @__PURE__ */ new Map();
871
+ const abortHandler = () => eventStream.abort(new Error("aborted"));
872
+ options.signal?.addEventListener("abort", abortHandler, { once: true });
873
+ void (async () => {
874
+ try {
875
+ for (const toolCall of toolCalls) {
876
+ if (options.signal?.aborted) break;
877
+ const record = await executeSingleToolCall(
878
+ toolCall,
879
+ options,
880
+ (event) => pushToolEvent(eventStream, state, event)
881
+ );
882
+ resultsById.set(record.toolCallId, record);
883
+ }
884
+ if (!state.finalized) eventStream.close();
885
+ } catch (err) {
886
+ if (!state.finalized) eventStream.abort(err instanceof Error ? err : new Error(String(err)));
887
+ }
888
+ })();
889
+ let aborted = false;
890
+ try {
891
+ for await (const event of eventStream) {
892
+ yield event;
893
+ }
894
+ } catch (err) {
895
+ if (isAbortError(err) || options.signal?.aborted) {
896
+ aborted = true;
897
+ } else {
898
+ throw err;
899
+ }
900
+ } finally {
901
+ options.signal?.removeEventListener("abort", abortHandler);
902
+ state.finalized = true;
903
+ }
904
+ const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
905
+ capToolResults(toolResults, options.maxToolResultChars);
906
+ return { toolResults, aborted };
907
+ }
908
+ async function* executeToolCallsParallel(toolCalls, initialToolResults, options) {
909
+ const eventStream = new import_gg_ai.EventStream();
910
+ const state = { finalized: false };
911
+ const resultsById = /* @__PURE__ */ new Map();
912
+ const abortHandler = () => eventStream.abort(new Error("aborted"));
913
+ options.signal?.addEventListener("abort", abortHandler, { once: true });
914
+ Promise.all(
915
+ toolCalls.map(async (toolCall) => {
916
+ const record = await executeSingleToolCall(
917
+ toolCall,
918
+ options,
919
+ (event) => pushToolEvent(eventStream, state, event)
920
+ );
921
+ resultsById.set(record.toolCallId, record);
922
+ })
923
+ ).then(() => {
924
+ if (!state.finalized) eventStream.close();
925
+ }).catch((err) => {
926
+ if (!state.finalized) eventStream.abort(err instanceof Error ? err : new Error(String(err)));
927
+ });
928
+ let aborted = false;
929
+ try {
930
+ for await (const event of eventStream) {
931
+ yield event;
932
+ }
933
+ } catch (err) {
934
+ if (isAbortError(err) || options.signal?.aborted) {
935
+ aborted = true;
936
+ } else {
937
+ throw err;
938
+ }
939
+ } finally {
940
+ options.signal?.removeEventListener("abort", abortHandler);
941
+ state.finalized = true;
942
+ }
943
+ const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
944
+ capToolResults(toolResults, options.maxToolResultChars);
945
+ return { toolResults, aborted };
946
+ }
947
+ function buildToolResults(initialToolResults, toolCalls, resultsById) {
948
+ const toolResults = [...initialToolResults];
949
+ for (const toolCall of toolCalls) {
950
+ const result = resultsById.get(toolCall.id);
951
+ if (result) {
952
+ toolResults.push({
953
+ type: "tool_result",
954
+ toolCallId: toolCall.id,
955
+ content: result.content,
956
+ isError: result.isError || void 0
957
+ });
958
+ } else {
959
+ toolResults.push({
960
+ type: "tool_result",
961
+ toolCallId: toolCall.id,
962
+ content: "Tool execution was aborted.",
963
+ isError: true
964
+ });
965
+ }
966
+ }
967
+ return toolResults;
968
+ }
969
+ function capToolResults(toolResults, maxToolResultChars) {
970
+ if (!maxToolResultChars) return;
971
+ const hardMax = 4e5;
972
+ const max = Math.min(maxToolResultChars, hardMax);
973
+ for (const toolResult of toolResults) {
974
+ if (typeof toolResult.content !== "string" || toolResult.content.length <= max) continue;
975
+ const headChars = Math.floor(max * 0.7);
976
+ const tailChars = max - headChars;
977
+ const head = toolResult.content.slice(0, headChars);
978
+ const tail = toolResult.content.slice(-tailChars);
979
+ const omitted = toolResult.content.length - headChars - tailChars;
980
+ toolResult.content = head + `
981
+
982
+ [... ${omitted} characters omitted ...]
983
+
984
+ ` + tail;
985
+ }
986
+ }
909
987
  function normalizeToolResult(raw) {
910
988
  return typeof raw === "string" ? { content: raw } : raw;
911
989
  }