@cydm/pie 2.1.1 → 2.2.0
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/builtin/extensions/ask-user/index.js +1 -1
- package/dist/builtin/extensions/computer-use/index.js +36 -15
- package/dist/builtin/extensions/mcp-adapter/index.js +58 -13
- package/dist/builtin/extensions/plan-mode/index.js +1 -1
- package/dist/builtin/extensions/subagent/index.js +2 -2
- package/dist/builtin/extensions/todo/index.js +1 -1
- package/dist/builtin/skills/tui-use/tui-use-cli.cjs +18 -0
- package/dist/builtin/skills/tui-use/tui-use-daemon.cjs +14 -1
- package/dist/chunks/{chunk-TJ2F4FL5.js → chunk-G3SE3I2L.js} +1 -1
- package/dist/chunks/{chunk-LU7RKALH.js → chunk-HH2Q2SNX.js} +3 -2
- package/dist/cli.js +57 -27
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createAskUserCapability
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-HH2Q2SNX.js";
|
|
5
5
|
import "../../../chunks/chunk-QJH6YN2W.js";
|
|
6
6
|
import "../../../chunks/chunk-IM43UYVV.js";
|
|
7
7
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
@@ -6901,17 +6901,28 @@ async function releaseOwnedBrowser(child, port, profile) {
|
|
|
6901
6901
|
if (port) await requestBrowserClose(port).catch(() => void 0);
|
|
6902
6902
|
if (!await waitForExit(child, 700)) {
|
|
6903
6903
|
if (process.platform === "win32" && child.pid) {
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
})
|
|
6904
|
+
const pid = child.pid;
|
|
6905
|
+
await new Promise((resolve) => {
|
|
6906
|
+
execFile("taskkill.exe", ["/PID", String(pid), "/T", "/F"], {
|
|
6907
|
+
windowsHide: true,
|
|
6908
|
+
timeout: 2e3
|
|
6909
|
+
}, () => resolve());
|
|
6910
|
+
});
|
|
6911
|
+
if (!await waitForExit(child, 1500)) {
|
|
6912
|
+
try {
|
|
6913
|
+
process.kill(pid);
|
|
6914
|
+
} catch {
|
|
6915
|
+
}
|
|
6916
|
+
if (!await waitForExit(child, 2e3)) {
|
|
6917
|
+
throw new Error(`Owned browser process ${pid} survived taskkill escalation.`);
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6911
6920
|
} else child.kill("SIGTERM");
|
|
6912
|
-
if (
|
|
6913
|
-
if (
|
|
6914
|
-
|
|
6921
|
+
if (process.platform !== "win32") {
|
|
6922
|
+
if (!await waitForExit(child, 2e3)) {
|
|
6923
|
+
child.kill("SIGKILL");
|
|
6924
|
+
if (!await waitForExit(child, 2e3)) throw new Error("Owned browser did not exit.");
|
|
6925
|
+
}
|
|
6915
6926
|
}
|
|
6916
6927
|
}
|
|
6917
6928
|
}
|
|
@@ -7206,16 +7217,24 @@ function shutdownComputerUseSession() {
|
|
|
7206
7217
|
}
|
|
7207
7218
|
async function releaseComputerUseSession() {
|
|
7208
7219
|
const drain = resourceScheduler.close();
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7220
|
+
const failures = [];
|
|
7221
|
+
const attempt = (step, work) => work().catch((error) => {
|
|
7222
|
+
failures.push(error instanceof Error ? new Error(`${step}: ${error.message}`) : error);
|
|
7223
|
+
});
|
|
7224
|
+
await attempt("disconnect CDP", () => disconnectCdp());
|
|
7225
|
+
await attempt("platform shutdown", async () => {
|
|
7226
|
+
await currentPlatformBackend.shutdown?.();
|
|
7227
|
+
});
|
|
7228
|
+
await attempt("drain scheduler", () => drain);
|
|
7229
|
+
await attempt("release owned browser", () => releaseOwnedBrowserState(runtimeState));
|
|
7213
7230
|
if (runtimeState.managedBrowserCdpPort && process.env.PIE_COMPUTER_USE_CDP_PORT === runtimeState.managedBrowserCdpPort) {
|
|
7214
7231
|
if (runtimeState.previousCdpPort === void 0) delete process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
7215
7232
|
else process.env.PIE_COMPUTER_USE_CDP_PORT = runtimeState.previousCdpPort;
|
|
7216
7233
|
}
|
|
7217
|
-
runtimeState.managedBrowserCdpPort = void 0;
|
|
7218
7234
|
runtimeState.previousCdpPort = void 0;
|
|
7235
|
+
if (runtimeState.managedBrowser === void 0) {
|
|
7236
|
+
runtimeState.managedBrowserCdpPort = void 0;
|
|
7237
|
+
}
|
|
7219
7238
|
savedStates.clear();
|
|
7220
7239
|
clearStoredOutputs();
|
|
7221
7240
|
runtimeState.windowRefs.clear();
|
|
@@ -7227,6 +7246,8 @@ async function releaseComputerUseSession() {
|
|
|
7227
7246
|
runtimeState.helperDiagnostics = void 0;
|
|
7228
7247
|
runtimeState.lastPermissionCheckAt = 0;
|
|
7229
7248
|
resourceScheduler = new ResourceScheduler();
|
|
7249
|
+
if (failures.length === 1) throw failures[0];
|
|
7250
|
+
if (failures.length > 1) throw new AggregateError(failures, "computer-use session release had partial failures (state was reset)");
|
|
7230
7251
|
}
|
|
7231
7252
|
function currentRuntimeMode() {
|
|
7232
7253
|
return isHeadlessMode() ? "stealth" : "default";
|
|
@@ -24491,6 +24491,10 @@ var McpServerManager = class {
|
|
|
24491
24491
|
definitions;
|
|
24492
24492
|
cachePath;
|
|
24493
24493
|
log;
|
|
24494
|
+
/** Set by dispose(); after it, no new connects and no late attach. */
|
|
24495
|
+
disposed = false;
|
|
24496
|
+
/** Prefixed names claimed by more than one server in the last loadCatalog(); callTool fail-closes on them. */
|
|
24497
|
+
conflictedNames = /* @__PURE__ */ new Set();
|
|
24494
24498
|
constructor(definitions, cachePath, log) {
|
|
24495
24499
|
this.definitions = new Map(definitions.map((definition) => [sanitizeName(definition.name), definition]));
|
|
24496
24500
|
if (this.definitions.size !== definitions.length) {
|
|
@@ -24549,6 +24553,7 @@ var McpServerManager = class {
|
|
|
24549
24553
|
}
|
|
24550
24554
|
/** Connect lazily. Concurrent callers share one in-flight connect. */
|
|
24551
24555
|
async connect(server, signal) {
|
|
24556
|
+
if (this.disposed) throw new Error("MCP server manager is disposed");
|
|
24552
24557
|
const key = sanitizeName(server);
|
|
24553
24558
|
const definition = this.definitions.get(key);
|
|
24554
24559
|
if (!definition) throw new Error(`unknown MCP server "${server}"`);
|
|
@@ -24561,12 +24566,17 @@ var McpServerManager = class {
|
|
|
24561
24566
|
runtime.connecting = (async () => {
|
|
24562
24567
|
this.log(`mcp: connecting to "${key}" (${definition.command ?? definition.url})`);
|
|
24563
24568
|
const { client, transport } = this.startTransport(definition, runtime);
|
|
24569
|
+
runtime.transport = transport;
|
|
24564
24570
|
client.onclose = () => {
|
|
24565
24571
|
this.log(`mcp: server "${key}" connection closed`);
|
|
24566
24572
|
runtime.client = void 0;
|
|
24567
24573
|
};
|
|
24568
24574
|
try {
|
|
24569
24575
|
await withTimeout(client.connect(transport), connectTimeoutFor(definition), `connect "${key}"`, signal);
|
|
24576
|
+
if (this.disposed) {
|
|
24577
|
+
await transport.close().catch(() => void 0);
|
|
24578
|
+
throw new Error(`MCP manager disposed while connecting to "${key}"`);
|
|
24579
|
+
}
|
|
24570
24580
|
runtime.client = client;
|
|
24571
24581
|
await this.refreshTools(runtime, connectTimeoutFor(definition));
|
|
24572
24582
|
return runtime;
|
|
@@ -24576,6 +24586,7 @@ var McpServerManager = class {
|
|
|
24576
24586
|
}
|
|
24577
24587
|
})().finally(() => {
|
|
24578
24588
|
runtime.connecting = void 0;
|
|
24589
|
+
runtime.transport = void 0;
|
|
24579
24590
|
});
|
|
24580
24591
|
try {
|
|
24581
24592
|
return await runtime.connecting;
|
|
@@ -24623,7 +24634,14 @@ var McpServerManager = class {
|
|
|
24623
24634
|
if (runtime.tools) snapshot[key] = runtime.tools;
|
|
24624
24635
|
}
|
|
24625
24636
|
fs2.mkdirSync(path2.dirname(this.cachePath), { recursive: true });
|
|
24626
|
-
|
|
24637
|
+
const tempPath = `${this.cachePath}.${process.pid}.tmp`;
|
|
24638
|
+
fs2.writeFileSync(tempPath, JSON.stringify({ updatedAt: Date.now(), tools: snapshot }, null, 2), "utf8");
|
|
24639
|
+
try {
|
|
24640
|
+
fs2.renameSync(tempPath, this.cachePath);
|
|
24641
|
+
} catch (error2) {
|
|
24642
|
+
fs2.unlinkSync(tempPath);
|
|
24643
|
+
throw error2;
|
|
24644
|
+
}
|
|
24627
24645
|
} catch (error2) {
|
|
24628
24646
|
this.log(`mcp: metadata cache write failed: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
24629
24647
|
}
|
|
@@ -24635,20 +24653,32 @@ var McpServerManager = class {
|
|
|
24635
24653
|
/** Metadata catalog: live runtimes plus the last persisted snapshot. */
|
|
24636
24654
|
loadCatalog() {
|
|
24637
24655
|
const catalog = /* @__PURE__ */ new Map();
|
|
24638
|
-
const
|
|
24639
|
-
|
|
24656
|
+
const ownerOf = /* @__PURE__ */ new Map();
|
|
24657
|
+
const conflicts = /* @__PURE__ */ new Set();
|
|
24658
|
+
const claim2 = (tool, live) => {
|
|
24659
|
+
const owner = ownerOf.get(tool.prefixedName);
|
|
24660
|
+
if (owner !== void 0 && owner !== tool.server) {
|
|
24661
|
+
conflicts.add(tool.prefixedName);
|
|
24662
|
+
return;
|
|
24663
|
+
}
|
|
24664
|
+
if (owner !== void 0 && !live) return;
|
|
24665
|
+
catalog.set(tool.prefixedName, tool);
|
|
24666
|
+
ownerOf.set(tool.prefixedName, tool.server);
|
|
24667
|
+
};
|
|
24668
|
+
for (const tools of Object.values(this.readCacheFile())) {
|
|
24640
24669
|
for (const tool of tools) {
|
|
24641
24670
|
if (!this.definitions.has(tool.server)) continue;
|
|
24642
|
-
|
|
24643
|
-
this.log(`mcp: metadata cache collision on ${tool.prefixedName} (server "${tool.server}", first seen from another server) \u2014 keeping the first entry`);
|
|
24644
|
-
continue;
|
|
24645
|
-
}
|
|
24646
|
-
catalog.set(tool.prefixedName, tool);
|
|
24671
|
+
claim2(tool, false);
|
|
24647
24672
|
}
|
|
24648
24673
|
}
|
|
24649
24674
|
for (const runtime of this.runtimes.values()) {
|
|
24650
|
-
for (const tool of runtime.tools ?? [])
|
|
24675
|
+
for (const tool of runtime.tools ?? []) claim2(tool, true);
|
|
24651
24676
|
}
|
|
24677
|
+
for (const name of conflicts) {
|
|
24678
|
+
catalog.delete(name);
|
|
24679
|
+
this.log(`mcp: tool name "${name}" is claimed by more than one server \u2014 disabled until the servers are renamed (fail-closed)`);
|
|
24680
|
+
}
|
|
24681
|
+
this.conflictedNames = conflicts;
|
|
24652
24682
|
return [...catalog.values()].sort((a, b) => a.prefixedName.localeCompare(b.prefixedName));
|
|
24653
24683
|
}
|
|
24654
24684
|
cacheMtime;
|
|
@@ -24676,6 +24706,12 @@ var McpServerManager = class {
|
|
|
24676
24706
|
}
|
|
24677
24707
|
async callTool(prefixedName, args, signal) {
|
|
24678
24708
|
const catalog = this.loadCatalog();
|
|
24709
|
+
if (this.conflictedNames.has(prefixedName)) {
|
|
24710
|
+
return {
|
|
24711
|
+
delivery: "not_sent",
|
|
24712
|
+
error: `MCP tool name "${prefixedName}" is claimed by more than one configured server. Rename one of the servers so every tool name is unambiguous; the call was NOT sent.`
|
|
24713
|
+
};
|
|
24714
|
+
}
|
|
24679
24715
|
const descriptor = catalog.find((tool) => tool.prefixedName === prefixedName);
|
|
24680
24716
|
let server = descriptor?.server;
|
|
24681
24717
|
let toolName = descriptor?.tool;
|
|
@@ -24746,12 +24782,17 @@ ${tail}` : "")
|
|
|
24746
24782
|
}
|
|
24747
24783
|
/** Close every client and reap every child process. */
|
|
24748
24784
|
async dispose() {
|
|
24785
|
+
this.disposed = true;
|
|
24749
24786
|
for (const runtime of this.runtimes.values()) {
|
|
24750
24787
|
try {
|
|
24751
24788
|
await runtime.client?.close();
|
|
24752
24789
|
} catch {
|
|
24753
24790
|
}
|
|
24791
|
+
if (!runtime.client && runtime.transport) {
|
|
24792
|
+
await runtime.transport.close().catch(() => void 0);
|
|
24793
|
+
}
|
|
24754
24794
|
runtime.client = void 0;
|
|
24795
|
+
runtime.transport = void 0;
|
|
24755
24796
|
}
|
|
24756
24797
|
this.runtimes.clear();
|
|
24757
24798
|
}
|
|
@@ -24820,10 +24861,14 @@ var DEFAULT_OUTPUT_MAX_BYTES = 8192;
|
|
|
24820
24861
|
var SEARCH_RESULT_LIMIT = 20;
|
|
24821
24862
|
function truncate(text, maxBytes) {
|
|
24822
24863
|
if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
|
|
24823
|
-
const
|
|
24824
|
-
return `${cut}
|
|
24864
|
+
const notice = `
|
|
24825
24865
|
|
|
24826
24866
|
\u2026[truncated: result exceeded ${maxBytes} bytes. Narrow the call arguments or read the resource directly.]`;
|
|
24867
|
+
const noticeBytes = Buffer.byteLength(notice, "utf8");
|
|
24868
|
+
const bodyBudget = Math.max(1, maxBytes - noticeBytes);
|
|
24869
|
+
let cut = Buffer.from(text, "utf8").subarray(0, bodyBudget).toString("utf8");
|
|
24870
|
+
if (cut.endsWith("\uFFFD")) cut = cut.slice(0, -1);
|
|
24871
|
+
return `${cut}${notice}`;
|
|
24827
24872
|
}
|
|
24828
24873
|
function summarizeParams(schema) {
|
|
24829
24874
|
if (!schema || typeof schema !== "object") return "";
|
|
@@ -25241,8 +25286,8 @@ function mcpAdapter(ctx) {
|
|
|
25241
25286
|
commandCtx.ui.notify(lines.join("\n"), "info");
|
|
25242
25287
|
}
|
|
25243
25288
|
});
|
|
25244
|
-
ctx.on("session:changed", () => {
|
|
25245
|
-
|
|
25289
|
+
ctx.on("session:changed", async () => {
|
|
25290
|
+
await reloadManager();
|
|
25246
25291
|
});
|
|
25247
25292
|
}
|
|
25248
25293
|
export {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
isPlanModeSafeCommand,
|
|
8
8
|
markCompletedPlanSteps,
|
|
9
9
|
restoreExecutionState
|
|
10
|
-
} from "../../../chunks/chunk-
|
|
10
|
+
} from "../../../chunks/chunk-HH2Q2SNX.js";
|
|
11
11
|
import "../../../chunks/chunk-QJH6YN2W.js";
|
|
12
12
|
import "../../../chunks/chunk-IM43UYVV.js";
|
|
13
13
|
import {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createCliHostCapabilities
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-G3SE3I2L.js";
|
|
5
5
|
import "../../../chunks/chunk-5353DEEC.js";
|
|
6
6
|
import {
|
|
7
7
|
createSharedFileSystemTools,
|
|
8
8
|
createSubagentCapability
|
|
9
|
-
} from "../../../chunks/chunk-
|
|
9
|
+
} from "../../../chunks/chunk-HH2Q2SNX.js";
|
|
10
10
|
import "../../../chunks/chunk-QJH6YN2W.js";
|
|
11
11
|
import "../../../chunks/chunk-IM43UYVV.js";
|
|
12
12
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
executeManageTodoList,
|
|
9
9
|
executionStateToTodos,
|
|
10
10
|
restoreExecutionState
|
|
11
|
-
} from "../../../chunks/chunk-
|
|
11
|
+
} from "../../../chunks/chunk-HH2Q2SNX.js";
|
|
12
12
|
import "../../../chunks/chunk-QJH6YN2W.js";
|
|
13
13
|
import "../../../chunks/chunk-IM43UYVV.js";
|
|
14
14
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
@@ -9999,6 +9999,16 @@ function validateRequest(value) {
|
|
|
9999
9999
|
string("command", true, 32768);
|
|
10000
10000
|
string("cwd");
|
|
10001
10001
|
string("label", false, 1024);
|
|
10002
|
+
if (r.env !== void 0) {
|
|
10003
|
+
if (!r.env || typeof r.env !== "object" || Array.isArray(r.env)) throw new Error("Invalid env: expected an object of string to string.");
|
|
10004
|
+
const entries = Object.entries(r.env);
|
|
10005
|
+
if (entries.length > 512) throw new Error("Invalid env: at most 512 variables.");
|
|
10006
|
+
for (const [k, v] of entries) {
|
|
10007
|
+
if (!k.length || k.length > 256 || k.includes("\0") || typeof v !== "string" || v.length > 65536 || v.includes("\0")) {
|
|
10008
|
+
throw new Error(`Invalid env entry ${JSON.stringify(k)}: expected string key and value without NUL bytes.`);
|
|
10009
|
+
}
|
|
10010
|
+
}
|
|
10011
|
+
}
|
|
10002
10012
|
if (r.argv !== void 0 && (!Array.isArray(r.argv) || r.argv.length < 1 || r.argv.length > 256 || r.argv.some((a) => typeof a !== "string" || a.includes("\0") || a.length > 32768) || !r.argv[0])) throw new Error("Invalid argv: expected a non-empty array of executable and arguments.");
|
|
10003
10013
|
// Fall through to the shared PTY size limits.
|
|
10004
10014
|
case "resize":
|
|
@@ -10294,6 +10304,13 @@ var SUPPORTED_KEYS = Object.keys(KEY_MAP);
|
|
|
10294
10304
|
var import_node_fs2 = require("node:fs");
|
|
10295
10305
|
var import_node_path3 = __toESM(require("node:path"));
|
|
10296
10306
|
var program2 = new Command();
|
|
10307
|
+
function callerEnv() {
|
|
10308
|
+
const env = {};
|
|
10309
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
10310
|
+
if (typeof value === "string") env[key] = value;
|
|
10311
|
+
}
|
|
10312
|
+
return env;
|
|
10313
|
+
}
|
|
10297
10314
|
program2.name("tui-use").description("TUI automation for AI agents \u2014 like BrowserUse, but for the terminal").option("--session <id>", "Target this session explicitly (safe for concurrent tasks)").version(version);
|
|
10298
10315
|
program2.command("start [args...]").description("Start an interactive program in a PTY session").option("--cwd <dir>", "Working directory for the command").option("--label <name>", "Human-readable label for this session").option("--cols <n>", "Terminal width (default: 120)", "120").option("--rows <n>", "Terminal height (default: 30)", "30").option("--argv-stdin", "Read a JSON array of executable and arguments from UTF-8 stdin; bypass the shell").action(async (args, opts) => {
|
|
10299
10316
|
let argv;
|
|
@@ -10311,6 +10328,7 @@ program2.command("start [args...]").description("Start an interactive program in
|
|
|
10311
10328
|
type: "start",
|
|
10312
10329
|
command,
|
|
10313
10330
|
cwd: import_node_path3.default.resolve(opts.cwd ?? process.cwd()),
|
|
10331
|
+
env: callerEnv(),
|
|
10314
10332
|
label: opts.label,
|
|
10315
10333
|
cols: Number(opts.cols),
|
|
10316
10334
|
rows: Number(opts.rows),
|
|
@@ -7267,7 +7267,10 @@ var Session = class {
|
|
|
7267
7267
|
rows,
|
|
7268
7268
|
useConptyDll: process.platform === "win32",
|
|
7269
7269
|
cwd: options.cwd ?? process.cwd(),
|
|
7270
|
-
env:
|
|
7270
|
+
// The caller's env, not the daemon starter's: a persistent daemon
|
|
7271
|
+
// outlives many projects, and each session must see the environment
|
|
7272
|
+
// of the shell that started it (PATH setups, PIE_* overrides, ...).
|
|
7273
|
+
env: options.env ?? process.env
|
|
7271
7274
|
});
|
|
7272
7275
|
} catch (error) {
|
|
7273
7276
|
this.terminal.dispose();
|
|
@@ -7606,6 +7609,16 @@ function validateRequest(value) {
|
|
|
7606
7609
|
string("command", true, 32768);
|
|
7607
7610
|
string("cwd");
|
|
7608
7611
|
string("label", false, 1024);
|
|
7612
|
+
if (r.env !== void 0) {
|
|
7613
|
+
if (!r.env || typeof r.env !== "object" || Array.isArray(r.env)) throw new Error("Invalid env: expected an object of string to string.");
|
|
7614
|
+
const entries = Object.entries(r.env);
|
|
7615
|
+
if (entries.length > 512) throw new Error("Invalid env: at most 512 variables.");
|
|
7616
|
+
for (const [k, v] of entries) {
|
|
7617
|
+
if (!k.length || k.length > 256 || k.includes("\0") || typeof v !== "string" || v.length > 65536 || v.includes("\0")) {
|
|
7618
|
+
throw new Error(`Invalid env entry ${JSON.stringify(k)}: expected string key and value without NUL bytes.`);
|
|
7619
|
+
}
|
|
7620
|
+
}
|
|
7621
|
+
}
|
|
7609
7622
|
if (r.argv !== void 0 && (!Array.isArray(r.argv) || r.argv.length < 1 || r.argv.length > 256 || r.argv.some((a) => typeof a !== "string" || a.includes("\0") || a.length > 32768) || !r.argv[0])) throw new Error("Invalid argv: expected a non-empty array of executable and arguments.");
|
|
7610
7623
|
// Fall through to the shared PTY size limits.
|
|
7611
7624
|
case "resize":
|
|
@@ -4856,7 +4856,7 @@ var AgentSessionRetryController = class {
|
|
|
4856
4856
|
}
|
|
4857
4857
|
return;
|
|
4858
4858
|
}
|
|
4859
|
-
const maxRetries = this.retry.maxRetries ?? 3;
|
|
4859
|
+
const maxRetries = this.retry.maxRetriesForFailure?.(failure) ?? this.retry.maxRetries ?? 3;
|
|
4860
4860
|
this.retryAttempt += 1;
|
|
4861
4861
|
if (this.retryAttempt > maxRetries) {
|
|
4862
4862
|
const terminalFailure = asTerminalFailure(failure);
|
|
@@ -4869,7 +4869,8 @@ var AgentSessionRetryController = class {
|
|
|
4869
4869
|
return;
|
|
4870
4870
|
}
|
|
4871
4871
|
const attempt = this.retryAttempt;
|
|
4872
|
-
const
|
|
4872
|
+
const rawDelayMs = (this.retry.baseDelayMs ?? 2e3) * 2 ** (attempt - 1);
|
|
4873
|
+
const delayMs = this.retry.maxDelayMs !== void 0 ? Math.min(rawDelayMs, this.retry.maxDelayMs) : rawDelayMs;
|
|
4873
4874
|
this.ensurePending();
|
|
4874
4875
|
this.setRecoveryState("retry_pending");
|
|
4875
4876
|
this.emit({ type: "turn_recovery_pending", recovery: "retry", failure, attempt, maxRetries, delayMs });
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
createCliWebResearchHealthStore,
|
|
8
8
|
formatSize,
|
|
9
9
|
truncateHeadTail
|
|
10
|
-
} from "./chunks/chunk-
|
|
10
|
+
} from "./chunks/chunk-G3SE3I2L.js";
|
|
11
11
|
import {
|
|
12
12
|
VERSION,
|
|
13
13
|
getAgentDir,
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
setExtensionEnabledInSettings,
|
|
79
79
|
shouldPreserveExecutionStateForUserText,
|
|
80
80
|
supersedeExecutionState
|
|
81
|
-
} from "./chunks/chunk-
|
|
81
|
+
} from "./chunks/chunk-HH2Q2SNX.js";
|
|
82
82
|
import "./chunks/chunk-QJH6YN2W.js";
|
|
83
83
|
import {
|
|
84
84
|
Deref,
|
|
@@ -77119,7 +77119,7 @@ function stripStaleUsageBeforeCompaction(messages, latestCompactionTimestamp) {
|
|
|
77119
77119
|
}
|
|
77120
77120
|
|
|
77121
77121
|
// src/runtime/retry-policy.ts
|
|
77122
|
-
var TRANSIENT_NETWORK_ERROR_PATTERN = /sse stream aborted|sse stream closed before end|sse stream ended before response completed|(?:read\s+)?ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|socket hang up|request timeout|client network socket disconnected before secure TLS connection was established|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated/i;
|
|
77122
|
+
var TRANSIENT_NETWORK_ERROR_PATTERN = /sse stream aborted|sse stream closed before end|sse stream ended before response completed|(?:read\s+)?ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|(?:read\s+|write\s+)?EPIPE|socket hang up|request timeout|client network socket disconnected before secure TLS connection was established|certificate (?:has )?expired|unable to verify (?:the first certificate|certificate)|self[- ]signed cert|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated/i;
|
|
77123
77123
|
var PROVIDER_TRANSIENT_ERROR_PATTERN = /overloaded|rate.?limit|too many requests|\b429\b|\b500\b|\b502\b|\b503\b|\b504\b|service.?unavailable|server error|internal error|retry delay/i;
|
|
77124
77124
|
var USER_ABORT_PATTERN = /request was aborted|local abort signal|user abort|user_interrupt|interrupted by user|esc pressed|ctrl\+c/i;
|
|
77125
77125
|
var AUTH_CONFIG_PATTERN = /missing api key|invalid api key|api key.*invalid|unauthorized|\b401\b|\b403\b|forbidden|authentication failed|no configured model|no models? are configured/i;
|
|
@@ -77127,6 +77127,8 @@ var INVALID_FILE_REFERENCE_PATTERN = /not the owner of this file|owner of this f
|
|
|
77127
77127
|
var INVALID_REQUEST_PATTERN = /bad request|\b400\b|invalid request|invalid schema|schema validation|invalid parameter|unsupported parameter|malformed/i;
|
|
77128
77128
|
var CLI_RETRY_MAX_RETRIES = 3;
|
|
77129
77129
|
var CLI_RETRY_BASE_DELAY_MS = 2e3;
|
|
77130
|
+
var CLI_TRANSIENT_NETWORK_MAX_RETRIES = 10;
|
|
77131
|
+
var CLI_RETRY_MAX_DELAY_MS = 6e4;
|
|
77130
77132
|
function isCliContextOverflowError(errorMessage4) {
|
|
77131
77133
|
return /context length exceeded|context_length_exceeded|maximum context length|maximum context size|too many tokens|input.*too long|prompt.*too long|context window|token limit exceeded|exceeds.{0,20}context/i.test(
|
|
77132
77134
|
errorMessage4
|
|
@@ -77203,6 +77205,31 @@ function getCliRetryBaseDelayMs() {
|
|
|
77203
77205
|
const parsed = Number(override);
|
|
77204
77206
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : CLI_RETRY_BASE_DELAY_MS;
|
|
77205
77207
|
}
|
|
77208
|
+
function getCliTransientNetworkMaxRetries() {
|
|
77209
|
+
const override = process.env.PIE_RETRY_TRANSIENT_NETWORK_MAX_RETRIES;
|
|
77210
|
+
if (!override) {
|
|
77211
|
+
return CLI_TRANSIENT_NETWORK_MAX_RETRIES;
|
|
77212
|
+
}
|
|
77213
|
+
const parsed = Number(override);
|
|
77214
|
+
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : CLI_TRANSIENT_NETWORK_MAX_RETRIES;
|
|
77215
|
+
}
|
|
77216
|
+
function getCliRetryMaxDelayMs() {
|
|
77217
|
+
const override = process.env.PIE_RETRY_MAX_DELAY_MS;
|
|
77218
|
+
if (!override) {
|
|
77219
|
+
return CLI_RETRY_MAX_DELAY_MS;
|
|
77220
|
+
}
|
|
77221
|
+
const parsed = Number(override);
|
|
77222
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : CLI_RETRY_MAX_DELAY_MS;
|
|
77223
|
+
}
|
|
77224
|
+
function createCliRetryPolicy(isRetryableErrorOverride) {
|
|
77225
|
+
return {
|
|
77226
|
+
isRetryableError: isRetryableErrorOverride ?? isCliRetryableError,
|
|
77227
|
+
maxRetries: CLI_RETRY_MAX_RETRIES,
|
|
77228
|
+
baseDelayMs: getCliRetryBaseDelayMs(),
|
|
77229
|
+
maxDelayMs: getCliRetryMaxDelayMs(),
|
|
77230
|
+
maxRetriesForFailure: (failure) => failure.kind === "transient_network" ? getCliTransientNetworkMaxRetries() : CLI_RETRY_MAX_RETRIES
|
|
77231
|
+
};
|
|
77232
|
+
}
|
|
77206
77233
|
|
|
77207
77234
|
// src/runtime/interactive-context-ui.ts
|
|
77208
77235
|
function calculateContextUsage(host) {
|
|
@@ -77921,11 +77948,9 @@ function createInteractiveAgentSessionController(host) {
|
|
|
77921
77948
|
},
|
|
77922
77949
|
getAutoContinueMessage: () => host.getTodoAutoContinueMessage(),
|
|
77923
77950
|
classifyFailure: (context) => classifyCliFailure(context),
|
|
77924
|
-
retry:
|
|
77925
|
-
|
|
77926
|
-
|
|
77927
|
-
baseDelayMs: getCliRetryBaseDelayMs()
|
|
77928
|
-
},
|
|
77951
|
+
retry: createCliRetryPolicy(
|
|
77952
|
+
(errorMessage4) => !host._isContextOverflowError(errorMessage4) && isCliRetryableError(errorMessage4)
|
|
77953
|
+
),
|
|
77929
77954
|
compaction: {
|
|
77930
77955
|
compact: async (context) => {
|
|
77931
77956
|
const beforeCompact = await host.extensionRunner?.emitSessionBeforeCompact({
|
|
@@ -80152,6 +80177,24 @@ async function composeCliRuntime(params) {
|
|
|
80152
80177
|
};
|
|
80153
80178
|
}
|
|
80154
80179
|
|
|
80180
|
+
// src/app/print-mode-retry-status.ts
|
|
80181
|
+
function createPrintModeRetryStatusReporter() {
|
|
80182
|
+
let exhaustedRetryBudget;
|
|
80183
|
+
return (event) => {
|
|
80184
|
+
if (event.type === "turn_recovery_pending" && event.recovery === "retry") {
|
|
80185
|
+
console.error(`Transient request error: ${event.failure.message}. Retrying in ${(event.delayMs ?? 0) / 1e3}s (${event.attempt}/${event.maxRetries}).`);
|
|
80186
|
+
} else if (event.type === "turn_retry_started") {
|
|
80187
|
+
console.error(`Retrying request (${event.attempt}/${event.maxRetries})...`);
|
|
80188
|
+
} else if (event.type === "turn_retry_succeeded") {
|
|
80189
|
+
console.error(`Retry succeeded after ${event.attempts} attempt${event.attempts === 1 ? "" : "s"}.`);
|
|
80190
|
+
} else if (event.type === "retry_exhausted") {
|
|
80191
|
+
exhaustedRetryBudget = event.maxRetries;
|
|
80192
|
+
} else if (event.type === "turn_failed_terminal" && (event.failure.kind === "transient_network" || event.failure.kind === "provider_transient")) {
|
|
80193
|
+
console.error(`Request failed after ${exhaustedRetryBudget ?? CLI_RETRY_MAX_RETRIES} retries: ${event.failure.message}`);
|
|
80194
|
+
}
|
|
80195
|
+
};
|
|
80196
|
+
}
|
|
80197
|
+
|
|
80155
80198
|
// src/app/print-mode.ts
|
|
80156
80199
|
function createNoOpExtensionUIContext() {
|
|
80157
80200
|
return {
|
|
@@ -80329,6 +80372,7 @@ async function runPrintMode(params) {
|
|
|
80329
80372
|
streamFn: params.streamFn
|
|
80330
80373
|
});
|
|
80331
80374
|
const sessionTrace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
|
|
80375
|
+
const reportRetryStatus = createPrintModeRetryStatusReporter();
|
|
80332
80376
|
const agentSessionController = new AgentSessionController({
|
|
80333
80377
|
agent,
|
|
80334
80378
|
sessionManager: runtime.sessionManager,
|
|
@@ -80349,11 +80393,7 @@ async function runPrintMode(params) {
|
|
|
80349
80393
|
messages: result.messages?.length ? [...context.messages, ...result.messages] : context.messages
|
|
80350
80394
|
};
|
|
80351
80395
|
},
|
|
80352
|
-
retry:
|
|
80353
|
-
isRetryableError: isCliRetryableError,
|
|
80354
|
-
maxRetries: CLI_RETRY_MAX_RETRIES,
|
|
80355
|
-
baseDelayMs: getCliRetryBaseDelayMs()
|
|
80356
|
-
},
|
|
80396
|
+
retry: createCliRetryPolicy(),
|
|
80357
80397
|
getAutoCompactDecision: ({ message, messages }) => createCliAutoCompactDecision({
|
|
80358
80398
|
message,
|
|
80359
80399
|
messages,
|
|
@@ -80388,20 +80428,14 @@ async function runPrintMode(params) {
|
|
|
80388
80428
|
classifyFailure: (context) => classifyCliFailure(context),
|
|
80389
80429
|
onEvent: (event) => {
|
|
80390
80430
|
sessionTrace.noteRuntimeEvent(event.type, event);
|
|
80391
|
-
if (event.type === "turn_recovery_pending" && event.recovery === "
|
|
80392
|
-
console.error(`Transient request error: ${event.failure.message}. Retrying in ${(event.delayMs ?? 0) / 1e3}s (${event.attempt}/${event.maxRetries}).`);
|
|
80393
|
-
} else if (event.type === "turn_recovery_pending" && event.recovery === "compaction") {
|
|
80431
|
+
if (event.type === "turn_recovery_pending" && event.recovery === "compaction") {
|
|
80394
80432
|
console.error(event.failure.kind === "context_overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context before retry...");
|
|
80395
80433
|
} else if (event.type === "auto_compaction_start") {
|
|
80396
80434
|
console.error(event.reason === "overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context...");
|
|
80397
80435
|
} else if (event.type === "auto_compaction_end" && !event.errorMessage) {
|
|
80398
80436
|
runtime.fileObservationState.clear();
|
|
80399
|
-
} else
|
|
80400
|
-
|
|
80401
|
-
} else if (event.type === "turn_retry_succeeded") {
|
|
80402
|
-
console.error(`Retry succeeded after ${event.attempts} attempt${event.attempts === 1 ? "" : "s"}.`);
|
|
80403
|
-
} else if (event.type === "turn_failed_terminal" && (event.failure.kind === "transient_network" || event.failure.kind === "provider_transient")) {
|
|
80404
|
-
console.error(`Request failed after ${CLI_RETRY_MAX_RETRIES} retries: ${event.failure.message}`);
|
|
80437
|
+
} else {
|
|
80438
|
+
reportRetryStatus(event);
|
|
80405
80439
|
}
|
|
80406
80440
|
}
|
|
80407
80441
|
});
|
|
@@ -81518,11 +81552,7 @@ async function runJsonEventsMode(params) {
|
|
|
81518
81552
|
messages: result?.messages?.length ? [...context.messages, ...result.messages] : context.messages
|
|
81519
81553
|
};
|
|
81520
81554
|
},
|
|
81521
|
-
retry:
|
|
81522
|
-
isRetryableError: isCliRetryableError,
|
|
81523
|
-
maxRetries: CLI_RETRY_MAX_RETRIES,
|
|
81524
|
-
baseDelayMs: getCliRetryBaseDelayMs()
|
|
81525
|
-
},
|
|
81555
|
+
retry: createCliRetryPolicy(),
|
|
81526
81556
|
getAutoCompactDecision: ({ message, messages }) => createCliAutoCompactDecision({
|
|
81527
81557
|
message,
|
|
81528
81558
|
messages,
|