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