@proagentstore/cli 0.4.11 → 0.4.13
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.
|
@@ -33,9 +33,14 @@ export class HeadlessSession {
|
|
|
33
33
|
this.cmdArgs = args;
|
|
34
34
|
this.binName = (this.cmdBin.split("/").pop() || this.cmdBin) || "cli";
|
|
35
35
|
}
|
|
36
|
-
/** True while the agent process is running.
|
|
36
|
+
/** True while the agent process is running. NOTE: do NOT use `proc.killed` — Node sets
|
|
37
|
+
* it true the instant a signal is DELIVERED, not when the process exits. interrupt()
|
|
38
|
+
* SIGINTs to abort a turn while the process keeps running, so `killed` gave a false
|
|
39
|
+
* "dead" → input() then spawned a SECOND process (orphaning the first). exitCode is
|
|
40
|
+
* null while running and set on normal exit; signalCode is set when a signal actually
|
|
41
|
+
* terminated it — together they're the real liveness signal. */
|
|
37
42
|
get alive() {
|
|
38
|
-
return this.proc !== null && this.proc.exitCode === null &&
|
|
43
|
+
return this.proc !== null && this.proc.exitCode === null && this.proc.signalCode === null;
|
|
39
44
|
}
|
|
40
45
|
/** Idle = ready for the next instruction. */
|
|
41
46
|
get ready() {
|
|
@@ -275,8 +280,12 @@ export function buildClaudeArgs(userArgs, resumeId) {
|
|
|
275
280
|
i++;
|
|
276
281
|
continue;
|
|
277
282
|
}
|
|
278
|
-
|
|
279
|
-
|
|
283
|
+
// Push every user token as-is. A previous `!args.includes(a)` dedup silently
|
|
284
|
+
// dropped a REPEATED flag token (e.g. the 2nd `--add-dir` in `--add-dir /a
|
|
285
|
+
// --add-dir /b`), which orphaned its value (`/b` became a stray positional).
|
|
286
|
+
// Our own structural flags are already protected via RESERVED_CLAUDE_FLAGS, so
|
|
287
|
+
// no dedup is needed here.
|
|
288
|
+
args.push(a);
|
|
280
289
|
}
|
|
281
290
|
if (!args.includes("--dangerously-skip-permissions"))
|
|
282
291
|
args.push("--dangerously-skip-permissions");
|
|
@@ -54,7 +54,11 @@ export class CodingRuntime {
|
|
|
54
54
|
snapshot(sessionId) {
|
|
55
55
|
const session = this.require(sessionId);
|
|
56
56
|
const alive = session.alive;
|
|
57
|
-
|
|
57
|
+
// ALWAYS return the transcript — it holds the produced output AND the
|
|
58
|
+
// `[exited with code N]` / `[error]` lines recorded on exit. Blanking it when the
|
|
59
|
+
// process is dead lost exactly the output + failure reason the brain/console needs
|
|
60
|
+
// to diagnose a crash or read a one-shot CLI's final result.
|
|
61
|
+
const pane = clip(session.snapshot());
|
|
58
62
|
return {
|
|
59
63
|
sessionId,
|
|
60
64
|
pane,
|
|
@@ -67,9 +67,9 @@ if (!config.token && !LOOPBACK.has(config.host)) {
|
|
|
67
67
|
process.exit(1);
|
|
68
68
|
}
|
|
69
69
|
const started = await startRunnerServer(config);
|
|
70
|
-
process.stdout.write(`
|
|
70
|
+
process.stdout.write(`ProAgentStore browser runtime listening at ${started.url}\n`);
|
|
71
71
|
process.stdout.write(`Data dir: ${config.dataDir}\n`);
|
|
72
|
-
process.stdout.write("Control plane: PAGS; runtime plane:
|
|
72
|
+
process.stdout.write("Control plane: PAGS; runtime plane: PAGS; brain placement: PAGS; runner role: tool-executor\n");
|
|
73
73
|
if (config.token)
|
|
74
74
|
process.stdout.write("Auth: bearer token required\n");
|
|
75
75
|
if (config.instanceId)
|
|
@@ -74,10 +74,10 @@ export class LocalRunner {
|
|
|
74
74
|
}
|
|
75
75
|
capabilities() {
|
|
76
76
|
return {
|
|
77
|
-
runtime: "
|
|
77
|
+
runtime: "pags-browser-runtime",
|
|
78
78
|
brainPlacement: "pags",
|
|
79
79
|
controlPlane: "pags",
|
|
80
|
-
runtimePlane: "
|
|
80
|
+
runtimePlane: "pags",
|
|
81
81
|
runnerRole: "tool-executor",
|
|
82
82
|
capabilities: [...CAPABILITIES, ...CodingRuntime.capabilities()],
|
|
83
83
|
taskTypes: ["echo", "browser.open", "job.apply_agent", ...CodingRuntime.taskTypes()],
|
|
@@ -42,10 +42,10 @@ async function route(runner, req, res) {
|
|
|
42
42
|
if ((req.method === "GET" || req.method === "POST") && path === "/health") {
|
|
43
43
|
return json(res, 200, {
|
|
44
44
|
ok: true,
|
|
45
|
-
service: "
|
|
45
|
+
service: "proagentstore-browser-runtime",
|
|
46
46
|
brainPlacement: "pags",
|
|
47
47
|
controlPlane: "pags",
|
|
48
|
-
runtimePlane: "
|
|
48
|
+
runtimePlane: "pags",
|
|
49
49
|
instanceId: runner.config.instanceId,
|
|
50
50
|
});
|
|
51
51
|
}
|
package/dist/index.js
CHANGED
|
@@ -932,9 +932,9 @@ function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, f
|
|
|
932
932
|
}
|
|
933
933
|
function createRunnerCommand() {
|
|
934
934
|
const command = new Command6("runner").description(
|
|
935
|
-
"Manage the local
|
|
935
|
+
"Manage the local ProAgentStore browser runtime for ProAgentStore agents"
|
|
936
936
|
);
|
|
937
|
-
command.command("start").description("Start the local
|
|
937
|
+
command.command("start").description("Start the local ProAgentStore browser runtime in the foreground").option("--host <host>", "Host to bind", "127.0.0.1").option("--port <port>", "Port to bind", "49171").option("--data-dir <path>", "Runner data directory").option("--token <token>", "Require this bearer token").option("--instance-id <id>", "Bind runner requests to a PAGS instance id").option("--headless", "Run Playwright headless").action(async (opts) => {
|
|
938
938
|
await startRunnerForeground(opts);
|
|
939
939
|
});
|
|
940
940
|
command.command("connect <instanceIds...>").description("Start ONE local runtime, connect via WebSocket relay, and register it for every given PAGS instance").option("--host <host>", "Host to bind", "127.0.0.1").option("--port <port>", "Port to bind", "49171").option("--data-dir <path>", "Runner data directory").option("--token <token>", "Runner bearer token. Defaults to PAGS_RUNNER_TOKEN or a generated token").option("--headless", "Run Playwright headless").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--runner-version <version>", "Runner version").option("--force", "Take over from another connected machine").action(async (instanceIds, opts) => {
|
|
@@ -952,10 +952,14 @@ function createRunnerCommand() {
|
|
|
952
952
|
});
|
|
953
953
|
runner.stdout?.on("data", (data) => process.stdout.write(data));
|
|
954
954
|
runner.stderr?.on("data", (data) => process.stderr.write(data));
|
|
955
|
+
let shuttingDown = false;
|
|
955
956
|
runner.on("exit", (code) => {
|
|
956
|
-
if (
|
|
957
|
+
if (shuttingDown) return;
|
|
958
|
+
writeError(`Local browser runtime exited unexpectedly${code ? ` (code ${code})` : ""}. Run \`pags up\` again to reconnect.`);
|
|
959
|
+
process.exit(code ?? 1);
|
|
957
960
|
});
|
|
958
961
|
const shutdown = () => {
|
|
962
|
+
shuttingDown = true;
|
|
959
963
|
if (!runner.killed) runner.kill("SIGTERM");
|
|
960
964
|
};
|
|
961
965
|
process.once("SIGINT", () => {
|
|
@@ -968,7 +972,7 @@ function createRunnerCommand() {
|
|
|
968
972
|
});
|
|
969
973
|
try {
|
|
970
974
|
await waitForLocalRunner({ url: localUrl, token: runnerToken, instanceId: primary });
|
|
971
|
-
writeLine(`Local
|
|
975
|
+
writeLine(`Local browser runtime healthy at ${localUrl}`);
|
|
972
976
|
await connectViaRelay(instanceIds, localUrl, runnerToken, opts, Boolean(opts.force));
|
|
973
977
|
await new Promise((resolvePromise) => {
|
|
974
978
|
runner.on("exit", () => resolvePromise());
|
|
@@ -978,12 +982,12 @@ function createRunnerCommand() {
|
|
|
978
982
|
throw error;
|
|
979
983
|
}
|
|
980
984
|
});
|
|
981
|
-
command.command("status").description("Check local
|
|
985
|
+
command.command("status").description("Check local browser runtime health and capabilities").option("--url <url>", "Runner URL").option("--token <token>", "Runner bearer token").option("--instance-id <id>", "PAGS instance id header").action(async (opts) => {
|
|
982
986
|
const health = await requestRunner("GET", "/health", opts);
|
|
983
987
|
const capabilities = await requestRunner("GET", "/capabilities", opts);
|
|
984
988
|
writeLine(JSON.stringify({ health, capabilities }, null, 2));
|
|
985
989
|
});
|
|
986
|
-
command.command("task").description("Create a local
|
|
990
|
+
command.command("task").description("Create a local browser runtime task").requiredOption("--type <type>", "Task type, e.g. echo or browser.open").option("--url <url>", "Runner URL").option("--token <token>", "Runner bearer token").option("--instance-id <id>", "PAGS instance id header").option("--input <json>", "Task input JSON").option("--job-url <url>", "Shortcut input for browser.open").option("--approve", "Create task in needs_approval state").option("--approval-prompt <text>", "Approval prompt").action(
|
|
987
991
|
async (opts) => {
|
|
988
992
|
let input = {};
|
|
989
993
|
if (opts.input) {
|
|
@@ -1004,7 +1008,7 @@ function createRunnerCommand() {
|
|
|
1004
1008
|
writeLine(JSON.stringify(task, null, 2));
|
|
1005
1009
|
}
|
|
1006
1010
|
);
|
|
1007
|
-
command.command("register <instanceId>").description("Register a local or managed
|
|
1011
|
+
command.command("register <instanceId>").description("Register a local or managed browser runtime endpoint with a PAGS instance").requiredOption("--endpoint-url <url>", "browser runtime endpoint URL to store in PAGS").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--runner-token <token>", "browser runtime bearer token to store in PAGS").option("--url <url>", "Local browser runtime URL to probe for capabilities").option("--token <token>", "Local browser runtime bearer token for capability probe").option("--instance-id <id>", "PAGS instance id header for capability probe").option("--placement <placement>", "Runtime placement: local or managed", "local").option("--runner-version <version>", "Runner version").option("--capability <name>", "Runtime capability; repeatable", collectCapability, []).option("--probe", "Read capabilities from the browser runtime before registering").action(async (instanceId, opts) => {
|
|
1008
1012
|
let capabilities = opts.capability || [];
|
|
1009
1013
|
if (opts.probe) {
|
|
1010
1014
|
const data = await requestRunner("GET", "/capabilities", {
|
|
@@ -1018,7 +1022,7 @@ function createRunnerCommand() {
|
|
|
1018
1022
|
const result = await requestPags("POST", `/v1/instances/${apiPathSegment(instanceId)}/runtime`, opts, body);
|
|
1019
1023
|
writeLine(JSON.stringify(result, null, 2));
|
|
1020
1024
|
});
|
|
1021
|
-
command.command("runtime <instanceId>").description("Read the PAGS runtime registration for an instance").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--probe", "Ask PAGS to probe /health and /capabilities on the
|
|
1025
|
+
command.command("runtime <instanceId>").description("Read the PAGS runtime registration for an instance").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--probe", "Ask PAGS to probe /health and /capabilities on the browser runtime").action(async (instanceId, opts) => {
|
|
1022
1026
|
const path = opts.probe ? `/v1/instances/${apiPathSegment(instanceId)}/runtime/status` : `/v1/instances/${apiPathSegment(instanceId)}/runtime`;
|
|
1023
1027
|
const result = await requestPags("GET", path, opts);
|
|
1024
1028
|
writeLine(JSON.stringify(result, null, 2));
|
|
@@ -1027,7 +1031,7 @@ function createRunnerCommand() {
|
|
|
1027
1031
|
const result = await requestPags("DELETE", `/v1/instances/${apiPathSegment(instanceId)}/runtime`, opts);
|
|
1028
1032
|
writeLine(JSON.stringify(result, null, 2));
|
|
1029
1033
|
});
|
|
1030
|
-
command.command("run <instanceId>").description("Create a task through PAGS on an instance's registered
|
|
1034
|
+
command.command("run <instanceId>").description("Create a task through PAGS on an instance's registered browser runtime").requiredOption("--type <type>", "Task type, e.g. echo or browser.open").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--input <json>", "Task input JSON").option("--job-url <url>", "Shortcut input for browser.open").option("--approve", "Create task in needs_approval state").option("--approval-prompt <text>", "Approval prompt").action(
|
|
1031
1035
|
async (instanceId, opts) => {
|
|
1032
1036
|
let input = {};
|
|
1033
1037
|
if (opts.input) {
|
|
@@ -1048,7 +1052,7 @@ function createRunnerCommand() {
|
|
|
1048
1052
|
writeLine(JSON.stringify(result, null, 2));
|
|
1049
1053
|
}
|
|
1050
1054
|
);
|
|
1051
|
-
command.command("approve-task <instanceId> <taskId>").description("Approve a registered
|
|
1055
|
+
command.command("approve-task <instanceId> <taskId>").description("Approve a registered browser runtime task through PAGS").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").action(async (instanceId, taskId, opts) => {
|
|
1052
1056
|
const result = await requestPags(
|
|
1053
1057
|
"POST",
|
|
1054
1058
|
`/v1/instances/${apiPathSegment(instanceId)}/tasks/${apiPathSegment(taskId)}/approve`,
|
|
@@ -1056,7 +1060,7 @@ function createRunnerCommand() {
|
|
|
1056
1060
|
);
|
|
1057
1061
|
writeLine(JSON.stringify(result, null, 2));
|
|
1058
1062
|
});
|
|
1059
|
-
command.command("cancel-task <instanceId> <taskId>").description("Cancel a registered
|
|
1063
|
+
command.command("cancel-task <instanceId> <taskId>").description("Cancel a registered browser runtime task through PAGS").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").action(async (instanceId, taskId, opts) => {
|
|
1060
1064
|
const result = await requestPags(
|
|
1061
1065
|
"POST",
|
|
1062
1066
|
`/v1/instances/${apiPathSegment(instanceId)}/tasks/${apiPathSegment(taskId)}/cancel`,
|
|
@@ -1064,7 +1068,7 @@ function createRunnerCommand() {
|
|
|
1064
1068
|
);
|
|
1065
1069
|
writeLine(JSON.stringify(result, null, 2));
|
|
1066
1070
|
});
|
|
1067
|
-
command.command("task-events <instanceId>").description("Read registered
|
|
1071
|
+
command.command("task-events <instanceId>").description("Read registered browser runtime task events through PAGS").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--limit <n>", "Number of events", "50").action(async (instanceId, opts) => {
|
|
1068
1072
|
const result = await requestPags(
|
|
1069
1073
|
"GET",
|
|
1070
1074
|
`/v1/instances/${apiPathSegment(instanceId)}/task-events?limit=${Number(opts.limit) || 50}`,
|
|
@@ -1076,11 +1080,11 @@ function createRunnerCommand() {
|
|
|
1076
1080
|
const task = await requestRunner("POST", `/tasks/${apiPathSegment(taskId)}/approve`, opts);
|
|
1077
1081
|
writeLine(JSON.stringify(task, null, 2));
|
|
1078
1082
|
});
|
|
1079
|
-
command.command("cancel <taskId>").description("Cancel a local
|
|
1083
|
+
command.command("cancel <taskId>").description("Cancel a local browser runtime task").option("--url <url>", "Runner URL").option("--token <token>", "Runner bearer token").option("--instance-id <id>", "PAGS instance id header").action(async (taskId, opts) => {
|
|
1080
1084
|
const task = await requestRunner("POST", `/tasks/${apiPathSegment(taskId)}/cancel`, opts);
|
|
1081
1085
|
writeLine(JSON.stringify(task, null, 2));
|
|
1082
1086
|
});
|
|
1083
|
-
command.command("events").description("List recent
|
|
1087
|
+
command.command("events").description("List recent browser runtime events").option("--url <url>", "Runner URL").option("--token <token>", "Runner bearer token").option("--instance-id <id>", "PAGS instance id header").option("--limit <n>", "Number of events", "50").action(async (opts) => {
|
|
1084
1088
|
const events = await requestRunner("GET", `/events?limit=${Number(opts.limit) || 50}`, opts);
|
|
1085
1089
|
writeLine(JSON.stringify(events, null, 2));
|
|
1086
1090
|
});
|
|
@@ -1289,7 +1293,7 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1289
1293
|
printStatus(state);
|
|
1290
1294
|
continue;
|
|
1291
1295
|
}
|
|
1292
|
-
if (trimmed.includes("
|
|
1296
|
+
if (trimmed.includes("browser runtime listening")) {
|
|
1293
1297
|
state.runner = "online";
|
|
1294
1298
|
state.lastEvent = "Runner started";
|
|
1295
1299
|
printStatus(state);
|