@kenkaiiii/gg-agent 5.83.2 → 5.83.3
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 +46 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +47 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
stream,
|
|
8
8
|
EventStream,
|
|
9
9
|
GGAIError,
|
|
10
|
+
ResponseStalledError,
|
|
10
11
|
environmentSecrets,
|
|
11
12
|
isHardBillingMessage,
|
|
12
13
|
redactValue,
|
|
@@ -605,6 +606,9 @@ async function* agentLoop(messages, options) {
|
|
|
605
606
|
let overloadRetries = 0;
|
|
606
607
|
let emptyResponseRetries = 0;
|
|
607
608
|
let stallRetries = 0;
|
|
609
|
+
let splitToolCallHintAdded = false;
|
|
610
|
+
let stalledInToolCall = false;
|
|
611
|
+
let stalledAfterConnecting = false;
|
|
608
612
|
let runawayToolcallRetries = 0;
|
|
609
613
|
let overflowCompactionAttempts = 0;
|
|
610
614
|
let toolResultTruncationAttempted = false;
|
|
@@ -622,6 +626,7 @@ async function* agentLoop(messages, options) {
|
|
|
622
626
|
const STALL_DELAY_MS = 1e3;
|
|
623
627
|
const MIN_PARTIAL_PRESERVE_CHARS = 200;
|
|
624
628
|
const PARTIAL_CONTINUATION_PROMPT = "[Your previous response was cut off by a connection failure. The text above is what was already delivered to the user. Continue exactly from where it stopped \u2014 do not repeat or restart it.]";
|
|
629
|
+
const SPLIT_TOOL_CALL_PROMPT = "[Your previous response was cut off while you were still writing a tool call's arguments, after minutes without data from the provider. None of that call was applied. Do not resend it as one large call: split the work into smaller pieces (e.g. a shorter first version, then further edits, or one file per call).]";
|
|
625
630
|
const MAX_OUTPUT_CONTINUATIONS = 2;
|
|
626
631
|
const MAX_TOKENS_CONTINUATION_PROMPT = "[Your previous response hit the output-token limit and was cut off. The text above is what was already delivered to the user. Continue exactly from where it stopped \u2014 do not repeat or restart it.]";
|
|
627
632
|
let maxTokensContinuations = 0;
|
|
@@ -647,7 +652,7 @@ async function* agentLoop(messages, options) {
|
|
|
647
652
|
const NON_STREAMING_HARD_TIMEOUT_MS = 3e5;
|
|
648
653
|
const nonStreamingHardTimeoutMs = options.thinking != null ? STREAM_THINKING_HARD_TIMEOUT_MS : NON_STREAMING_HARD_TIMEOUT_MS;
|
|
649
654
|
const VISIBLE_STALL_AFTER_MS = 6e4;
|
|
650
|
-
const usesSilentReasoningBudget = options.provider === "sakana" || options.provider === "openai" && options.thinking != null;
|
|
655
|
+
const usesSilentReasoningBudget = options.provider === "sakana" || options.provider === "xai" || options.provider === "openai" && options.thinking != null;
|
|
651
656
|
const localBackend = isLocalBackendUrl(options.baseUrl);
|
|
652
657
|
const baseFirstEventTimeoutMs = localBackend ? Number.POSITIVE_INFINITY : usesSilentReasoningBudget ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
|
|
653
658
|
const baseHardTimeoutMs = localBackend || usesSilentReasoningBudget ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
|
|
@@ -869,7 +874,7 @@ async function* agentLoop(messages, options) {
|
|
|
869
874
|
}, hardTimeoutMs);
|
|
870
875
|
}
|
|
871
876
|
}
|
|
872
|
-
if (event.type === "thinking_delta" && !hasReceivedThinking) {
|
|
877
|
+
if ((event.type === "thinking_delta" || event.type === "keepalive" && event.reasoning === true) && !hasReceivedThinking) {
|
|
873
878
|
hasReceivedThinking = true;
|
|
874
879
|
if (hardTimer) clearTimeout(hardTimer);
|
|
875
880
|
hardTimeoutMs = STREAM_THINKING_HARD_TIMEOUT_MS;
|
|
@@ -1198,6 +1203,9 @@ async function* agentLoop(messages, options) {
|
|
|
1198
1203
|
const malformed = isMalformedStream(err);
|
|
1199
1204
|
const socketDrop = isTransportFailure(err);
|
|
1200
1205
|
const transportFailure = (idleTimedOut || malformed || socketDrop) && !options.signal?.aborted;
|
|
1206
|
+
const attemptMs = Date.now() - streamCallStart;
|
|
1207
|
+
if (transportFailure && toolInputOpen) stalledInToolCall = true;
|
|
1208
|
+
if (transportFailure && streamEventCount > 0) stalledAfterConnecting = true;
|
|
1201
1209
|
if (transportFailure && stallRetries < MAX_STALL_RETRIES) {
|
|
1202
1210
|
stallRetries++;
|
|
1203
1211
|
const cause = malformed ? "malformed_stream" : socketDrop ? "socket_drop" : "stream_stall";
|
|
@@ -1228,6 +1236,20 @@ async function* agentLoop(messages, options) {
|
|
|
1228
1236
|
});
|
|
1229
1237
|
preservedChars = attemptText.length;
|
|
1230
1238
|
}
|
|
1239
|
+
let splitHint = false;
|
|
1240
|
+
if (toolInputOpen && attemptMs >= VISIBLE_STALL_AFTER_MS && !splitToolCallHintAdded) {
|
|
1241
|
+
splitToolCallHintAdded = true;
|
|
1242
|
+
splitHint = true;
|
|
1243
|
+
messages.push({
|
|
1244
|
+
role: "user",
|
|
1245
|
+
content: SPLIT_TOOL_CALL_PROMPT,
|
|
1246
|
+
provenance: {
|
|
1247
|
+
source: "runtime",
|
|
1248
|
+
kind: "continuation",
|
|
1249
|
+
visibility: "hidden"
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1231
1253
|
diag("retry", {
|
|
1232
1254
|
reason: cause,
|
|
1233
1255
|
attempt: stallRetries,
|
|
@@ -1235,7 +1257,8 @@ async function* agentLoop(messages, options) {
|
|
|
1235
1257
|
delayMs,
|
|
1236
1258
|
events: streamEventCount,
|
|
1237
1259
|
nonStreaming: useNonStreamingFallback,
|
|
1238
|
-
preservedChars
|
|
1260
|
+
preservedChars,
|
|
1261
|
+
splitHint
|
|
1239
1262
|
});
|
|
1240
1263
|
yield {
|
|
1241
1264
|
type: "retry",
|
|
@@ -1262,9 +1285,25 @@ async function* agentLoop(messages, options) {
|
|
|
1262
1285
|
eventTypes: eventTypeCounts,
|
|
1263
1286
|
lastEventType,
|
|
1264
1287
|
sinceLastEventMs: Date.now() - lastEventTime,
|
|
1265
|
-
attemptDurationMs:
|
|
1266
|
-
maxConsumerLagMs
|
|
1288
|
+
attemptDurationMs: attemptMs,
|
|
1289
|
+
maxConsumerLagMs,
|
|
1290
|
+
stalledAfterConnecting,
|
|
1291
|
+
stalledInToolCall
|
|
1267
1292
|
});
|
|
1293
|
+
if (stalledAfterConnecting) {
|
|
1294
|
+
yield {
|
|
1295
|
+
type: "error",
|
|
1296
|
+
error: new ResponseStalledError(
|
|
1297
|
+
`The provider stopped sending data before the response finished, ${MAX_STALL_RETRIES} automatic retries in a row. Your conversation is preserved.`,
|
|
1298
|
+
{
|
|
1299
|
+
inToolCall: stalledInToolCall,
|
|
1300
|
+
hint: stalledInToolCall ? "The model was writing one very large tool call each time. Ask it to make the change in smaller pieces (shorter files or several edits), then retry." : "Retry once. If it keeps happening, choose another model or lower the thinking level, and disable any VPN or proxy that may buffer streamed responses.",
|
|
1301
|
+
cause: err
|
|
1302
|
+
}
|
|
1303
|
+
)
|
|
1304
|
+
};
|
|
1305
|
+
break;
|
|
1306
|
+
}
|
|
1268
1307
|
yield {
|
|
1269
1308
|
type: "error",
|
|
1270
1309
|
error: new GGAIError(
|
|
@@ -1313,6 +1352,9 @@ async function* agentLoop(messages, options) {
|
|
|
1313
1352
|
}
|
|
1314
1353
|
overloadRetries = 0;
|
|
1315
1354
|
stallRetries = 0;
|
|
1355
|
+
splitToolCallHintAdded = false;
|
|
1356
|
+
stalledInToolCall = false;
|
|
1357
|
+
stalledAfterConnecting = false;
|
|
1316
1358
|
runawayToolcallRetries = 0;
|
|
1317
1359
|
const contentArr = Array.isArray(response.message.content) ? response.message.content : null;
|
|
1318
1360
|
const hasActionableContent = response.message.content !== "" && contentArr !== null && contentArr.some(
|