@cydm/pie 2.5.0 → 2.5.2
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 +3 -3
- package/dist/builtin/extensions/computer-use/index.js +17 -2
- package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +90 -9
- package/dist/builtin/extensions/herdr-agent-state/index.js +39 -3
- package/dist/builtin/extensions/mcp-adapter/index.js +161 -35
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +4 -4
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-bridge.js +5 -0
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +5 -2
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +1 -1
- package/dist/builtin/skills/chrome-devtools-axi/{cli-P4VG6ZZG.js → cli-EJ5MQZNA.js} +76 -27
- package/dist/builtin/skills/tui-use/tui-use-cli.cjs +25 -9
- package/dist/builtin/skills/tui-use/tui-use-daemon.cjs +7 -1
- package/dist/chunks/{chunk-JXY3YLDS.js → chunk-LO2V5DZZ.js} +46 -9
- package/dist/chunks/{chunk-PU7IIEKH.js → chunk-M4OJARWJ.js} +25 -15
- package/dist/chunks/{chunk-ZKHMNEXL.js → chunk-RTTGO2A6.js} +1 -1
- package/dist/chunks/{chunk-YRXXRLMQ.js → chunk-UD7KYQ6J.js} +9 -0
- package/dist/chunks/{src-SXUQ7OY6.js → src-33WRCQWX.js} +2 -2
- package/dist/chunks/{test-stream-OD3B57AS.js → test-stream-LFR6GSKQ.js} +1 -1
- package/dist/cli.js +117 -20
- package/package.json +1 -1
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
executeManageTodoList,
|
|
9
9
|
executionStateToTodos,
|
|
10
10
|
restoreExecutionState
|
|
11
|
-
} from "../../../chunks/chunk-
|
|
12
|
-
import "../../../chunks/chunk-
|
|
13
|
-
import "../../../chunks/chunk-
|
|
11
|
+
} from "../../../chunks/chunk-LO2V5DZZ.js";
|
|
12
|
+
import "../../../chunks/chunk-RTTGO2A6.js";
|
|
13
|
+
import "../../../chunks/chunk-UD7KYQ6J.js";
|
|
14
14
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
15
15
|
import "../../../chunks/chunk-LZQXQOPJ.js";
|
|
16
16
|
|
|
@@ -19640,6 +19640,11 @@ async function handleBridgeRequest(client, req, res, sessionName, logForbidden,
|
|
|
19640
19640
|
writeJson(res, 200, {
|
|
19641
19641
|
status: "ok",
|
|
19642
19642
|
session: sessionName,
|
|
19643
|
+
// The bridge's own PID so `stop` can verify that the process named
|
|
19644
|
+
// in a (possibly stale) pid file is really THIS bridge before any
|
|
19645
|
+
// signal is sent — a healthy session on the recorded port alone
|
|
19646
|
+
// must not authorize killing an unrelated reused PID.
|
|
19647
|
+
pid: process.pid,
|
|
19643
19648
|
busy: client.isBusy?.() ?? false,
|
|
19644
19649
|
...droppedSelection ? { pageIdentityChanged: true } : {}
|
|
19645
19650
|
});
|
|
@@ -46,8 +46,11 @@ export function runChromeDevtoolsAxiCli(args = process.argv.slice(2), options =
|
|
|
46
46
|
...process.env,
|
|
47
47
|
CHROME_DEVTOOLS_AXI_MCP_PATH: process.env.CHROME_DEVTOOLS_AXI_MCP_PATH?.trim() || resolveChromeDevtoolsMcpScript(),
|
|
48
48
|
// Pie pins chrome-devtools-mcp; its daily background update check
|
|
49
|
-
// (network + ~/.cache write + "install @latest" nag)
|
|
50
|
-
// the
|
|
49
|
+
// (network + ~/.cache write + "install @latest" nag) is UNCONDITIONALLY
|
|
50
|
+
// disabled for the packaged CLI: the upstream treats any nonempty
|
|
51
|
+
// value — including "0" or "false" — as "disable", so this env var
|
|
52
|
+
// cannot re-enable the check. To run the check, invoke the vendored
|
|
53
|
+
// cli outside Pie with the variable unset.
|
|
51
54
|
CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS: process.env.CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS || "1",
|
|
52
55
|
...options.env,
|
|
53
56
|
},
|
|
@@ -21,6 +21,6 @@ function tryFastPath(argv, options) {
|
|
|
21
21
|
|
|
22
22
|
// vendor/chrome-devtools-axi/bin/chrome-devtools-axi.ts
|
|
23
23
|
if (!tryFastPath(process.argv.slice(2), { version: VERSION })) {
|
|
24
|
-
const { main } = await import("./cli-
|
|
24
|
+
const { main } = await import("./cli-EJ5MQZNA.js");
|
|
25
25
|
await main(process.argv.slice(2));
|
|
26
26
|
}
|
|
@@ -1935,6 +1935,23 @@ async function waitForProcessExit(pid, timeoutMs) {
|
|
|
1935
1935
|
return !isProcessAlive(pid);
|
|
1936
1936
|
}
|
|
1937
1937
|
function isBridgeProcess(pid) {
|
|
1938
|
+
if (process.platform === "win32") {
|
|
1939
|
+
try {
|
|
1940
|
+
const command = execFileSync(
|
|
1941
|
+
"powershell",
|
|
1942
|
+
[
|
|
1943
|
+
"-NoProfile",
|
|
1944
|
+
"-NonInteractive",
|
|
1945
|
+
"-Command",
|
|
1946
|
+
`(Get-CimInstance Win32_Process -Filter "ProcessId=${pid}").CommandLine`
|
|
1947
|
+
],
|
|
1948
|
+
{ encoding: "utf-8", timeout: 4e3 }
|
|
1949
|
+
);
|
|
1950
|
+
return command.includes("chrome-devtools-axi-bridge");
|
|
1951
|
+
} catch {
|
|
1952
|
+
return false;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1938
1955
|
try {
|
|
1939
1956
|
const command = execFileSync("ps", ["-p", String(pid), "-o", "command="], {
|
|
1940
1957
|
encoding: "utf-8",
|
|
@@ -1949,28 +1966,43 @@ async function probeBridgeIdentity(port, sessionName) {
|
|
|
1949
1966
|
try {
|
|
1950
1967
|
const resp = await httpGet(port, "/health", HEALTH_TIMEOUT_MS);
|
|
1951
1968
|
const data = JSON.parse(resp);
|
|
1952
|
-
if (data.status !== "ok") return "unknown";
|
|
1969
|
+
if (data.status !== "ok") return { identity: "unknown" };
|
|
1953
1970
|
if (typeof data.session === "string" && data.session !== sessionName) {
|
|
1954
|
-
return "other";
|
|
1971
|
+
return { identity: "other" };
|
|
1955
1972
|
}
|
|
1956
|
-
return
|
|
1973
|
+
return {
|
|
1974
|
+
identity: "own",
|
|
1975
|
+
reportedPid: typeof data.pid === "number" && data.pid > 0 ? data.pid : void 0
|
|
1976
|
+
};
|
|
1957
1977
|
} catch {
|
|
1958
|
-
return "unknown";
|
|
1978
|
+
return { identity: "unknown" };
|
|
1959
1979
|
}
|
|
1960
1980
|
}
|
|
1961
1981
|
async function judgeRecordedBridge(pidInfo, sessionName) {
|
|
1962
|
-
const
|
|
1963
|
-
if (identity === "own") {
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1982
|
+
const probe = await probeBridgeIdentity(pidInfo.port, sessionName);
|
|
1983
|
+
if (probe.identity === "own") {
|
|
1984
|
+
if (probe.reportedPid !== void 0) {
|
|
1985
|
+
if (probe.reportedPid === pidInfo.pid) {
|
|
1986
|
+
return {
|
|
1987
|
+
terminate: true,
|
|
1988
|
+
killProcessGroup: isBridgeProcess(pidInfo.pid),
|
|
1989
|
+
targetPid: pidInfo.pid
|
|
1990
|
+
};
|
|
1991
|
+
}
|
|
1992
|
+
return {
|
|
1993
|
+
terminate: true,
|
|
1994
|
+
killProcessGroup: isBridgeProcess(probe.reportedPid),
|
|
1995
|
+
targetPid: probe.reportedPid
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
const bridge2 = isBridgeProcess(pidInfo.pid);
|
|
1999
|
+
return { terminate: bridge2, killProcessGroup: bridge2, targetPid: pidInfo.pid };
|
|
1968
2000
|
}
|
|
1969
|
-
if (identity === "other") {
|
|
2001
|
+
if (probe.identity === "other") {
|
|
1970
2002
|
return { terminate: false, killProcessGroup: false };
|
|
1971
2003
|
}
|
|
1972
2004
|
const bridge = isBridgeProcess(pidInfo.pid);
|
|
1973
|
-
return { terminate: bridge, killProcessGroup: bridge };
|
|
2005
|
+
return { terminate: bridge, killProcessGroup: bridge, targetPid: pidInfo.pid };
|
|
1974
2006
|
}
|
|
1975
2007
|
function removePidFile(pidFile) {
|
|
1976
2008
|
try {
|
|
@@ -1978,13 +2010,27 @@ function removePidFile(pidFile) {
|
|
|
1978
2010
|
} catch {
|
|
1979
2011
|
}
|
|
1980
2012
|
}
|
|
2013
|
+
function taskkillTree(pid) {
|
|
2014
|
+
try {
|
|
2015
|
+
execFileSync("taskkill", ["/PID", String(pid), "/T", "/F"], {
|
|
2016
|
+
stdio: "ignore",
|
|
2017
|
+
timeout: 1e4
|
|
2018
|
+
});
|
|
2019
|
+
return true;
|
|
2020
|
+
} catch {
|
|
2021
|
+
return !isProcessAlive(pid);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
1981
2024
|
async function terminateBridgeProcess(pid, opts = {}) {
|
|
1982
|
-
if (!isProcessAlive(pid)) return;
|
|
2025
|
+
if (!isProcessAlive(pid)) return true;
|
|
1983
2026
|
const killProcessGroup = opts.killProcessGroup === true;
|
|
2027
|
+
if (process.platform === "win32") {
|
|
2028
|
+
return taskkillTree(pid) && !await isProcessAlive(pid);
|
|
2029
|
+
}
|
|
1984
2030
|
try {
|
|
1985
2031
|
process.kill(pid, "SIGTERM");
|
|
1986
|
-
} catch {
|
|
1987
|
-
return;
|
|
2032
|
+
} catch (error) {
|
|
2033
|
+
if (error.code === "ESRCH") return true;
|
|
1988
2034
|
}
|
|
1989
2035
|
if (await waitForProcessExit(pid, 2e3)) {
|
|
1990
2036
|
if (killProcessGroup) {
|
|
@@ -1993,7 +2039,7 @@ async function terminateBridgeProcess(pid, opts = {}) {
|
|
|
1993
2039
|
} catch {
|
|
1994
2040
|
}
|
|
1995
2041
|
}
|
|
1996
|
-
return;
|
|
2042
|
+
return true;
|
|
1997
2043
|
}
|
|
1998
2044
|
if (killProcessGroup) {
|
|
1999
2045
|
try {
|
|
@@ -2010,7 +2056,7 @@ async function terminateBridgeProcess(pid, opts = {}) {
|
|
|
2010
2056
|
} catch {
|
|
2011
2057
|
}
|
|
2012
2058
|
}
|
|
2013
|
-
|
|
2059
|
+
return waitForProcessExit(pid, 1e3);
|
|
2014
2060
|
}
|
|
2015
2061
|
function spawnBridgeProcess(port, sessionName) {
|
|
2016
2062
|
const bridgeScript = resolveBridgeScript(import.meta.dirname);
|
|
@@ -2100,7 +2146,7 @@ async function ensureBridge(spawnBridge = spawnBridgeProcess, notice) {
|
|
|
2100
2146
|
}
|
|
2101
2147
|
const verdict = await judgeRecordedBridge(pidInfo, sessionName);
|
|
2102
2148
|
if (verdict.terminate) {
|
|
2103
|
-
await terminateBridgeProcess(pidInfo.pid, {
|
|
2149
|
+
await terminateBridgeProcess(verdict.targetPid ?? pidInfo.pid, {
|
|
2104
2150
|
killProcessGroup: verdict.killProcessGroup
|
|
2105
2151
|
});
|
|
2106
2152
|
} else {
|
|
@@ -2374,15 +2420,15 @@ async function getSessionSnapshotIfRunning() {
|
|
|
2374
2420
|
}
|
|
2375
2421
|
async function stopBridge() {
|
|
2376
2422
|
const pidInfo = readPidFile();
|
|
2377
|
-
if (!pidInfo) return
|
|
2378
|
-
if (!isProcessAlive(pidInfo.pid)) return
|
|
2423
|
+
if (!pidInfo) return "noop";
|
|
2424
|
+
if (!isProcessAlive(pidInfo.pid)) return "noop";
|
|
2379
2425
|
const verdict = await judgeRecordedBridge(pidInfo, resolveSessionName());
|
|
2380
|
-
if (!verdict.terminate) return
|
|
2381
|
-
await terminateBridgeProcess(pidInfo.pid, {
|
|
2426
|
+
if (!verdict.terminate) return "noop";
|
|
2427
|
+
const terminated = await terminateBridgeProcess(verdict.targetPid ?? pidInfo.pid, {
|
|
2382
2428
|
killProcessGroup: verdict.killProcessGroup
|
|
2383
2429
|
});
|
|
2384
2430
|
clearSelectedPageId();
|
|
2385
|
-
return
|
|
2431
|
+
return terminated ? "stopped" : "failed";
|
|
2386
2432
|
}
|
|
2387
2433
|
|
|
2388
2434
|
// vendor/chrome-devtools-axi/src/generation.ts
|
|
@@ -3931,12 +3977,15 @@ async function handleStart() {
|
|
|
3931
3977
|
const port = await ensureBridge();
|
|
3932
3978
|
return encode({ status: "ready", port });
|
|
3933
3979
|
}
|
|
3934
|
-
function formatStopOutput(
|
|
3935
|
-
|
|
3980
|
+
function formatStopOutput(outcome) {
|
|
3981
|
+
if (outcome === "failed") {
|
|
3982
|
+
throw new Error("bridge stop failed: the target survived SIGTERM and SIGKILL escalation");
|
|
3983
|
+
}
|
|
3984
|
+
return encode({ status: outcome === "stopped" ? "stopped" : "stopped (no-op)" });
|
|
3936
3985
|
}
|
|
3937
3986
|
async function handleStop() {
|
|
3938
|
-
const
|
|
3939
|
-
return formatStopOutput(
|
|
3987
|
+
const outcome = await stopBridge();
|
|
3988
|
+
return formatStopOutput(outcome);
|
|
3940
3989
|
}
|
|
3941
3990
|
async function handlePages() {
|
|
3942
3991
|
const result = await callTool("list_pages");
|
|
@@ -9950,7 +9950,13 @@ var import_node_child_process = require("node:child_process");
|
|
|
9950
9950
|
var import_node_crypto = require("node:crypto");
|
|
9951
9951
|
var import_node_os = __toESM(require("node:os"));
|
|
9952
9952
|
var import_node_path = __toESM(require("node:path"));
|
|
9953
|
-
var expandHome = (value) =>
|
|
9953
|
+
var expandHome = (value) => {
|
|
9954
|
+
if (value === "~") return import_node_os.default.homedir();
|
|
9955
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
9956
|
+
return import_node_path.default.join(import_node_os.default.homedir(), value.slice(2).replace(/\\/g, "/"));
|
|
9957
|
+
}
|
|
9958
|
+
return value;
|
|
9959
|
+
};
|
|
9954
9960
|
var STATE_DIR = import_node_path.default.resolve(process.env.PIE_TUI_USE_STATE_DIR ? expandHome(process.env.PIE_TUI_USE_STATE_DIR) : import_node_path.default.join(expandHome(process.env.PIE_CODING_AGENT_DIR || import_node_path.default.join(import_node_os.default.homedir(), ".pie")), "tui-use"));
|
|
9955
9961
|
var LOG_PATH = import_node_path.default.join(STATE_DIR, "daemon.log");
|
|
9956
9962
|
var PID_PATH = import_node_path.default.join(STATE_DIR, "daemon.pid");
|
|
@@ -10139,17 +10145,27 @@ async function startDaemon() {
|
|
|
10139
10145
|
if (error.code !== "EEXIST") throw error;
|
|
10140
10146
|
try {
|
|
10141
10147
|
const contents = import_node_fs.default.readFileSync(LOCK_PATH, "utf8");
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10148
|
+
let reclaim = false;
|
|
10149
|
+
try {
|
|
10150
|
+
const lock = JSON.parse(contents);
|
|
10151
|
+
let alive = true;
|
|
10152
|
+
if (!Number.isInteger(lock.pid) || lock.pid <= 0) alive = false;
|
|
10153
|
+
else {
|
|
10154
|
+
try {
|
|
10155
|
+
process.kill(lock.pid, 0);
|
|
10156
|
+
} catch (e) {
|
|
10157
|
+
if (e.code === "ESRCH") alive = false;
|
|
10158
|
+
}
|
|
10159
|
+
}
|
|
10160
|
+
if (!alive) reclaim = true;
|
|
10161
|
+
} catch {
|
|
10146
10162
|
try {
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10163
|
+
const mtimeMs = import_node_fs.default.statSync(LOCK_PATH).mtimeMs;
|
|
10164
|
+
if (Date.now() - mtimeMs > 5e3) reclaim = true;
|
|
10165
|
+
} catch {
|
|
10150
10166
|
}
|
|
10151
10167
|
}
|
|
10152
|
-
if (
|
|
10168
|
+
if (reclaim && import_node_fs.default.readFileSync(LOCK_PATH, "utf8") === contents) import_node_fs.default.unlinkSync(LOCK_PATH);
|
|
10153
10169
|
} catch {
|
|
10154
10170
|
}
|
|
10155
10171
|
await sleep(100);
|
|
@@ -7661,7 +7661,13 @@ function validateRequest(value) {
|
|
|
7661
7661
|
var import_node_crypto = require("node:crypto");
|
|
7662
7662
|
var import_node_os = __toESM(require("node:os"));
|
|
7663
7663
|
var import_node_path3 = __toESM(require("node:path"));
|
|
7664
|
-
var expandHome = (value) =>
|
|
7664
|
+
var expandHome = (value) => {
|
|
7665
|
+
if (value === "~") return import_node_os.default.homedir();
|
|
7666
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
7667
|
+
return import_node_path3.default.join(import_node_os.default.homedir(), value.slice(2).replace(/\\/g, "/"));
|
|
7668
|
+
}
|
|
7669
|
+
return value;
|
|
7670
|
+
};
|
|
7665
7671
|
var STATE_DIR = import_node_path3.default.resolve(process.env.PIE_TUI_USE_STATE_DIR ? expandHome(process.env.PIE_TUI_USE_STATE_DIR) : import_node_path3.default.join(expandHome(process.env.PIE_CODING_AGENT_DIR || import_node_path3.default.join(import_node_os.default.homedir(), ".pie")), "tui-use"));
|
|
7666
7672
|
var LOG_PATH = import_node_path3.default.join(STATE_DIR, "daemon.log");
|
|
7667
7673
|
var PID_PATH = import_node_path3.default.join(STATE_DIR, "daemon.pid");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
Agent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RTTGO2A6.js";
|
|
5
5
|
import {
|
|
6
6
|
FileSystemGateway,
|
|
7
7
|
completeSimple,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
getPlatformConfig,
|
|
11
11
|
hashText,
|
|
12
12
|
streamSimple
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-UD7KYQ6J.js";
|
|
14
14
|
import {
|
|
15
15
|
Type
|
|
16
16
|
} from "./chunk-XXGYUYXI.js";
|
|
@@ -1742,8 +1742,7 @@ function normalizeTaskDefs(args) {
|
|
|
1742
1742
|
if (def.model !== void 0 && !modelOverride) {
|
|
1743
1743
|
return { error: `Invalid task #${index + 1}: "model" must be a non-empty model reference such as "provider/model-id".` };
|
|
1744
1744
|
}
|
|
1745
|
-
|
|
1746
|
-
if (def.thinkingLevel !== void 0 && (!thinkingLevel || !SUBAGENT_THINKING_LEVELS.includes(thinkingLevel))) {
|
|
1745
|
+
if (def.thinkingLevel !== void 0 && (typeof def.thinkingLevel !== "string" || !SUBAGENT_THINKING_LEVELS.includes(def.thinkingLevel))) {
|
|
1747
1746
|
return { error: `Invalid task #${index + 1}: "thinkingLevel" must be one of ${SUBAGENT_THINKING_LEVELS.map((level) => `"${level}"`).join(", ")}.` };
|
|
1748
1747
|
}
|
|
1749
1748
|
normalized.push({
|
|
@@ -1752,7 +1751,7 @@ function normalizeTaskDefs(args) {
|
|
|
1752
1751
|
priority,
|
|
1753
1752
|
timeoutSeconds,
|
|
1754
1753
|
modelOverride,
|
|
1755
|
-
thinkingLevel
|
|
1754
|
+
thinkingLevel: def.thinkingLevel
|
|
1756
1755
|
});
|
|
1757
1756
|
}
|
|
1758
1757
|
return normalized;
|
|
@@ -2968,6 +2967,9 @@ var FileSessionStore = class {
|
|
|
2968
2967
|
throw new Error(`Session directory is a symbolic link; ${operation} refused: ${dir}`);
|
|
2969
2968
|
}
|
|
2970
2969
|
headStatus(sessionId) {
|
|
2970
|
+
if (sessionDirIsSymlink(this.pathsFor(sessionId).dir)) {
|
|
2971
|
+
return "missing";
|
|
2972
|
+
}
|
|
2971
2973
|
const head = this.tryReadHeadFile(sessionId);
|
|
2972
2974
|
if (head === "corrupt") {
|
|
2973
2975
|
return "corrupt";
|
|
@@ -3023,6 +3025,9 @@ var FileSessionStore = class {
|
|
|
3023
3025
|
* never reinitialize a damaged session to sequence 0.
|
|
3024
3026
|
*/
|
|
3025
3027
|
tryReadHeadFile(sessionId) {
|
|
3028
|
+
if (sessionDirIsSymlink(this.pathsFor(sessionId).dir)) {
|
|
3029
|
+
return null;
|
|
3030
|
+
}
|
|
3026
3031
|
const headPath = this.pathsFor(sessionId).headPath;
|
|
3027
3032
|
const durable = readDurableFileSync(this.gateway, headPath, (content) => this.parseHeadContent(content));
|
|
3028
3033
|
if (durable !== null) {
|
|
@@ -5239,6 +5244,16 @@ var AgentSessionQueue = class {
|
|
|
5239
5244
|
}
|
|
5240
5245
|
this.emitQueueChanged();
|
|
5241
5246
|
}
|
|
5247
|
+
/** Promote only an input still owned by this queue, never re-send agent-owned inputs. */
|
|
5248
|
+
promoteLatestFollowUp() {
|
|
5249
|
+
const input = this.queuedInputs.slice().reverse().find((queued) => queued.visibility === "user" && queued.mode === "followUp");
|
|
5250
|
+
if (!input || input.deliveredToAgent) return void 0;
|
|
5251
|
+
input.mode = "steer";
|
|
5252
|
+
input.deliverWhileStreaming = true;
|
|
5253
|
+
if (this.getIsStreaming()) this.deliverToAgent(input);
|
|
5254
|
+
this.emitQueueChanged();
|
|
5255
|
+
return cloneQueuedInput(input);
|
|
5256
|
+
}
|
|
5242
5257
|
deliverToAgent(queuedInput) {
|
|
5243
5258
|
if (queuedInput.deliveredToAgent) {
|
|
5244
5259
|
return;
|
|
@@ -6399,6 +6414,12 @@ var AgentSessionController = class {
|
|
|
6399
6414
|
drainQueuedInputsForEditor() {
|
|
6400
6415
|
return this.queue.drainForEditor();
|
|
6401
6416
|
}
|
|
6417
|
+
/** Upgrade the latest visible follow-up that has not been delivered to the agent. */
|
|
6418
|
+
promoteLatestFollowUpToSteer() {
|
|
6419
|
+
const promoted = this.disposed ? void 0 : this.queue.promoteLatestFollowUp();
|
|
6420
|
+
if (promoted && !this.isStreaming) this.requestQueueDispatch();
|
|
6421
|
+
return promoted;
|
|
6422
|
+
}
|
|
6402
6423
|
replaceQueuedInputText(search, replacement) {
|
|
6403
6424
|
this.queue.replaceText(search, replacement);
|
|
6404
6425
|
}
|
|
@@ -8770,7 +8791,7 @@ function createReadTool(cwd, options) {
|
|
|
8770
8791
|
return {
|
|
8771
8792
|
name: "read",
|
|
8772
8793
|
label: "read",
|
|
8773
|
-
description: `Read a file's contents. Use this before editing, and use offset/limit for large files.
|
|
8794
|
+
description: `Read a file's contents. Use this before editing, and use offset/limit for large files. Images are attached for the current model when it supports vision; otherwise a configured file-understanding service analyzes them. Video, audio, and documents require a configured understanding service. Pass question to specify what to focus on; it does not force a separate model request. Example: read_file path='Scripts/PlayerController.cs' or read_file path='Data/config.json'. ${pathResolutionDescription} For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). When you need the full file, continue with a larger offset until complete.`,
|
|
8774
8795
|
parameters: readSchema,
|
|
8775
8796
|
execute: async (_toolCallId, params, signal) => {
|
|
8776
8797
|
const { path: path4, root, offset, limit, question } = params;
|
|
@@ -8843,7 +8864,7 @@ function createReadTool(cwd, options) {
|
|
|
8843
8864
|
});
|
|
8844
8865
|
return;
|
|
8845
8866
|
}
|
|
8846
|
-
if (magicInfo?.kind === "image" &&
|
|
8867
|
+
if (magicInfo?.kind === "image" && options?.understandFile && (!INLINE_IMAGE_MIME_TYPES.has(magicInfo.mimeType) || stat.size > MAX_INLINE_IMAGE_BYTES)) {
|
|
8847
8868
|
resolve3(await options.understandFile({
|
|
8848
8869
|
absolutePath,
|
|
8849
8870
|
displayPath: path4,
|
|
@@ -8859,7 +8880,7 @@ function createReadTool(cwd, options) {
|
|
|
8859
8880
|
}
|
|
8860
8881
|
const imageInfo = options?.allowBinary === false || magicInfo?.kind !== "image" || !INLINE_IMAGE_MIME_TYPES.has(magicInfo.mimeType) ? void 0 : await readImageInfo(absolutePath, fs2);
|
|
8861
8882
|
if (imageInfo) {
|
|
8862
|
-
if (
|
|
8883
|
+
if (options?.understandFile) {
|
|
8863
8884
|
resolve3(await options.understandFile({
|
|
8864
8885
|
absolutePath,
|
|
8865
8886
|
displayPath: path4,
|
|
@@ -8874,7 +8895,8 @@ function createReadTool(cwd, options) {
|
|
|
8874
8895
|
const dimensionText = imageInfo.width && imageInfo.height ? `, ${imageInfo.width}x${imageInfo.height}` : "";
|
|
8875
8896
|
resolve3({
|
|
8876
8897
|
content: [
|
|
8877
|
-
{ type: "text", text: `Read image file [${imageInfo.mimeType}${dimensionText}]. Original image attached as an image block; for very large images, prefer a smaller crop or resized copy before rereading
|
|
8898
|
+
{ type: "text", text: `Read image file [${imageInfo.mimeType}${dimensionText}]. Original image attached as an image block; for very large images, prefer a smaller crop or resized copy before rereading.${question?.trim() ? `
|
|
8899
|
+
Focus: ${question.trim()}` : ""}` },
|
|
8878
8900
|
{ type: "image", data: imageInfo.base64, mimeType: imageInfo.mimeType }
|
|
8879
8901
|
],
|
|
8880
8902
|
details: {
|
|
@@ -13446,6 +13468,21 @@ function createReadFileUnderstandingHandler(deps) {
|
|
|
13446
13468
|
async function understandFileWithModel(deps, request) {
|
|
13447
13469
|
const purpose = `read_file.${request.kind}`;
|
|
13448
13470
|
const agentModel = deps.getAgentModel();
|
|
13471
|
+
if (request.kind === "image" && request.imageInfo && agentModel?.input.includes("image")) {
|
|
13472
|
+
if (request.signal?.aborted) throw new Error("Operation aborted");
|
|
13473
|
+
return {
|
|
13474
|
+
content: [
|
|
13475
|
+
{ type: "text", text: `Read image file ${request.displayPath} [${request.mimeType}]. Original image attached for the current model.${request.question?.trim() ? `
|
|
13476
|
+
Focus: ${request.question.trim()}` : ""}` },
|
|
13477
|
+
{ type: "image", data: request.imageInfo.base64, mimeType: request.imageInfo.mimeType }
|
|
13478
|
+
],
|
|
13479
|
+
details: {
|
|
13480
|
+
image: { mimeType: request.imageInfo.mimeType, width: request.imageInfo.width, height: request.imageInfo.height },
|
|
13481
|
+
understanding: { purpose, kind: request.kind, mimeType: request.mimeType, agentModel: getModelLabel(agentModel), routeSource: "current_model", inputMode: "nativeAttachment" }
|
|
13482
|
+
},
|
|
13483
|
+
isError: false
|
|
13484
|
+
};
|
|
13485
|
+
}
|
|
13449
13486
|
const singleDecision = deps.resolveToolModel(purpose);
|
|
13450
13487
|
const candidateDecisions = deps.resolveToolModelCandidates?.(purpose) ?? [singleDecision];
|
|
13451
13488
|
const sessionId = deps.getSessionId() || `read-file-${Date.now()}`;
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
createSharedWebSearchTool,
|
|
9
9
|
interpretShellExit,
|
|
10
10
|
requestInteraction
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LO2V5DZZ.js";
|
|
12
12
|
import {
|
|
13
13
|
getBuiltinDir,
|
|
14
14
|
getConfigDir
|
|
@@ -543,9 +543,24 @@ function createBashTool(defaultCwd, options) {
|
|
|
543
543
|
totalNewlines += data.reduce((count, byte) => count + (byte === 10 ? 1 : 0), 0);
|
|
544
544
|
if (headBytes >= maxHeadBytes) return;
|
|
545
545
|
const prefix = data.subarray(0, maxHeadBytes - headBytes);
|
|
546
|
-
headChunks.push(prefix);
|
|
546
|
+
headChunks.push(Buffer.from(prefix));
|
|
547
547
|
headBytes += prefix.length;
|
|
548
548
|
};
|
|
549
|
+
const appendRollingChunk = (data) => {
|
|
550
|
+
const owned = Buffer.from(data);
|
|
551
|
+
chunks.push(owned);
|
|
552
|
+
chunksBytes += owned.length;
|
|
553
|
+
while (chunksBytes > maxChunksBytes && chunks.length > 1) {
|
|
554
|
+
const removed = chunks.shift();
|
|
555
|
+
chunksBytes -= removed.length;
|
|
556
|
+
}
|
|
557
|
+
if (chunks.length === 1 && chunksBytes > maxChunksBytes) {
|
|
558
|
+
const only = chunks[0];
|
|
559
|
+
const tail = only.subarray(only.length - maxChunksBytes);
|
|
560
|
+
chunks[0] = Buffer.from(tail);
|
|
561
|
+
chunksBytes = tail.length;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
549
564
|
let timedOut = false;
|
|
550
565
|
let processExited = false;
|
|
551
566
|
let exitCode = null;
|
|
@@ -641,12 +656,7 @@ function createBashTool(defaultCwd, options) {
|
|
|
641
656
|
return;
|
|
642
657
|
}
|
|
643
658
|
}
|
|
644
|
-
|
|
645
|
-
chunksBytes += data.length;
|
|
646
|
-
while (chunksBytes > maxChunksBytes && chunks.length > 1) {
|
|
647
|
-
const removed = chunks.shift();
|
|
648
|
-
chunksBytes -= removed.length;
|
|
649
|
-
}
|
|
659
|
+
appendRollingChunk(data);
|
|
650
660
|
if (onUpdate) {
|
|
651
661
|
const fullBuffer = Buffer.concat(chunks);
|
|
652
662
|
const fullText = fullBuffer.toString("utf-8");
|
|
@@ -700,12 +710,7 @@ function createBashTool(defaultCwd, options) {
|
|
|
700
710
|
return;
|
|
701
711
|
}
|
|
702
712
|
}
|
|
703
|
-
|
|
704
|
-
chunksBytes += data.length;
|
|
705
|
-
while (chunksBytes > maxChunksBytes && chunks.length > 1) {
|
|
706
|
-
const removed = chunks.shift();
|
|
707
|
-
chunksBytes -= removed.length;
|
|
708
|
-
}
|
|
713
|
+
appendRollingChunk(data);
|
|
709
714
|
});
|
|
710
715
|
const finishExecution = async (code, sig, stdioIncomplete = false) => {
|
|
711
716
|
if (settled) return;
|
|
@@ -1171,7 +1176,12 @@ function createCliRenderedPageReader() {
|
|
|
1171
1176
|
networkRequests: linesOf(stripHelpHints(networkOutput))
|
|
1172
1177
|
};
|
|
1173
1178
|
} finally {
|
|
1174
|
-
|
|
1179
|
+
try {
|
|
1180
|
+
await runAxi(["stop"], { env, timeoutMs: 15e3 });
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
process.stderr.write(`[rendered-page-reader] axi stop after read failed: ${error instanceof Error ? error.message : String(error)}
|
|
1183
|
+
`);
|
|
1184
|
+
}
|
|
1175
1185
|
}
|
|
1176
1186
|
};
|
|
1177
1187
|
}
|
|
@@ -2960,6 +2960,7 @@ function convertMessages(model, context, compat) {
|
|
|
2960
2960
|
const hasContent = content !== null && content !== void 0 && (typeof content === "string" ? content.length > 0 : Array.isArray(content) && content.length > 0);
|
|
2961
2961
|
if (hasContent || assistantMsg.tool_calls) params.push(assistantMsg);
|
|
2962
2962
|
} else if (msg.role === "toolResult") {
|
|
2963
|
+
const attachments = [];
|
|
2963
2964
|
for (; i < transformedMessages.length && transformedMessages[i].role === "toolResult"; i++) {
|
|
2964
2965
|
const toolMsg = transformedMessages[i];
|
|
2965
2966
|
const textResult = toolMsg.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
@@ -2970,7 +2971,15 @@ function convertMessages(model, context, compat) {
|
|
|
2970
2971
|
};
|
|
2971
2972
|
if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
|
|
2972
2973
|
params.push(toolResultMsg);
|
|
2974
|
+
if (model.input.includes("image")) {
|
|
2975
|
+
const images = toolMsg.content.filter((c) => c.type === "image");
|
|
2976
|
+
if (images.length > 0) {
|
|
2977
|
+
attachments.push({ type: "text", text: `Images from tool ${toolMsg.toolName ?? "unknown"} (call ${toolMsg.toolCallId}):` });
|
|
2978
|
+
for (const image of images) attachments.push(...convertUserContentItem(image));
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2973
2981
|
}
|
|
2982
|
+
if (attachments.length > 0) params.push({ role: "user", content: attachments });
|
|
2974
2983
|
i -= 1;
|
|
2975
2984
|
}
|
|
2976
2985
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
EventStream
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UD7KYQ6J.js";
|
|
5
5
|
import "./chunk-XXGYUYXI.js";
|
|
6
6
|
import "./chunk-LZQXQOPJ.js";
|
|
7
7
|
|