pullfrog 0.1.19 → 0.1.21
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/cli.mjs +121 -160
- package/dist/index.js +120 -159
- package/dist/internal.js +4 -10
- package/dist/utils/activity.d.ts +18 -33
- package/dist/utils/subprocess.d.ts +0 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -101189,11 +101189,12 @@ var modelAliases = Object.entries(providers).flatMap(
|
|
|
101189
101189
|
hidden: def.hidden ?? false
|
|
101190
101190
|
}))
|
|
101191
101191
|
);
|
|
101192
|
-
var defaultProxyAlias = modelAliases.find((a) => a.slug === "
|
|
101192
|
+
var defaultProxyAlias = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro");
|
|
101193
101193
|
if (!defaultProxyAlias?.openRouterResolve) {
|
|
101194
|
-
throw new Error("DEFAULT_PROXY_MODEL:
|
|
101194
|
+
throw new Error("DEFAULT_PROXY_MODEL: deepseek/deepseek-pro missing openRouterResolve");
|
|
101195
101195
|
}
|
|
101196
101196
|
var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
|
|
101197
|
+
var defaultProxyDisplayName = defaultProxyAlias.displayName;
|
|
101197
101198
|
var MAX_FALLBACK_DEPTH = 10;
|
|
101198
101199
|
function resolveDisplayAlias(slug2) {
|
|
101199
101200
|
let current = slug2;
|
|
@@ -101235,6 +101236,111 @@ function formatMcpToolRef(agentId, toolName) {
|
|
|
101235
101236
|
|
|
101236
101237
|
// utils/activity.ts
|
|
101237
101238
|
import { performance as performance2 } from "node:perf_hooks";
|
|
101239
|
+
function isMonitorDebugEnabled() {
|
|
101240
|
+
return process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || process.env.LOG_LEVEL === "debug";
|
|
101241
|
+
}
|
|
101242
|
+
var DEFAULT_ACTIVITY_TIMEOUT_MS = 3e5;
|
|
101243
|
+
var AGENT_ACTIVITY_TIMEOUT_MS = 9e5;
|
|
101244
|
+
var DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5e3;
|
|
101245
|
+
var DEBUG_TS_PREFIX = /^(?:\[\d{4}-\d{2}-\d{2}T[^\]]+\]\s+)?/.source;
|
|
101246
|
+
var ACTIVITY_NOISE_PATTERNS = [
|
|
101247
|
+
new RegExp(`${DEBUG_TS_PREFIX}\\[mcp-proxy\\]`),
|
|
101248
|
+
new RegExp(`${DEBUG_TS_PREFIX}\xBB provider error detected`),
|
|
101249
|
+
new RegExp(`${DEBUG_TS_PREFIX}\\[DEBUG\\]\\s+(?:spawn|process) activity `),
|
|
101250
|
+
/^::debug::(?:spawn|process) activity /
|
|
101251
|
+
];
|
|
101252
|
+
function isActivityNoise(chunk) {
|
|
101253
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
101254
|
+
if (!text.trim()) return true;
|
|
101255
|
+
return text.split("\n").every((line) => {
|
|
101256
|
+
const trimmed = line.trim();
|
|
101257
|
+
if (!trimmed) return true;
|
|
101258
|
+
return ACTIVITY_NOISE_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
101259
|
+
});
|
|
101260
|
+
}
|
|
101261
|
+
var _lastActivity = performance2.now();
|
|
101262
|
+
function markActivity() {
|
|
101263
|
+
_lastActivity = performance2.now();
|
|
101264
|
+
}
|
|
101265
|
+
function getIdleMs() {
|
|
101266
|
+
return Math.round(performance2.now() - _lastActivity);
|
|
101267
|
+
}
|
|
101268
|
+
function wrapWrite(original, onActivity) {
|
|
101269
|
+
const wrapped = (chunk, encodingOrCb, cb) => {
|
|
101270
|
+
if (!isActivityNoise(chunk)) {
|
|
101271
|
+
onActivity();
|
|
101272
|
+
}
|
|
101273
|
+
if (typeof encodingOrCb === "function") {
|
|
101274
|
+
return original(chunk, encodingOrCb);
|
|
101275
|
+
}
|
|
101276
|
+
return original(chunk, encodingOrCb, cb);
|
|
101277
|
+
};
|
|
101278
|
+
return wrapped;
|
|
101279
|
+
}
|
|
101280
|
+
function startProcessOutputMonitor(ctx) {
|
|
101281
|
+
let timedOut = false;
|
|
101282
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
101283
|
+
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
101284
|
+
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
|
|
101285
|
+
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
|
|
101286
|
+
const debugBypass = (msg) => {
|
|
101287
|
+
if (!isMonitorDebugEnabled()) return;
|
|
101288
|
+
originalStdoutWrite(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}
|
|
101289
|
+
`);
|
|
101290
|
+
};
|
|
101291
|
+
debugBypass(`process activity monitor started: timeout=${ctx.timeoutMs}ms`);
|
|
101292
|
+
const intervalId = setInterval(() => {
|
|
101293
|
+
const idleMs = getIdleMs();
|
|
101294
|
+
debugBypass(`process activity check: idle=${idleMs}ms / ${ctx.timeoutMs}ms`);
|
|
101295
|
+
if (timedOut || idleMs <= ctx.timeoutMs) return;
|
|
101296
|
+
timedOut = true;
|
|
101297
|
+
ctx.onTimeout(idleMs);
|
|
101298
|
+
}, ctx.checkIntervalMs);
|
|
101299
|
+
function stop() {
|
|
101300
|
+
clearInterval(intervalId);
|
|
101301
|
+
process.stdout.write = originalStdoutWrite;
|
|
101302
|
+
process.stderr.write = originalStderrWrite;
|
|
101303
|
+
}
|
|
101304
|
+
return { stop };
|
|
101305
|
+
}
|
|
101306
|
+
function createProcessOutputActivityTimeout(ctx) {
|
|
101307
|
+
markActivity();
|
|
101308
|
+
let rejectFn = null;
|
|
101309
|
+
const promise2 = new Promise((_2, reject) => {
|
|
101310
|
+
rejectFn = reject;
|
|
101311
|
+
});
|
|
101312
|
+
let monitor = null;
|
|
101313
|
+
monitor = startProcessOutputMonitor({
|
|
101314
|
+
timeoutMs: ctx.timeoutMs,
|
|
101315
|
+
checkIntervalMs: ctx.checkIntervalMs,
|
|
101316
|
+
onTimeout: (idleMs) => {
|
|
101317
|
+
if (!rejectFn) return;
|
|
101318
|
+
const idleSec = Math.round(idleMs / 1e3);
|
|
101319
|
+
if (monitor) {
|
|
101320
|
+
monitor.stop();
|
|
101321
|
+
}
|
|
101322
|
+
const reject = rejectFn;
|
|
101323
|
+
rejectFn = null;
|
|
101324
|
+
reject(new Error(`activity timeout: no output for ${idleSec}s`));
|
|
101325
|
+
}
|
|
101326
|
+
});
|
|
101327
|
+
return {
|
|
101328
|
+
promise: promise2,
|
|
101329
|
+
// stop() also disarms forceReject so a late safety-net fire can't reject
|
|
101330
|
+
// the promise after the run has already succeeded.
|
|
101331
|
+
stop: () => {
|
|
101332
|
+
monitor?.stop();
|
|
101333
|
+
rejectFn = null;
|
|
101334
|
+
},
|
|
101335
|
+
forceReject: (reason) => {
|
|
101336
|
+
if (!rejectFn) return;
|
|
101337
|
+
monitor?.stop();
|
|
101338
|
+
const reject = rejectFn;
|
|
101339
|
+
rejectFn = null;
|
|
101340
|
+
reject(new Error(reason));
|
|
101341
|
+
}
|
|
101342
|
+
};
|
|
101343
|
+
}
|
|
101238
101344
|
|
|
101239
101345
|
// utils/log.ts
|
|
101240
101346
|
var core = __toESM(require_core(), 1);
|
|
@@ -101550,137 +101656,6 @@ function formatUsageSummary(entries) {
|
|
|
101550
101656
|
].join("\n");
|
|
101551
101657
|
}
|
|
101552
101658
|
|
|
101553
|
-
// utils/activity.ts
|
|
101554
|
-
function isMonitorDebugEnabled() {
|
|
101555
|
-
return process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || process.env.LOG_LEVEL === "debug";
|
|
101556
|
-
}
|
|
101557
|
-
var DEFAULT_ACTIVITY_TIMEOUT_MS = 3e5;
|
|
101558
|
-
var DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5e3;
|
|
101559
|
-
var DEBUG_TS_PREFIX = /^(?:\[\d{4}-\d{2}-\d{2}T[^\]]+\]\s+)?/.source;
|
|
101560
|
-
var ACTIVITY_NOISE_PATTERNS = [
|
|
101561
|
-
new RegExp(`${DEBUG_TS_PREFIX}\\[mcp-proxy\\]`),
|
|
101562
|
-
new RegExp(`${DEBUG_TS_PREFIX}\xBB provider error detected`),
|
|
101563
|
-
new RegExp(`${DEBUG_TS_PREFIX}\\[DEBUG\\]\\s+(?:spawn|process) activity `),
|
|
101564
|
-
/^::debug::(?:spawn|process) activity /
|
|
101565
|
-
];
|
|
101566
|
-
function isActivityNoise(chunk) {
|
|
101567
|
-
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
101568
|
-
if (!text.trim()) return true;
|
|
101569
|
-
return text.split("\n").every((line) => {
|
|
101570
|
-
const trimmed = line.trim();
|
|
101571
|
-
if (!trimmed) return true;
|
|
101572
|
-
return ACTIVITY_NOISE_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
101573
|
-
});
|
|
101574
|
-
}
|
|
101575
|
-
var _lastActivity = performance2.now();
|
|
101576
|
-
var MAX_TOOL_CALL_SUSPENSION_MS = 15 * 60 * 1e3;
|
|
101577
|
-
var _suspendedAt = null;
|
|
101578
|
-
var _suspensionTimer = null;
|
|
101579
|
-
function markActivity() {
|
|
101580
|
-
_lastActivity = performance2.now();
|
|
101581
|
-
}
|
|
101582
|
-
function getIdleMs() {
|
|
101583
|
-
if (_suspendedAt !== null) return 0;
|
|
101584
|
-
return Math.round(performance2.now() - _lastActivity);
|
|
101585
|
-
}
|
|
101586
|
-
function suspendActivity(maxMs = MAX_TOOL_CALL_SUSPENSION_MS) {
|
|
101587
|
-
if (_suspendedAt !== null) return;
|
|
101588
|
-
_suspendedAt = performance2.now();
|
|
101589
|
-
_suspensionTimer = setTimeout(() => {
|
|
101590
|
-
log.warning(`activity watchdog suspended >${Math.round(maxMs / 1e3)}s \u2014 auto-resuming`);
|
|
101591
|
-
resumeActivity();
|
|
101592
|
-
}, maxMs);
|
|
101593
|
-
_suspensionTimer.unref?.();
|
|
101594
|
-
}
|
|
101595
|
-
function resumeActivity() {
|
|
101596
|
-
if (_suspendedAt === null) return;
|
|
101597
|
-
_suspendedAt = null;
|
|
101598
|
-
if (_suspensionTimer) {
|
|
101599
|
-
clearTimeout(_suspensionTimer);
|
|
101600
|
-
_suspensionTimer = null;
|
|
101601
|
-
}
|
|
101602
|
-
_lastActivity = performance2.now();
|
|
101603
|
-
}
|
|
101604
|
-
function isActivitySuspended() {
|
|
101605
|
-
return _suspendedAt !== null;
|
|
101606
|
-
}
|
|
101607
|
-
function wrapWrite(original, onActivity) {
|
|
101608
|
-
const wrapped = (chunk, encodingOrCb, cb) => {
|
|
101609
|
-
if (!isActivityNoise(chunk)) {
|
|
101610
|
-
onActivity();
|
|
101611
|
-
}
|
|
101612
|
-
if (typeof encodingOrCb === "function") {
|
|
101613
|
-
return original(chunk, encodingOrCb);
|
|
101614
|
-
}
|
|
101615
|
-
return original(chunk, encodingOrCb, cb);
|
|
101616
|
-
};
|
|
101617
|
-
return wrapped;
|
|
101618
|
-
}
|
|
101619
|
-
function startProcessOutputMonitor(ctx) {
|
|
101620
|
-
let timedOut = false;
|
|
101621
|
-
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
101622
|
-
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
101623
|
-
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
|
|
101624
|
-
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
|
|
101625
|
-
const debugBypass = (msg) => {
|
|
101626
|
-
if (!isMonitorDebugEnabled()) return;
|
|
101627
|
-
originalStdoutWrite(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}
|
|
101628
|
-
`);
|
|
101629
|
-
};
|
|
101630
|
-
debugBypass(`process activity monitor started: timeout=${ctx.timeoutMs}ms`);
|
|
101631
|
-
const intervalId = setInterval(() => {
|
|
101632
|
-
const idleMs = getIdleMs();
|
|
101633
|
-
debugBypass(`process activity check: idle=${idleMs}ms / ${ctx.timeoutMs}ms`);
|
|
101634
|
-
if (timedOut || idleMs <= ctx.timeoutMs) return;
|
|
101635
|
-
timedOut = true;
|
|
101636
|
-
ctx.onTimeout(idleMs);
|
|
101637
|
-
}, ctx.checkIntervalMs);
|
|
101638
|
-
function stop() {
|
|
101639
|
-
clearInterval(intervalId);
|
|
101640
|
-
process.stdout.write = originalStdoutWrite;
|
|
101641
|
-
process.stderr.write = originalStderrWrite;
|
|
101642
|
-
}
|
|
101643
|
-
return { stop };
|
|
101644
|
-
}
|
|
101645
|
-
function createProcessOutputActivityTimeout(ctx) {
|
|
101646
|
-
markActivity();
|
|
101647
|
-
let rejectFn = null;
|
|
101648
|
-
const promise2 = new Promise((_2, reject) => {
|
|
101649
|
-
rejectFn = reject;
|
|
101650
|
-
});
|
|
101651
|
-
let monitor = null;
|
|
101652
|
-
monitor = startProcessOutputMonitor({
|
|
101653
|
-
timeoutMs: ctx.timeoutMs,
|
|
101654
|
-
checkIntervalMs: ctx.checkIntervalMs,
|
|
101655
|
-
onTimeout: (idleMs) => {
|
|
101656
|
-
if (!rejectFn) return;
|
|
101657
|
-
const idleSec = Math.round(idleMs / 1e3);
|
|
101658
|
-
if (monitor) {
|
|
101659
|
-
monitor.stop();
|
|
101660
|
-
}
|
|
101661
|
-
const reject = rejectFn;
|
|
101662
|
-
rejectFn = null;
|
|
101663
|
-
reject(new Error(`activity timeout: no output for ${idleSec}s`));
|
|
101664
|
-
}
|
|
101665
|
-
});
|
|
101666
|
-
return {
|
|
101667
|
-
promise: promise2,
|
|
101668
|
-
// stop() also disarms forceReject so a late safety-net fire can't reject
|
|
101669
|
-
// the promise after the run has already succeeded.
|
|
101670
|
-
stop: () => {
|
|
101671
|
-
monitor?.stop();
|
|
101672
|
-
rejectFn = null;
|
|
101673
|
-
},
|
|
101674
|
-
forceReject: (reason) => {
|
|
101675
|
-
if (!rejectFn) return;
|
|
101676
|
-
monitor?.stop();
|
|
101677
|
-
const reject = rejectFn;
|
|
101678
|
-
rejectFn = null;
|
|
101679
|
-
reject(new Error(reason));
|
|
101680
|
-
}
|
|
101681
|
-
};
|
|
101682
|
-
}
|
|
101683
|
-
|
|
101684
101659
|
// utils/install.ts
|
|
101685
101660
|
import { spawnSync } from "node:child_process";
|
|
101686
101661
|
import { chmodSync, createWriteStream, existsSync as existsSync2, mkdirSync } from "node:fs";
|
|
@@ -101880,7 +101855,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
101880
101855
|
// package.json
|
|
101881
101856
|
var package_default = {
|
|
101882
101857
|
name: "pullfrog",
|
|
101883
|
-
version: "0.1.
|
|
101858
|
+
version: "0.1.21",
|
|
101884
101859
|
type: "module",
|
|
101885
101860
|
bin: {
|
|
101886
101861
|
pullfrog: "dist/cli.mjs",
|
|
@@ -102218,11 +102193,6 @@ async function spawn3(options) {
|
|
|
102218
102193
|
`spawn activity timer: pid=${child.pid} cmd=${options.cmd} timeout=${activityTimeoutMs}ms`
|
|
102219
102194
|
);
|
|
102220
102195
|
activityCheckIntervalId = setInterval(() => {
|
|
102221
|
-
if (options.isPausedExternally?.()) {
|
|
102222
|
-
lastActivityTime = performance3.now();
|
|
102223
|
-
log.debug(`spawn activity check: pid=${child.pid} paused externally`);
|
|
102224
|
-
return;
|
|
102225
|
-
}
|
|
102226
102196
|
const idleMs = performance3.now() - lastActivityTime;
|
|
102227
102197
|
log.debug(
|
|
102228
102198
|
`spawn activity check: pid=${child.pid} idle=${Math.round(idleMs)}ms / ${activityTimeoutMs}ms`
|
|
@@ -103690,7 +103660,6 @@ async function runClaude(params) {
|
|
|
103690
103660
|
}
|
|
103691
103661
|
} else if (block.type === "tool_use") {
|
|
103692
103662
|
const toolName = block.name || "unknown";
|
|
103693
|
-
suspendActivity();
|
|
103694
103663
|
if (params.onToolUse) {
|
|
103695
103664
|
params.onToolUse({
|
|
103696
103665
|
toolName,
|
|
@@ -103735,7 +103704,6 @@ async function runClaude(params) {
|
|
|
103735
103704
|
for (const block of content) {
|
|
103736
103705
|
if (typeof block === "string") continue;
|
|
103737
103706
|
if (block.type === "tool_result") {
|
|
103738
|
-
resumeActivity();
|
|
103739
103707
|
timerFor(label).markToolResult();
|
|
103740
103708
|
const outputContent = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map(
|
|
103741
103709
|
(entry) => typeof entry === "string" ? entry : typeof entry === "object" && entry !== null && "text" in entry ? String(entry.text) : JSON.stringify(entry)
|
|
@@ -103822,9 +103790,10 @@ async function runClaude(params) {
|
|
|
103822
103790
|
args: params.args,
|
|
103823
103791
|
cwd: params.cwd,
|
|
103824
103792
|
env: params.env,
|
|
103825
|
-
|
|
103793
|
+
// flat agent idle budget — long synchronous MCP tool calls (issue #760)
|
|
103794
|
+
// sit well under it, so no per-toolcall suspend bracketing is needed.
|
|
103795
|
+
activityTimeout: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
103826
103796
|
onActivityTimeout: params.onActivityTimeout,
|
|
103827
|
-
isPausedExternally: isActivitySuspended,
|
|
103828
103797
|
stdio: ["ignore", "pipe", "pipe"],
|
|
103829
103798
|
// run claude in its own process group so SIGKILL on activity timeout /
|
|
103830
103799
|
// outer cancellation reaches any subprocesses it spawns (rg, file
|
|
@@ -108179,13 +108148,6 @@ async function onToolPart(ctx, part, label, isOrchestrator) {
|
|
|
108179
108148
|
const status = part.state.status;
|
|
108180
108149
|
const toolName = part.tool;
|
|
108181
108150
|
const toolId = part.callID;
|
|
108182
|
-
if (toolName !== "task") {
|
|
108183
|
-
if (status === "completed" || status === "error") {
|
|
108184
|
-
resumeActivity();
|
|
108185
|
-
} else {
|
|
108186
|
-
suspendActivity();
|
|
108187
|
-
}
|
|
108188
|
-
}
|
|
108189
108151
|
if (toolName === "task" && status === "running" && isOrchestrator && !ctx.taskDispatchByCallID.has(toolId)) {
|
|
108190
108152
|
const input = part.state.input ?? {};
|
|
108191
108153
|
const dispatched = ctx.labeler.recordTaskDispatch(input);
|
|
@@ -108433,7 +108395,6 @@ function startInnerActivityWatchdog(params) {
|
|
|
108433
108395
|
let fired = false;
|
|
108434
108396
|
const id = setInterval(() => {
|
|
108435
108397
|
if (fired) return;
|
|
108436
|
-
if (isActivitySuspended()) return;
|
|
108437
108398
|
const idleMs = performance6.now() - params.ctx.lastEventAt;
|
|
108438
108399
|
if (idleMs <= params.timeoutMs) return;
|
|
108439
108400
|
fired = true;
|
|
@@ -108589,13 +108550,13 @@ var opencode = agent({
|
|
|
108589
108550
|
const watchdog = startInnerActivityWatchdog({
|
|
108590
108551
|
ctx: runnerCtx,
|
|
108591
108552
|
// model-stall budget: how long the orchestrator may stream NO progress
|
|
108592
|
-
// (no token/tool part.updated) before we tear the turn down.
|
|
108593
|
-
//
|
|
108594
|
-
//
|
|
108595
|
-
//
|
|
108596
|
-
//
|
|
108597
|
-
//
|
|
108598
|
-
timeoutMs:
|
|
108553
|
+
// (no token/tool part.updated) before we tear the turn down. opencode's
|
|
108554
|
+
// keepalive/lifecycle events keep the outer process-output monitor
|
|
108555
|
+
// alive even while the model is silent, so this inner timer is the only
|
|
108556
|
+
// stall detector for the v2 SSE path. it shares the flat idle budget so
|
|
108557
|
+
// a long synchronous tool call (no part.updated while it runs) can't
|
|
108558
|
+
// false-positive it.
|
|
108559
|
+
timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
108599
108560
|
abortController
|
|
108600
108561
|
});
|
|
108601
108562
|
const sdkModel = parseModel2(model);
|
|
@@ -161974,7 +161935,7 @@ ${instructions.user}` : null,
|
|
|
161974
161935
|
}
|
|
161975
161936
|
}
|
|
161976
161937
|
activityTimeout = createProcessOutputActivityTimeout({
|
|
161977
|
-
timeoutMs:
|
|
161938
|
+
timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
161978
161939
|
checkIntervalMs: DEFAULT_ACTIVITY_CHECK_INTERVAL_MS
|
|
161979
161940
|
});
|
|
161980
161941
|
activityTimeout.promise.catch(() => {
|
|
@@ -163019,7 +162980,7 @@ async function run2() {
|
|
|
163019
162980
|
}
|
|
163020
162981
|
|
|
163021
162982
|
// cli.ts
|
|
163022
|
-
var VERSION10 = "0.1.
|
|
162983
|
+
var VERSION10 = "0.1.21";
|
|
163023
162984
|
var bin = basename2(process.argv[1] || "");
|
|
163024
162985
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
163025
162986
|
var rawArgs = process.argv.slice(2);
|
package/dist/index.js
CHANGED
|
@@ -99389,11 +99389,12 @@ var modelAliases = Object.entries(providers).flatMap(
|
|
|
99389
99389
|
hidden: def.hidden ?? false
|
|
99390
99390
|
}))
|
|
99391
99391
|
);
|
|
99392
|
-
var defaultProxyAlias = modelAliases.find((a) => a.slug === "
|
|
99392
|
+
var defaultProxyAlias = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro");
|
|
99393
99393
|
if (!defaultProxyAlias?.openRouterResolve) {
|
|
99394
|
-
throw new Error("DEFAULT_PROXY_MODEL:
|
|
99394
|
+
throw new Error("DEFAULT_PROXY_MODEL: deepseek/deepseek-pro missing openRouterResolve");
|
|
99395
99395
|
}
|
|
99396
99396
|
var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
|
|
99397
|
+
var defaultProxyDisplayName = defaultProxyAlias.displayName;
|
|
99397
99398
|
var MAX_FALLBACK_DEPTH = 10;
|
|
99398
99399
|
function resolveDisplayAlias(slug2) {
|
|
99399
99400
|
let current = slug2;
|
|
@@ -99435,6 +99436,111 @@ function formatMcpToolRef(agentId, toolName) {
|
|
|
99435
99436
|
|
|
99436
99437
|
// utils/activity.ts
|
|
99437
99438
|
import { performance as performance2 } from "node:perf_hooks";
|
|
99439
|
+
function isMonitorDebugEnabled() {
|
|
99440
|
+
return process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || process.env.LOG_LEVEL === "debug";
|
|
99441
|
+
}
|
|
99442
|
+
var DEFAULT_ACTIVITY_TIMEOUT_MS = 3e5;
|
|
99443
|
+
var AGENT_ACTIVITY_TIMEOUT_MS = 9e5;
|
|
99444
|
+
var DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5e3;
|
|
99445
|
+
var DEBUG_TS_PREFIX = /^(?:\[\d{4}-\d{2}-\d{2}T[^\]]+\]\s+)?/.source;
|
|
99446
|
+
var ACTIVITY_NOISE_PATTERNS = [
|
|
99447
|
+
new RegExp(`${DEBUG_TS_PREFIX}\\[mcp-proxy\\]`),
|
|
99448
|
+
new RegExp(`${DEBUG_TS_PREFIX}\xBB provider error detected`),
|
|
99449
|
+
new RegExp(`${DEBUG_TS_PREFIX}\\[DEBUG\\]\\s+(?:spawn|process) activity `),
|
|
99450
|
+
/^::debug::(?:spawn|process) activity /
|
|
99451
|
+
];
|
|
99452
|
+
function isActivityNoise(chunk) {
|
|
99453
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
99454
|
+
if (!text.trim()) return true;
|
|
99455
|
+
return text.split("\n").every((line) => {
|
|
99456
|
+
const trimmed = line.trim();
|
|
99457
|
+
if (!trimmed) return true;
|
|
99458
|
+
return ACTIVITY_NOISE_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
99459
|
+
});
|
|
99460
|
+
}
|
|
99461
|
+
var _lastActivity = performance2.now();
|
|
99462
|
+
function markActivity() {
|
|
99463
|
+
_lastActivity = performance2.now();
|
|
99464
|
+
}
|
|
99465
|
+
function getIdleMs() {
|
|
99466
|
+
return Math.round(performance2.now() - _lastActivity);
|
|
99467
|
+
}
|
|
99468
|
+
function wrapWrite(original, onActivity) {
|
|
99469
|
+
const wrapped = (chunk, encodingOrCb, cb) => {
|
|
99470
|
+
if (!isActivityNoise(chunk)) {
|
|
99471
|
+
onActivity();
|
|
99472
|
+
}
|
|
99473
|
+
if (typeof encodingOrCb === "function") {
|
|
99474
|
+
return original(chunk, encodingOrCb);
|
|
99475
|
+
}
|
|
99476
|
+
return original(chunk, encodingOrCb, cb);
|
|
99477
|
+
};
|
|
99478
|
+
return wrapped;
|
|
99479
|
+
}
|
|
99480
|
+
function startProcessOutputMonitor(ctx) {
|
|
99481
|
+
let timedOut = false;
|
|
99482
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
99483
|
+
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
99484
|
+
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
|
|
99485
|
+
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
|
|
99486
|
+
const debugBypass = (msg) => {
|
|
99487
|
+
if (!isMonitorDebugEnabled()) return;
|
|
99488
|
+
originalStdoutWrite(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}
|
|
99489
|
+
`);
|
|
99490
|
+
};
|
|
99491
|
+
debugBypass(`process activity monitor started: timeout=${ctx.timeoutMs}ms`);
|
|
99492
|
+
const intervalId = setInterval(() => {
|
|
99493
|
+
const idleMs = getIdleMs();
|
|
99494
|
+
debugBypass(`process activity check: idle=${idleMs}ms / ${ctx.timeoutMs}ms`);
|
|
99495
|
+
if (timedOut || idleMs <= ctx.timeoutMs) return;
|
|
99496
|
+
timedOut = true;
|
|
99497
|
+
ctx.onTimeout(idleMs);
|
|
99498
|
+
}, ctx.checkIntervalMs);
|
|
99499
|
+
function stop() {
|
|
99500
|
+
clearInterval(intervalId);
|
|
99501
|
+
process.stdout.write = originalStdoutWrite;
|
|
99502
|
+
process.stderr.write = originalStderrWrite;
|
|
99503
|
+
}
|
|
99504
|
+
return { stop };
|
|
99505
|
+
}
|
|
99506
|
+
function createProcessOutputActivityTimeout(ctx) {
|
|
99507
|
+
markActivity();
|
|
99508
|
+
let rejectFn = null;
|
|
99509
|
+
const promise2 = new Promise((_, reject) => {
|
|
99510
|
+
rejectFn = reject;
|
|
99511
|
+
});
|
|
99512
|
+
let monitor = null;
|
|
99513
|
+
monitor = startProcessOutputMonitor({
|
|
99514
|
+
timeoutMs: ctx.timeoutMs,
|
|
99515
|
+
checkIntervalMs: ctx.checkIntervalMs,
|
|
99516
|
+
onTimeout: (idleMs) => {
|
|
99517
|
+
if (!rejectFn) return;
|
|
99518
|
+
const idleSec = Math.round(idleMs / 1e3);
|
|
99519
|
+
if (monitor) {
|
|
99520
|
+
monitor.stop();
|
|
99521
|
+
}
|
|
99522
|
+
const reject = rejectFn;
|
|
99523
|
+
rejectFn = null;
|
|
99524
|
+
reject(new Error(`activity timeout: no output for ${idleSec}s`));
|
|
99525
|
+
}
|
|
99526
|
+
});
|
|
99527
|
+
return {
|
|
99528
|
+
promise: promise2,
|
|
99529
|
+
// stop() also disarms forceReject so a late safety-net fire can't reject
|
|
99530
|
+
// the promise after the run has already succeeded.
|
|
99531
|
+
stop: () => {
|
|
99532
|
+
monitor?.stop();
|
|
99533
|
+
rejectFn = null;
|
|
99534
|
+
},
|
|
99535
|
+
forceReject: (reason) => {
|
|
99536
|
+
if (!rejectFn) return;
|
|
99537
|
+
monitor?.stop();
|
|
99538
|
+
const reject = rejectFn;
|
|
99539
|
+
rejectFn = null;
|
|
99540
|
+
reject(new Error(reason));
|
|
99541
|
+
}
|
|
99542
|
+
};
|
|
99543
|
+
}
|
|
99438
99544
|
|
|
99439
99545
|
// utils/log.ts
|
|
99440
99546
|
var core = __toESM(require_core(), 1);
|
|
@@ -99750,137 +99856,6 @@ function formatUsageSummary(entries) {
|
|
|
99750
99856
|
].join("\n");
|
|
99751
99857
|
}
|
|
99752
99858
|
|
|
99753
|
-
// utils/activity.ts
|
|
99754
|
-
function isMonitorDebugEnabled() {
|
|
99755
|
-
return process.env.ACTIONS_STEP_DEBUG === "true" || process.env.RUNNER_DEBUG === "1" || process.env.LOG_LEVEL === "debug";
|
|
99756
|
-
}
|
|
99757
|
-
var DEFAULT_ACTIVITY_TIMEOUT_MS = 3e5;
|
|
99758
|
-
var DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5e3;
|
|
99759
|
-
var DEBUG_TS_PREFIX = /^(?:\[\d{4}-\d{2}-\d{2}T[^\]]+\]\s+)?/.source;
|
|
99760
|
-
var ACTIVITY_NOISE_PATTERNS = [
|
|
99761
|
-
new RegExp(`${DEBUG_TS_PREFIX}\\[mcp-proxy\\]`),
|
|
99762
|
-
new RegExp(`${DEBUG_TS_PREFIX}\xBB provider error detected`),
|
|
99763
|
-
new RegExp(`${DEBUG_TS_PREFIX}\\[DEBUG\\]\\s+(?:spawn|process) activity `),
|
|
99764
|
-
/^::debug::(?:spawn|process) activity /
|
|
99765
|
-
];
|
|
99766
|
-
function isActivityNoise(chunk) {
|
|
99767
|
-
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
99768
|
-
if (!text.trim()) return true;
|
|
99769
|
-
return text.split("\n").every((line) => {
|
|
99770
|
-
const trimmed = line.trim();
|
|
99771
|
-
if (!trimmed) return true;
|
|
99772
|
-
return ACTIVITY_NOISE_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
99773
|
-
});
|
|
99774
|
-
}
|
|
99775
|
-
var _lastActivity = performance2.now();
|
|
99776
|
-
var MAX_TOOL_CALL_SUSPENSION_MS = 15 * 60 * 1e3;
|
|
99777
|
-
var _suspendedAt = null;
|
|
99778
|
-
var _suspensionTimer = null;
|
|
99779
|
-
function markActivity() {
|
|
99780
|
-
_lastActivity = performance2.now();
|
|
99781
|
-
}
|
|
99782
|
-
function getIdleMs() {
|
|
99783
|
-
if (_suspendedAt !== null) return 0;
|
|
99784
|
-
return Math.round(performance2.now() - _lastActivity);
|
|
99785
|
-
}
|
|
99786
|
-
function suspendActivity(maxMs = MAX_TOOL_CALL_SUSPENSION_MS) {
|
|
99787
|
-
if (_suspendedAt !== null) return;
|
|
99788
|
-
_suspendedAt = performance2.now();
|
|
99789
|
-
_suspensionTimer = setTimeout(() => {
|
|
99790
|
-
log.warning(`activity watchdog suspended >${Math.round(maxMs / 1e3)}s \u2014 auto-resuming`);
|
|
99791
|
-
resumeActivity();
|
|
99792
|
-
}, maxMs);
|
|
99793
|
-
_suspensionTimer.unref?.();
|
|
99794
|
-
}
|
|
99795
|
-
function resumeActivity() {
|
|
99796
|
-
if (_suspendedAt === null) return;
|
|
99797
|
-
_suspendedAt = null;
|
|
99798
|
-
if (_suspensionTimer) {
|
|
99799
|
-
clearTimeout(_suspensionTimer);
|
|
99800
|
-
_suspensionTimer = null;
|
|
99801
|
-
}
|
|
99802
|
-
_lastActivity = performance2.now();
|
|
99803
|
-
}
|
|
99804
|
-
function isActivitySuspended() {
|
|
99805
|
-
return _suspendedAt !== null;
|
|
99806
|
-
}
|
|
99807
|
-
function wrapWrite(original, onActivity) {
|
|
99808
|
-
const wrapped = (chunk, encodingOrCb, cb) => {
|
|
99809
|
-
if (!isActivityNoise(chunk)) {
|
|
99810
|
-
onActivity();
|
|
99811
|
-
}
|
|
99812
|
-
if (typeof encodingOrCb === "function") {
|
|
99813
|
-
return original(chunk, encodingOrCb);
|
|
99814
|
-
}
|
|
99815
|
-
return original(chunk, encodingOrCb, cb);
|
|
99816
|
-
};
|
|
99817
|
-
return wrapped;
|
|
99818
|
-
}
|
|
99819
|
-
function startProcessOutputMonitor(ctx) {
|
|
99820
|
-
let timedOut = false;
|
|
99821
|
-
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
99822
|
-
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
99823
|
-
process.stdout.write = wrapWrite(originalStdoutWrite, markActivity);
|
|
99824
|
-
process.stderr.write = wrapWrite(originalStderrWrite, markActivity);
|
|
99825
|
-
const debugBypass = (msg) => {
|
|
99826
|
-
if (!isMonitorDebugEnabled()) return;
|
|
99827
|
-
originalStdoutWrite(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] ${msg}
|
|
99828
|
-
`);
|
|
99829
|
-
};
|
|
99830
|
-
debugBypass(`process activity monitor started: timeout=${ctx.timeoutMs}ms`);
|
|
99831
|
-
const intervalId = setInterval(() => {
|
|
99832
|
-
const idleMs = getIdleMs();
|
|
99833
|
-
debugBypass(`process activity check: idle=${idleMs}ms / ${ctx.timeoutMs}ms`);
|
|
99834
|
-
if (timedOut || idleMs <= ctx.timeoutMs) return;
|
|
99835
|
-
timedOut = true;
|
|
99836
|
-
ctx.onTimeout(idleMs);
|
|
99837
|
-
}, ctx.checkIntervalMs);
|
|
99838
|
-
function stop() {
|
|
99839
|
-
clearInterval(intervalId);
|
|
99840
|
-
process.stdout.write = originalStdoutWrite;
|
|
99841
|
-
process.stderr.write = originalStderrWrite;
|
|
99842
|
-
}
|
|
99843
|
-
return { stop };
|
|
99844
|
-
}
|
|
99845
|
-
function createProcessOutputActivityTimeout(ctx) {
|
|
99846
|
-
markActivity();
|
|
99847
|
-
let rejectFn = null;
|
|
99848
|
-
const promise2 = new Promise((_, reject) => {
|
|
99849
|
-
rejectFn = reject;
|
|
99850
|
-
});
|
|
99851
|
-
let monitor = null;
|
|
99852
|
-
monitor = startProcessOutputMonitor({
|
|
99853
|
-
timeoutMs: ctx.timeoutMs,
|
|
99854
|
-
checkIntervalMs: ctx.checkIntervalMs,
|
|
99855
|
-
onTimeout: (idleMs) => {
|
|
99856
|
-
if (!rejectFn) return;
|
|
99857
|
-
const idleSec = Math.round(idleMs / 1e3);
|
|
99858
|
-
if (monitor) {
|
|
99859
|
-
monitor.stop();
|
|
99860
|
-
}
|
|
99861
|
-
const reject = rejectFn;
|
|
99862
|
-
rejectFn = null;
|
|
99863
|
-
reject(new Error(`activity timeout: no output for ${idleSec}s`));
|
|
99864
|
-
}
|
|
99865
|
-
});
|
|
99866
|
-
return {
|
|
99867
|
-
promise: promise2,
|
|
99868
|
-
// stop() also disarms forceReject so a late safety-net fire can't reject
|
|
99869
|
-
// the promise after the run has already succeeded.
|
|
99870
|
-
stop: () => {
|
|
99871
|
-
monitor?.stop();
|
|
99872
|
-
rejectFn = null;
|
|
99873
|
-
},
|
|
99874
|
-
forceReject: (reason) => {
|
|
99875
|
-
if (!rejectFn) return;
|
|
99876
|
-
monitor?.stop();
|
|
99877
|
-
const reject = rejectFn;
|
|
99878
|
-
rejectFn = null;
|
|
99879
|
-
reject(new Error(reason));
|
|
99880
|
-
}
|
|
99881
|
-
};
|
|
99882
|
-
}
|
|
99883
|
-
|
|
99884
99859
|
// utils/install.ts
|
|
99885
99860
|
import { spawnSync } from "node:child_process";
|
|
99886
99861
|
import { chmodSync, createWriteStream, existsSync as existsSync2, mkdirSync } from "node:fs";
|
|
@@ -100080,7 +100055,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
100080
100055
|
// package.json
|
|
100081
100056
|
var package_default = {
|
|
100082
100057
|
name: "pullfrog",
|
|
100083
|
-
version: "0.1.
|
|
100058
|
+
version: "0.1.21",
|
|
100084
100059
|
type: "module",
|
|
100085
100060
|
bin: {
|
|
100086
100061
|
pullfrog: "dist/cli.mjs",
|
|
@@ -100418,11 +100393,6 @@ async function spawn(options) {
|
|
|
100418
100393
|
`spawn activity timer: pid=${child.pid} cmd=${options.cmd} timeout=${activityTimeoutMs}ms`
|
|
100419
100394
|
);
|
|
100420
100395
|
activityCheckIntervalId = setInterval(() => {
|
|
100421
|
-
if (options.isPausedExternally?.()) {
|
|
100422
|
-
lastActivityTime = performance3.now();
|
|
100423
|
-
log.debug(`spawn activity check: pid=${child.pid} paused externally`);
|
|
100424
|
-
return;
|
|
100425
|
-
}
|
|
100426
100396
|
const idleMs = performance3.now() - lastActivityTime;
|
|
100427
100397
|
log.debug(
|
|
100428
100398
|
`spawn activity check: pid=${child.pid} idle=${Math.round(idleMs)}ms / ${activityTimeoutMs}ms`
|
|
@@ -101890,7 +101860,6 @@ async function runClaude(params) {
|
|
|
101890
101860
|
}
|
|
101891
101861
|
} else if (block.type === "tool_use") {
|
|
101892
101862
|
const toolName = block.name || "unknown";
|
|
101893
|
-
suspendActivity();
|
|
101894
101863
|
if (params.onToolUse) {
|
|
101895
101864
|
params.onToolUse({
|
|
101896
101865
|
toolName,
|
|
@@ -101935,7 +101904,6 @@ async function runClaude(params) {
|
|
|
101935
101904
|
for (const block of content) {
|
|
101936
101905
|
if (typeof block === "string") continue;
|
|
101937
101906
|
if (block.type === "tool_result") {
|
|
101938
|
-
resumeActivity();
|
|
101939
101907
|
timerFor(label).markToolResult();
|
|
101940
101908
|
const outputContent = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map(
|
|
101941
101909
|
(entry) => typeof entry === "string" ? entry : typeof entry === "object" && entry !== null && "text" in entry ? String(entry.text) : JSON.stringify(entry)
|
|
@@ -102022,9 +101990,10 @@ async function runClaude(params) {
|
|
|
102022
101990
|
args: params.args,
|
|
102023
101991
|
cwd: params.cwd,
|
|
102024
101992
|
env: params.env,
|
|
102025
|
-
|
|
101993
|
+
// flat agent idle budget — long synchronous MCP tool calls (issue #760)
|
|
101994
|
+
// sit well under it, so no per-toolcall suspend bracketing is needed.
|
|
101995
|
+
activityTimeout: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
102026
101996
|
onActivityTimeout: params.onActivityTimeout,
|
|
102027
|
-
isPausedExternally: isActivitySuspended,
|
|
102028
101997
|
stdio: ["ignore", "pipe", "pipe"],
|
|
102029
101998
|
// run claude in its own process group so SIGKILL on activity timeout /
|
|
102030
101999
|
// outer cancellation reaches any subprocesses it spawns (rg, file
|
|
@@ -106421,13 +106390,6 @@ async function onToolPart(ctx, part, label, isOrchestrator) {
|
|
|
106421
106390
|
const status = part.state.status;
|
|
106422
106391
|
const toolName = part.tool;
|
|
106423
106392
|
const toolId = part.callID;
|
|
106424
|
-
if (toolName !== "task") {
|
|
106425
|
-
if (status === "completed" || status === "error") {
|
|
106426
|
-
resumeActivity();
|
|
106427
|
-
} else {
|
|
106428
|
-
suspendActivity();
|
|
106429
|
-
}
|
|
106430
|
-
}
|
|
106431
106393
|
if (toolName === "task" && status === "running" && isOrchestrator && !ctx.taskDispatchByCallID.has(toolId)) {
|
|
106432
106394
|
const input = part.state.input ?? {};
|
|
106433
106395
|
const dispatched = ctx.labeler.recordTaskDispatch(input);
|
|
@@ -106675,7 +106637,6 @@ function startInnerActivityWatchdog(params) {
|
|
|
106675
106637
|
let fired = false;
|
|
106676
106638
|
const id = setInterval(() => {
|
|
106677
106639
|
if (fired) return;
|
|
106678
|
-
if (isActivitySuspended()) return;
|
|
106679
106640
|
const idleMs = performance6.now() - params.ctx.lastEventAt;
|
|
106680
106641
|
if (idleMs <= params.timeoutMs) return;
|
|
106681
106642
|
fired = true;
|
|
@@ -106831,13 +106792,13 @@ var opencode = agent({
|
|
|
106831
106792
|
const watchdog = startInnerActivityWatchdog({
|
|
106832
106793
|
ctx: runnerCtx,
|
|
106833
106794
|
// model-stall budget: how long the orchestrator may stream NO progress
|
|
106834
|
-
// (no token/tool part.updated) before we tear the turn down.
|
|
106835
|
-
//
|
|
106836
|
-
//
|
|
106837
|
-
//
|
|
106838
|
-
//
|
|
106839
|
-
//
|
|
106840
|
-
timeoutMs:
|
|
106795
|
+
// (no token/tool part.updated) before we tear the turn down. opencode's
|
|
106796
|
+
// keepalive/lifecycle events keep the outer process-output monitor
|
|
106797
|
+
// alive even while the model is silent, so this inner timer is the only
|
|
106798
|
+
// stall detector for the v2 SSE path. it shares the flat idle budget so
|
|
106799
|
+
// a long synchronous tool call (no part.updated while it runs) can't
|
|
106800
|
+
// false-positive it.
|
|
106801
|
+
timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
106841
106802
|
abortController
|
|
106842
106803
|
});
|
|
106843
106804
|
const sdkModel = parseModel2(model);
|
|
@@ -160216,7 +160177,7 @@ ${instructions.user}` : null,
|
|
|
160216
160177
|
}
|
|
160217
160178
|
}
|
|
160218
160179
|
activityTimeout = createProcessOutputActivityTimeout({
|
|
160219
|
-
timeoutMs:
|
|
160180
|
+
timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
160220
160181
|
checkIntervalMs: DEFAULT_ACTIVITY_CHECK_INTERVAL_MS
|
|
160221
160182
|
});
|
|
160222
160183
|
activityTimeout.promise.catch(() => {
|
package/dist/internal.js
CHANGED
|
@@ -476,20 +476,14 @@ var modelAliases = Object.entries(providers).flatMap(
|
|
|
476
476
|
hidden: def.hidden ?? false
|
|
477
477
|
}))
|
|
478
478
|
);
|
|
479
|
-
var defaultProxyAlias = modelAliases.find((a) => a.slug === "
|
|
479
|
+
var defaultProxyAlias = modelAliases.find((a) => a.slug === "deepseek/deepseek-pro");
|
|
480
480
|
if (!defaultProxyAlias?.openRouterResolve) {
|
|
481
|
-
throw new Error("DEFAULT_PROXY_MODEL:
|
|
481
|
+
throw new Error("DEFAULT_PROXY_MODEL: deepseek/deepseek-pro missing openRouterResolve");
|
|
482
482
|
}
|
|
483
483
|
var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
|
|
484
|
+
var defaultProxyDisplayName = defaultProxyAlias.displayName;
|
|
484
485
|
function getAutoSelectHintModel() {
|
|
485
|
-
|
|
486
|
-
if (!alias) return "Kimi 2.6";
|
|
487
|
-
const modelId = alias.resolve.split("/")[1] ?? "kimi-k2.6";
|
|
488
|
-
const version = modelId.replace(/^kimi-k2\./, "");
|
|
489
|
-
if (version && version !== modelId) {
|
|
490
|
-
return `Kimi 2.${version}`;
|
|
491
|
-
}
|
|
492
|
-
return alias.displayName;
|
|
486
|
+
return defaultProxyDisplayName;
|
|
493
487
|
}
|
|
494
488
|
function resolveModelSlug(slug) {
|
|
495
489
|
return modelAliases.find((a) => a.slug === slug)?.resolve;
|
package/dist/utils/activity.d.ts
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generic `spawn()` idle default for ordinary short-lived subprocesses (prep
|
|
3
|
+
* probes, package-manager invocations, dependency installs). these should be
|
|
4
|
+
* producing output steadily, so a comparatively tight budget catches a wedged
|
|
5
|
+
* command promptly. the long-silent-tool tolerance the agent harnesses need
|
|
6
|
+
* lives in AGENT_ACTIVITY_TIMEOUT_MS, applied explicitly at those sites.
|
|
7
|
+
*/
|
|
1
8
|
export declare const DEFAULT_ACTIVITY_TIMEOUT_MS = 300000;
|
|
9
|
+
/**
|
|
10
|
+
* flat idle budget for the agent activity watchdog (the outer process-output
|
|
11
|
+
* monitor, the v1 harness spawns, and the v2 inner event-silence watchdog).
|
|
12
|
+
* sized to exceed the worst-case legitimate silent tool window (issue #760:
|
|
13
|
+
* `checkout_pr` git fetch+deepen on a large monorepo, ~4-5min) with generous
|
|
14
|
+
* headroom, so no single in-flight tool call can be mistaken for a stall. a
|
|
15
|
+
* timeout this generous needs no suspend/resume bracketing — the cost of a
|
|
16
|
+
* genuinely hung run is only GitHub Actions minutes, not tokens.
|
|
17
|
+
*/
|
|
18
|
+
export declare const AGENT_ACTIVITY_TIMEOUT_MS = 900000;
|
|
2
19
|
export declare const DEFAULT_ACTIVITY_CHECK_INTERVAL_MS = 5000;
|
|
3
20
|
export declare const ACTIVITY_NOISE_PATTERNS: readonly RegExp[];
|
|
4
21
|
export declare function isActivityNoise(chunk: string | Uint8Array): boolean;
|
|
@@ -12,44 +29,12 @@ export type ActivityTimeout = {
|
|
|
12
29
|
/** force the timeout to reject immediately with a custom reason */
|
|
13
30
|
forceReject: (reason: string) => void;
|
|
14
31
|
};
|
|
15
|
-
/**
|
|
16
|
-
* upper bound on how long a single tool call can suspend the activity
|
|
17
|
-
* watchdog. matched against the typical worst-case `checkout_pr`
|
|
18
|
-
* fetch+deepen on a large monorepo (issue #760: 4-5min) plus generous
|
|
19
|
-
* headroom for slower MCP tools, while still bounding the worst case if
|
|
20
|
-
* a tool genuinely hangs and `tool_result` never arrives — auto-resume
|
|
21
|
-
* fires here and the normal idle clock takes over from a fresh baseline.
|
|
22
|
-
*/
|
|
23
|
-
export declare const MAX_TOOL_CALL_SUSPENSION_MS: number;
|
|
24
32
|
/**
|
|
25
33
|
* mark activity to reset the no-output timeout.
|
|
26
34
|
* call this whenever the agent emits any event, even if it isn't logged to stdout.
|
|
27
35
|
*/
|
|
28
36
|
export declare function markActivity(): void;
|
|
29
|
-
/**
|
|
30
|
-
* get the time since last activity in milliseconds.
|
|
31
|
-
* returns 0 while the watchdog is suspended (issue #760).
|
|
32
|
-
*/
|
|
37
|
+
/** get the time since last activity in milliseconds. */
|
|
33
38
|
export declare function getIdleMs(): number;
|
|
34
|
-
/**
|
|
35
|
-
* suspend the activity watchdog while a long-running, in-flight unit of
|
|
36
|
-
* work is happening (e.g. an MCP `tools/call` that synchronously awaits
|
|
37
|
-
* a multi-minute git fetch). bracket calls with `resumeActivity()` from
|
|
38
|
-
* the agent harness's `tool_use` / `tool_result` event handlers.
|
|
39
|
-
*
|
|
40
|
-
* - idempotent: nested suspends are no-ops; the first resume wins.
|
|
41
|
-
* - bounded: auto-resumes after `maxMs` so a buggy tool that never
|
|
42
|
-
* produces a `tool_result` can't pin the watchdog open forever.
|
|
43
|
-
* - safe: only the *agent harness* (claude.ts / opencode.ts) on explicit,
|
|
44
|
-
* paired CLI events should call this. NEVER blanket-suspend on internal
|
|
45
|
-
* noise — that would resurrect issue #12 zombie runs.
|
|
46
|
-
*/
|
|
47
|
-
export declare function suspendActivity(maxMs?: number): void;
|
|
48
|
-
/**
|
|
49
|
-
* resume the activity watchdog. resets the idle baseline so a stale
|
|
50
|
-
* idle window before the suspend can't immediately re-fire.
|
|
51
|
-
*/
|
|
52
|
-
export declare function resumeActivity(): void;
|
|
53
|
-
export declare function isActivitySuspended(): boolean;
|
|
54
39
|
export declare function createProcessOutputActivityTimeout(ctx: ActivityTimeoutContext): ActivityTimeout;
|
|
55
40
|
export {};
|
|
@@ -43,7 +43,6 @@ export interface SpawnOptions {
|
|
|
43
43
|
timeout?: number;
|
|
44
44
|
activityTimeout?: number;
|
|
45
45
|
onActivityTimeout?: (() => void) | undefined;
|
|
46
|
-
isPausedExternally?: () => boolean;
|
|
47
46
|
cwd?: string;
|
|
48
47
|
stdio?: ("pipe" | "ignore" | "inherit")[];
|
|
49
48
|
onStdout?: (chunk: string) => void;
|