@kenkaiiii/gg-agent 4.11.3 → 4.12.1

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
@@ -249,23 +249,25 @@ async function* agentLoop(messages, options) {
249
249
  while (turn < maxTurns) {
250
250
  options.signal?.throwIfAborted();
251
251
  turn++;
252
- let msgChars = 0;
253
- for (const m of messages) {
254
- if (typeof m.content === "string") msgChars += m.content.length;
255
- else if (Array.isArray(m.content)) {
256
- for (const p of m.content) {
257
- if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
258
- if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
252
+ if (_diagFn) {
253
+ let msgChars = 0;
254
+ for (const m of messages) {
255
+ if (typeof m.content === "string") msgChars += m.content.length;
256
+ else if (Array.isArray(m.content)) {
257
+ for (const p of m.content) {
258
+ if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
259
+ if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
260
+ }
259
261
  }
260
262
  }
263
+ diag("turn_start", {
264
+ turn,
265
+ messages: messages.length,
266
+ chars: msgChars,
267
+ provider: options.provider,
268
+ model: options.model
269
+ });
261
270
  }
262
- diag("turn_start", {
263
- turn,
264
- messages: messages.length,
265
- chars: msgChars,
266
- provider: options.provider,
267
- model: options.model
268
- });
269
271
  if (firstTurn && options.getSteeringMessages) {
270
272
  const steering = await options.getSteeringMessages();
271
273
  if (steering && steering.length > 0) {
@@ -801,7 +803,7 @@ async function* agentLoop(messages, options) {
801
803
  const hasSequentialToolCall = toolCalls.some(
802
804
  (toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
803
805
  );
804
- const executionResult = hasSequentialToolCall ? yield* executeToolCallsSequential(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
806
+ const executionResult = hasSequentialToolCall ? yield* executeToolCallsMixed(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
805
807
  messages.push({ role: "tool", content: executionResult.toolResults });
806
808
  const toolsAborted = executionResult.aborted;
807
809
  if (fatalToolArgumentError) {
@@ -861,8 +863,10 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
861
863
  } else {
862
864
  try {
863
865
  const parsed = tool.parameters.parse(toolCall.args);
866
+ const callerSignal = options.signal;
867
+ const toolTimeout = AbortSignal.timeout(3e5);
864
868
  const ctx = {
865
- signal: options.signal ?? AbortSignal.timeout(3e5),
869
+ signal: callerSignal ? AbortSignal.any([callerSignal, toolTimeout]) : toolTimeout,
866
870
  toolCallId: toolCall.id,
867
871
  onUpdate: (update) => {
868
872
  pushEvent({
@@ -911,22 +915,59 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
911
915
  });
912
916
  return { toolCallId: toolCall.id, content: resultContent, isError };
913
917
  }
914
- async function* executeToolCallsSequential(toolCalls, initialToolResults, options) {
918
+ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
915
919
  const eventStream = new import_gg_ai.EventStream();
916
920
  const state = { finalized: false };
917
921
  const resultsById = /* @__PURE__ */ new Map();
918
922
  const abortHandler = () => eventStream.abort(new Error("aborted"));
919
923
  options.signal?.addEventListener("abort", abortHandler, { once: true });
924
+ const phases = [];
925
+ let currentParallel = [];
926
+ for (const toolCall of toolCalls) {
927
+ const isSequential = options.toolMap.get(toolCall.name)?.executionMode === "sequential";
928
+ if (isSequential) {
929
+ if (currentParallel.length > 0) {
930
+ phases.push({ parallel: currentParallel, sequential: null });
931
+ currentParallel = [];
932
+ }
933
+ phases.push({ parallel: [], sequential: toolCall });
934
+ } else {
935
+ currentParallel.push(toolCall);
936
+ }
937
+ }
938
+ if (currentParallel.length > 0) {
939
+ phases.push({ parallel: currentParallel, sequential: null });
940
+ }
920
941
  void (async () => {
921
942
  try {
922
- for (const toolCall of toolCalls) {
943
+ for (const phase of phases) {
923
944
  if (options.signal?.aborted) break;
924
- const record = await executeSingleToolCall(
925
- toolCall,
926
- options,
927
- (event) => pushToolEvent(eventStream, state, event)
928
- );
929
- resultsById.set(record.toolCallId, record);
945
+ if (phase.sequential) {
946
+ const record = await executeSingleToolCall(
947
+ phase.sequential,
948
+ options,
949
+ (event) => pushToolEvent(eventStream, state, event)
950
+ );
951
+ resultsById.set(record.toolCallId, record);
952
+ } else if (phase.parallel.length === 1) {
953
+ const record = await executeSingleToolCall(
954
+ phase.parallel[0],
955
+ options,
956
+ (event) => pushToolEvent(eventStream, state, event)
957
+ );
958
+ resultsById.set(record.toolCallId, record);
959
+ } else {
960
+ await Promise.all(
961
+ phase.parallel.map(async (toolCall) => {
962
+ const record = await executeSingleToolCall(
963
+ toolCall,
964
+ options,
965
+ (event) => pushToolEvent(eventStream, state, event)
966
+ );
967
+ resultsById.set(record.toolCallId, record);
968
+ })
969
+ );
970
+ }
930
971
  }
931
972
  if (!state.finalized) eventStream.close();
932
973
  } catch (err) {