@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 +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.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
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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
|
}
|