@kenkaiiii/gg-agent 5.60.9 → 5.61.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 +73 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +73 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -298,6 +298,35 @@ function abortableSleep(ms, signal) {
|
|
|
298
298
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
299
299
|
});
|
|
300
300
|
}
|
|
301
|
+
var PREFILL_TIMEOUT_MS_PER_1K_TOKENS = 640;
|
|
302
|
+
var STREAM_FIRST_EVENT_TIMEOUT_MS = 45e3;
|
|
303
|
+
var STREAM_FIRST_EVENT_TIMEOUT_MAX_MS = 18e4;
|
|
304
|
+
var STREAM_FIRST_EVENT_TIMEOUT_SCALE_MIN_TOKENS = 2e4;
|
|
305
|
+
function scaledFirstEventTimeoutMs(promptTokens) {
|
|
306
|
+
if (promptTokens < STREAM_FIRST_EVENT_TIMEOUT_SCALE_MIN_TOKENS) return null;
|
|
307
|
+
return Math.min(
|
|
308
|
+
STREAM_FIRST_EVENT_TIMEOUT_MAX_MS,
|
|
309
|
+
STREAM_FIRST_EVENT_TIMEOUT_MS + promptTokens / 1e3 * PREFILL_TIMEOUT_MS_PER_1K_TOKENS
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
var CACHE_HEALTH_MIN_PROMPT_TOKENS = 4e4;
|
|
313
|
+
var CACHE_HEALTH_LOW_RATIO = 0.5;
|
|
314
|
+
function assessCacheHealth(usage) {
|
|
315
|
+
const input = usage.inputTokens ?? 0;
|
|
316
|
+
const cacheRead = usage.cacheRead ?? 0;
|
|
317
|
+
const cacheWrite = usage.cacheWrite ?? 0;
|
|
318
|
+
const promptTokens = input + cacheRead + cacheWrite;
|
|
319
|
+
if (promptTokens < CACHE_HEALTH_MIN_PROMPT_TOKENS) {
|
|
320
|
+
return { ratio: null, promptTokens, cacheRead, low: false };
|
|
321
|
+
}
|
|
322
|
+
const ratio = cacheRead / promptTokens;
|
|
323
|
+
return {
|
|
324
|
+
ratio,
|
|
325
|
+
promptTokens,
|
|
326
|
+
cacheRead,
|
|
327
|
+
low: ratio < CACHE_HEALTH_LOW_RATIO
|
|
328
|
+
};
|
|
329
|
+
}
|
|
301
330
|
async function* agentLoop(messages, options) {
|
|
302
331
|
const maxTurns = options.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
303
332
|
let effectiveMaxTurns = maxTurns;
|
|
@@ -339,6 +368,7 @@ async function* agentLoop(messages, options) {
|
|
|
339
368
|
let providerCalls = 0;
|
|
340
369
|
let nonStreamingCalls = 0;
|
|
341
370
|
let warnedNonStreaming = false;
|
|
371
|
+
let warnedPromptCacheMiss = false;
|
|
342
372
|
const MAX_OUTPUT_CEILING_RETRIES = 1;
|
|
343
373
|
let outputCeilingRetries = 0;
|
|
344
374
|
const ceilingKey = outputRouteKey({
|
|
@@ -348,7 +378,6 @@ async function* agentLoop(messages, options) {
|
|
|
348
378
|
});
|
|
349
379
|
const OVERLOAD_BASE_DELAY_MS = 2e3;
|
|
350
380
|
const OVERLOAD_MAX_DELAY_MS = 3e4;
|
|
351
|
-
const STREAM_FIRST_EVENT_TIMEOUT_MS = 45e3;
|
|
352
381
|
const STREAM_IDLE_TIMEOUT_MS = 9e4;
|
|
353
382
|
const STREAM_HARD_TIMEOUT_MS = 9e4;
|
|
354
383
|
const STREAM_OUTPUT_HARD_TIMEOUT_MS = 3e5;
|
|
@@ -357,8 +386,8 @@ async function* agentLoop(messages, options) {
|
|
|
357
386
|
const NON_STREAMING_HARD_TIMEOUT_MS = 3e5;
|
|
358
387
|
const usesSilentReasoningBudget = options.provider === "sakana" || options.provider === "openai" && options.thinking != null;
|
|
359
388
|
const localBackend = isLocalBackendUrl(options.baseUrl);
|
|
360
|
-
const
|
|
361
|
-
const
|
|
389
|
+
const baseFirstEventTimeoutMs = localBackend ? Number.POSITIVE_INFINITY : usesSilentReasoningBudget ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
|
|
390
|
+
const baseHardTimeoutMs = localBackend || usesSilentReasoningBudget ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
|
|
362
391
|
const MAX_TOOLCALL_DELTA_CHARS = 1e6;
|
|
363
392
|
const MAX_TOOLCALL_DELTA_EVENTS = 2e4;
|
|
364
393
|
let logicalTurnStartedAt = 0;
|
|
@@ -370,17 +399,28 @@ async function* agentLoop(messages, options) {
|
|
|
370
399
|
turn++;
|
|
371
400
|
if (logicalTurnStartedAt === 0) logicalTurnStartedAt = Date.now();
|
|
372
401
|
toolMap = new Map((options.tools ?? []).map((t) => [t.name, t]));
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
|
|
381
|
-
}
|
|
402
|
+
let msgChars = 0;
|
|
403
|
+
for (const m of messages) {
|
|
404
|
+
if (typeof m.content === "string") msgChars += m.content.length;
|
|
405
|
+
else if (Array.isArray(m.content)) {
|
|
406
|
+
for (const p of m.content) {
|
|
407
|
+
if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
|
|
408
|
+
if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
|
|
382
409
|
}
|
|
383
410
|
}
|
|
411
|
+
}
|
|
412
|
+
let firstEventTimeoutMs;
|
|
413
|
+
let initialHardTimeoutMs;
|
|
414
|
+
if (baseFirstEventTimeoutMs === STREAM_FIRST_EVENT_TIMEOUT_MS) {
|
|
415
|
+
const promptTokens = Math.ceil(msgChars / 3);
|
|
416
|
+
const scaled = scaledFirstEventTimeoutMs(promptTokens);
|
|
417
|
+
firstEventTimeoutMs = scaled ?? baseFirstEventTimeoutMs;
|
|
418
|
+
initialHardTimeoutMs = Math.max(baseHardTimeoutMs, firstEventTimeoutMs + 3e4);
|
|
419
|
+
} else {
|
|
420
|
+
firstEventTimeoutMs = baseFirstEventTimeoutMs;
|
|
421
|
+
initialHardTimeoutMs = baseHardTimeoutMs;
|
|
422
|
+
}
|
|
423
|
+
if (_diagFn) {
|
|
384
424
|
diag("turn_start", {
|
|
385
425
|
turn,
|
|
386
426
|
messages: messages.length,
|
|
@@ -990,6 +1030,27 @@ async function* agentLoop(messages, options) {
|
|
|
990
1030
|
if (response.usage.cacheWrite) {
|
|
991
1031
|
totalUsage.cacheWrite = (totalUsage.cacheWrite ?? 0) + response.usage.cacheWrite;
|
|
992
1032
|
}
|
|
1033
|
+
const cacheHealth = assessCacheHealth(response.usage);
|
|
1034
|
+
if (cacheHealth.ratio !== null) {
|
|
1035
|
+
diag("cache_health", {
|
|
1036
|
+
promptTokens: cacheHealth.promptTokens,
|
|
1037
|
+
cacheRead: cacheHealth.cacheRead,
|
|
1038
|
+
ratio: Math.round(cacheHealth.ratio * 100) / 100,
|
|
1039
|
+
provider: options.provider,
|
|
1040
|
+
model: options.model
|
|
1041
|
+
});
|
|
1042
|
+
if (cacheHealth.low && !warnedPromptCacheMiss) {
|
|
1043
|
+
warnedPromptCacheMiss = true;
|
|
1044
|
+
diag("prompt_cache_miss", {
|
|
1045
|
+
promptTokens: cacheHealth.promptTokens,
|
|
1046
|
+
cacheRead: cacheHealth.cacheRead,
|
|
1047
|
+
ratio: Math.round(cacheHealth.ratio * 100) / 100,
|
|
1048
|
+
provider: options.provider,
|
|
1049
|
+
model: options.model,
|
|
1050
|
+
impact: "large prompts are consistently served mostly uncached \u2014 every turn re-prefills the whole context; if this persists, lower the provider's compaction latency cap (resolveCompactionPolicy)"
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
993
1054
|
if (!emptyExhausted) {
|
|
994
1055
|
messages.push(response.message);
|
|
995
1056
|
latestProviderUsage = response.usage;
|