@proagentstore/cli 0.4.119 → 0.4.121
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/browser-runner/local-apply/bridge.js +8 -2
- package/dist/index.js +134 -61
- package/package.json +1 -1
|
@@ -55,8 +55,14 @@ const PAGINATION_NAME = /^(next|previous|prev|more|load more|show more|see more|
|
|
|
55
55
|
const STEP_NAME = /^(next|continue|back|previous|add( another)?|upload|attach|browse|choose( a)? file|select( a)? file|remove|edit|expand|collapse|show more)\b/i;
|
|
56
56
|
/** A tick that is a legal or privacy agreement: the owner's call, not the CLI's. */
|
|
57
57
|
const CONSENT_NAME = /\b(agree|consent|terms|privacy|acknowledge|certify|accept|declaration|gdpr)\b/i;
|
|
58
|
-
/**
|
|
59
|
-
|
|
58
|
+
/**
|
|
59
|
+
* A field that is a credential: a sign-in, never an application answer. It includes the box an emailed or texted
|
|
60
|
+
* one-time code goes into (#1014) — "Enter the 6-digit code we emailed you", "Sign-in code" — which has no password
|
|
61
|
+
* field beside it, so the page check never sees a sign-in: the CLI is stopped at the field and the owner takes the
|
|
62
|
+
* exact session over (#1013). The Runner holds no mailbox access and never reads, asks for or types a code itself.
|
|
63
|
+
* Ordinary "code" answers (a postcode, a promo or referral code) are not credentials.
|
|
64
|
+
*/
|
|
65
|
+
export const CREDENTIAL_NAME = /password|passcode|one[- ]?time|\botp\b|2fa|two[- ]factor|\b(?:verification|security|sign[- ]?in|log[- ]?in|login|access|authentication|confirmation) code\b|\b\d[- ]?digit code\b|\bcode (?:that )?we (?:sent|emailed|texted)\b|\bcode (?:sent|emailed|texted) to\b/i;
|
|
60
66
|
/** Keys that move between fields without entering or activating anything. */
|
|
61
67
|
const SAFE_KEYS = /^(Tab|Shift\+Tab|Arrow(Up|Down|Left|Right)|Escape|Home|End|PageUp|PageDown)$/;
|
|
62
68
|
/**
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
|
|
12
12
|
// src/index.ts
|
|
13
13
|
import { createRequire as createRequire3 } from "module";
|
|
14
|
-
import { Command as
|
|
14
|
+
import { Command as Command10 } from "commander";
|
|
15
15
|
|
|
16
16
|
// src/commands/check.ts
|
|
17
17
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -541,44 +541,44 @@ function stringList(value) {
|
|
|
541
541
|
if (!Array.isArray(value)) return [];
|
|
542
542
|
return value.filter((n) => typeof n === "string" && n.trim().length > 0).map((n) => n.trim());
|
|
543
543
|
}
|
|
544
|
-
function withName(
|
|
544
|
+
function withName(identity2, name) {
|
|
545
545
|
const current = name.trim();
|
|
546
|
-
const prev =
|
|
546
|
+
const prev = identity2?.names ?? [];
|
|
547
547
|
const names = current ? [current, ...prev.filter((n) => n !== current)] : [...prev];
|
|
548
|
-
return { id:
|
|
548
|
+
return { id: identity2?.id ?? "", names: names.slice(0, MAX_NAMES), declined: identity2?.declined ?? [] };
|
|
549
549
|
}
|
|
550
|
-
function withClaimedNames(
|
|
550
|
+
function withClaimedNames(identity2, claimed) {
|
|
551
551
|
const add = claimed.map((n) => n.trim()).filter(Boolean);
|
|
552
|
-
const ordered = [
|
|
552
|
+
const ordered = [identity2.names[0], ...add, ...identity2.names.slice(1)].filter((n) => !!n);
|
|
553
553
|
const names = [];
|
|
554
554
|
for (const n of ordered) if (!names.includes(n)) names.push(n);
|
|
555
555
|
return {
|
|
556
|
-
id:
|
|
556
|
+
id: identity2.id,
|
|
557
557
|
names: names.slice(0, MAX_NAMES),
|
|
558
|
-
declined: (
|
|
558
|
+
declined: (identity2.declined ?? []).filter((n) => !add.includes(n))
|
|
559
559
|
};
|
|
560
560
|
}
|
|
561
|
-
function withUnclaimedName(
|
|
561
|
+
function withUnclaimedName(identity2, name) {
|
|
562
562
|
const unclaim = name.trim();
|
|
563
|
-
if (!unclaim) return
|
|
564
|
-
const names =
|
|
565
|
-
const declined = [...
|
|
563
|
+
if (!unclaim) return identity2;
|
|
564
|
+
const names = identity2.names.filter((n) => n !== unclaim);
|
|
565
|
+
const declined = [...identity2.declined ?? []];
|
|
566
566
|
if (!declined.includes(unclaim)) declined.push(unclaim);
|
|
567
|
-
return { id:
|
|
567
|
+
return { id: identity2.id, names, declined: declined.slice(-MAX_DECLINED) };
|
|
568
568
|
}
|
|
569
|
-
function withDeclinedNames(
|
|
570
|
-
const out = [...
|
|
569
|
+
function withDeclinedNames(identity2, declined) {
|
|
570
|
+
const out = [...identity2.declined ?? []];
|
|
571
571
|
for (const raw of declined) {
|
|
572
572
|
const name = raw.trim();
|
|
573
|
-
if (!name || out.includes(name) ||
|
|
573
|
+
if (!name || out.includes(name) || identity2.names.includes(name)) continue;
|
|
574
574
|
out.push(name);
|
|
575
575
|
}
|
|
576
|
-
return { id:
|
|
576
|
+
return { id: identity2.id, names: identity2.names, declined: out.slice(-MAX_DECLINED) };
|
|
577
577
|
}
|
|
578
|
-
function saveMachineIdentity(
|
|
578
|
+
function saveMachineIdentity(identity2) {
|
|
579
579
|
try {
|
|
580
580
|
mkdirSync3(CONFIG_DIR2, { recursive: true });
|
|
581
|
-
writeFileSync3(MACHINE_FILE, JSON.stringify(
|
|
581
|
+
writeFileSync3(MACHINE_FILE, JSON.stringify(identity2, null, 2));
|
|
582
582
|
return true;
|
|
583
583
|
} catch {
|
|
584
584
|
return false;
|
|
@@ -630,9 +630,9 @@ function parseNodesResponse(data) {
|
|
|
630
630
|
}
|
|
631
631
|
return out;
|
|
632
632
|
}
|
|
633
|
-
function claimCandidates(nodes,
|
|
634
|
-
const mine = new Set(
|
|
635
|
-
const declined = new Set(
|
|
633
|
+
function claimCandidates(nodes, identity2) {
|
|
634
|
+
const mine = new Set(identity2.names);
|
|
635
|
+
const declined = new Set(identity2.declined ?? []);
|
|
636
636
|
const seen = /* @__PURE__ */ new Set();
|
|
637
637
|
const out = [];
|
|
638
638
|
for (const n of nodes) {
|
|
@@ -647,14 +647,14 @@ function claimCandidates(nodes, identity) {
|
|
|
647
647
|
}
|
|
648
648
|
return out.sort((a, b) => stampMs(b.lastSeenAt) - stampMs(a.lastSeenAt));
|
|
649
649
|
}
|
|
650
|
-
function resolveClaimByName(requested, nodes,
|
|
650
|
+
function resolveClaimByName(requested, nodes, identity2) {
|
|
651
651
|
const byName = new Map(nodes.map((n) => [n.node, n]));
|
|
652
652
|
const claim = [];
|
|
653
653
|
const problems = [];
|
|
654
654
|
for (const raw of requested) {
|
|
655
655
|
const name = raw.trim();
|
|
656
656
|
if (!name || claim.includes(name)) continue;
|
|
657
|
-
if (
|
|
657
|
+
if (identity2.names.includes(name)) {
|
|
658
658
|
problems.push(`${name}: this machine already claims that name.`);
|
|
659
659
|
continue;
|
|
660
660
|
}
|
|
@@ -741,11 +741,11 @@ async function maybeClaimMachineNames(opts) {
|
|
|
741
741
|
suppressed: !!env.PAGS_NO_PROMPT
|
|
742
742
|
});
|
|
743
743
|
if (skip) return { prompted: false, reason: skip };
|
|
744
|
-
const
|
|
745
|
-
if (!
|
|
744
|
+
const identity2 = loadMachineIdentity();
|
|
745
|
+
if (!identity2.id) return { prompted: false, reason: "no-identity" };
|
|
746
746
|
const nodes = await fetchNodeSummaries(opts);
|
|
747
747
|
if (!nodes) return { prompted: false, reason: "unavailable" };
|
|
748
|
-
const candidates = claimCandidates(nodes,
|
|
748
|
+
const candidates = claimCandidates(nodes, identity2);
|
|
749
749
|
if (!candidates.length) return { prompted: false, reason: "nothing-unclaimed" };
|
|
750
750
|
const nowMs = opts.now ?? Date.now();
|
|
751
751
|
writeLine("");
|
|
@@ -771,14 +771,14 @@ async function maybeClaimMachineNames(opts) {
|
|
|
771
771
|
}
|
|
772
772
|
const names = candidates.map((c2) => c2.node);
|
|
773
773
|
if (selection.kind !== "pick") {
|
|
774
|
-
saveMachineIdentity(withDeclinedNames(
|
|
774
|
+
saveMachineIdentity(withDeclinedNames(identity2, names));
|
|
775
775
|
writeLine(` Skipped \u2014 these names will not be offered again (${machineFilePath()}).`);
|
|
776
776
|
writeLine("");
|
|
777
777
|
return { prompted: true, reason: "declined", claimed: [], declined: names };
|
|
778
778
|
}
|
|
779
779
|
const claimed = selection.indices.map((i) => names[i]);
|
|
780
780
|
const rest = names.filter((n) => !claimed.includes(n));
|
|
781
|
-
saveMachineIdentity(withDeclinedNames(withClaimedNames(
|
|
781
|
+
saveMachineIdentity(withDeclinedNames(withClaimedNames(identity2, claimed), rest));
|
|
782
782
|
writeLine(` Claiming ${claimed.join(", ")} \u2014 merged on the next register.`);
|
|
783
783
|
writeLine("");
|
|
784
784
|
return { prompted: true, reason: "claimed", claimed, declined: rest };
|
|
@@ -899,15 +899,15 @@ async function loadNodes(token) {
|
|
|
899
899
|
var listCommand = new Command4("list").description("List the machines ProAgentStore has seen on this account").action(async () => {
|
|
900
900
|
const session = requireSession();
|
|
901
901
|
const nodes = await loadNodes(session.token);
|
|
902
|
-
const
|
|
902
|
+
const identity2 = loadMachineIdentity();
|
|
903
903
|
writeLine("");
|
|
904
|
-
writeLine(` This machine: ${
|
|
905
|
-
if (
|
|
904
|
+
writeLine(` This machine: ${identity2.names[0] ?? "unknown"} ${identity2.id ? `(id ${identity2.id})` : "(no id \u2014 check that ~/.config/proagentstore/ is writable)"}`);
|
|
905
|
+
if (identity2.names.length > 1) writeLine(` Also claims: ${identity2.names.slice(1).join(", ")}`);
|
|
906
906
|
writeLine("");
|
|
907
907
|
if (!nodes.length) writeLine(" No machines registered yet \u2014 run `pags up`.");
|
|
908
908
|
const now = Date.now();
|
|
909
909
|
for (const n of nodes) {
|
|
910
|
-
const owner = n.machineId ? n.machineId ===
|
|
910
|
+
const owner = n.machineId ? n.machineId === identity2.id ? "this machine" : "claimed" : "unclaimed";
|
|
911
911
|
writeLine(` ${n.node}`);
|
|
912
912
|
writeLine(` ${describeCandidate(n, now)} \xB7 ${n.connected ? "connected" : "offline"} \xB7 ${owner}`);
|
|
913
913
|
}
|
|
@@ -918,19 +918,19 @@ var listCommand = new Command4("list").description("List the machines ProAgentSt
|
|
|
918
918
|
});
|
|
919
919
|
var claimCommand = new Command4("claim").description("Record that a machine name on this account is THIS machine").argument("<name...>", "Node name(s) to claim, as shown by `pags machines list`").action(async (names) => {
|
|
920
920
|
const session = requireSession();
|
|
921
|
-
const
|
|
922
|
-
if (!
|
|
921
|
+
const identity2 = loadMachineIdentity();
|
|
922
|
+
if (!identity2.id) {
|
|
923
923
|
writeError("This machine has no id \u2014 `~/.config/proagentstore/` is not writable, so a claim could not be sent.");
|
|
924
924
|
process.exit(1);
|
|
925
925
|
}
|
|
926
926
|
const nodes = await loadNodes(session.token);
|
|
927
|
-
const { claim, problems } = resolveClaimByName(names, nodes,
|
|
927
|
+
const { claim, problems } = resolveClaimByName(names, nodes, identity2);
|
|
928
928
|
for (const p of problems) writeError(` \u2717 ${p}`);
|
|
929
929
|
if (!claim.length) {
|
|
930
930
|
writeError(" Nothing claimed.");
|
|
931
931
|
process.exit(problems.length ? 1 : 0);
|
|
932
932
|
}
|
|
933
|
-
if (!saveMachineIdentity(withClaimedNames(
|
|
933
|
+
if (!saveMachineIdentity(withClaimedNames(identity2, claim))) {
|
|
934
934
|
writeError(` \u2717 Could not write ${machineFilePath()} \u2014 nothing claimed.`);
|
|
935
935
|
process.exit(1);
|
|
936
936
|
}
|
|
@@ -938,8 +938,8 @@ var claimCommand = new Command4("claim").description("Record that a machine name
|
|
|
938
938
|
});
|
|
939
939
|
var unclaimCommand = new Command4("unclaim").description("Remove a mistaken machine name claim from this machine (#467)").argument("<name...>", "Node name(s) to un-claim, as shown by `pags machines list`").action(async (names) => {
|
|
940
940
|
const session = requireSession();
|
|
941
|
-
const
|
|
942
|
-
if (!
|
|
941
|
+
const identity2 = loadMachineIdentity();
|
|
942
|
+
if (!identity2.id) {
|
|
943
943
|
writeError("This machine has no id \u2014 `~/.config/proagentstore/` is not writable, so the claim record cannot be found.");
|
|
944
944
|
process.exit(1);
|
|
945
945
|
}
|
|
@@ -947,12 +947,12 @@ var unclaimCommand = new Command4("unclaim").description("Remove a mistaken mach
|
|
|
947
947
|
for (const raw of names) {
|
|
948
948
|
const name = raw.trim();
|
|
949
949
|
if (!name) continue;
|
|
950
|
-
if (name ===
|
|
950
|
+
if (name === identity2.names[0]) {
|
|
951
951
|
writeError(` \u2717 ${name}: this is the machine's CURRENT hostname. You cannot un-claim the name it is actively registering under \u2014 stop \`pags up\` and rename the machine first.`);
|
|
952
952
|
anyFailed = true;
|
|
953
953
|
continue;
|
|
954
954
|
}
|
|
955
|
-
if (!
|
|
955
|
+
if (!identity2.names.includes(name)) {
|
|
956
956
|
writeError(` \u2717 ${name}: this machine does not claim that name.`);
|
|
957
957
|
anyFailed = true;
|
|
958
958
|
continue;
|
|
@@ -962,7 +962,7 @@ var unclaimCommand = new Command4("unclaim").description("Remove a mistaken mach
|
|
|
962
962
|
"DELETE",
|
|
963
963
|
`/v1/terminals/nodes/${apiPathSegment(name)}/claim`,
|
|
964
964
|
{ pagsToken: session.token, apiBase: pagsApiBase() },
|
|
965
|
-
{ machineId:
|
|
965
|
+
{ machineId: identity2.id }
|
|
966
966
|
);
|
|
967
967
|
} catch (e) {
|
|
968
968
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -970,7 +970,7 @@ var unclaimCommand = new Command4("unclaim").description("Remove a mistaken mach
|
|
|
970
970
|
anyFailed = true;
|
|
971
971
|
continue;
|
|
972
972
|
}
|
|
973
|
-
const updated = withUnclaimedName(
|
|
973
|
+
const updated = withUnclaimedName(identity2, name);
|
|
974
974
|
if (!saveMachineIdentity(updated)) {
|
|
975
975
|
writeError(` \u2717 Server un-claimed ${name} but could not update ${machineFilePath()} \u2014 the next \`pags up\` may re-stamp it. Edit that file by hand and remove "${name}" from the names array.`);
|
|
976
976
|
anyFailed = true;
|
|
@@ -1006,12 +1006,84 @@ var mcpCommand = new Command5("mcp").description("Run a local stdio proxy for th
|
|
|
1006
1006
|
await runMcpProxy(opts, args);
|
|
1007
1007
|
});
|
|
1008
1008
|
|
|
1009
|
+
// src/commands/remote-auth.ts
|
|
1010
|
+
import { Command as Command6 } from "commander";
|
|
1011
|
+
import { hostname as hostname3 } from "os";
|
|
1012
|
+
var CONSOLE = "https://proagentstore.online/console";
|
|
1013
|
+
var FIELDS = ["request_id", "agent", "machine", "resource", "scopes", "approval_url", "expires_at"];
|
|
1014
|
+
var SECRET_KEY = /verifier|proof|private|secret|token|password|credential|ciphertext|session|cookie|^code$/i;
|
|
1015
|
+
var REMOTE_AUTH_STATES = ["pending", "approving", "approved_awaiting_machine", "consumed", "connected", "denied", "expired", "cancelled", "failed"];
|
|
1016
|
+
function keysOf(v, out = []) {
|
|
1017
|
+
if (v && typeof v === "object") {
|
|
1018
|
+
for (const [k, x] of Object.entries(v)) {
|
|
1019
|
+
out.push(k);
|
|
1020
|
+
keysOf(x, out);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return out;
|
|
1024
|
+
}
|
|
1025
|
+
function buildRelayBody(input, identity2) {
|
|
1026
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return { ok: false, error: "Expected the request as a JSON object on stdin." };
|
|
1027
|
+
const secret = keysOf(input).filter((k) => SECRET_KEY.test(k));
|
|
1028
|
+
if (secret.length) return { ok: false, error: `Refused: the request carries ${[...new Set(secret)].join(", ")}. Keep proofs, verifiers, keys and tokens on this machine \u2014 relay only the public request details.` };
|
|
1029
|
+
const src = input;
|
|
1030
|
+
const body = {};
|
|
1031
|
+
for (const f of FIELDS) if (f in src) body[f] = src[f];
|
|
1032
|
+
body.relayed_by = { node: identity2.node, machine_id: identity2.id || null };
|
|
1033
|
+
return { ok: true, body };
|
|
1034
|
+
}
|
|
1035
|
+
function identity() {
|
|
1036
|
+
const id = loadMachineIdentity();
|
|
1037
|
+
return { id: id.id, node: id.names[0] ?? hostname3() };
|
|
1038
|
+
}
|
|
1039
|
+
async function readStdin() {
|
|
1040
|
+
const chunks = [];
|
|
1041
|
+
for await (const c2 of process.stdin) chunks.push(c2);
|
|
1042
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1043
|
+
}
|
|
1044
|
+
var relayCommand = new Command6("relay").description("Relay a PAS sign-in request's public details (JSON on stdin) so the owner gets a push for it").action(async () => {
|
|
1045
|
+
let input;
|
|
1046
|
+
try {
|
|
1047
|
+
input = JSON.parse(await readStdin());
|
|
1048
|
+
} catch {
|
|
1049
|
+
writeError("Expected the request as JSON on stdin.");
|
|
1050
|
+
process.exit(2);
|
|
1051
|
+
}
|
|
1052
|
+
const built = buildRelayBody(input, identity());
|
|
1053
|
+
if (!built.ok) {
|
|
1054
|
+
writeError(built.error);
|
|
1055
|
+
process.exit(2);
|
|
1056
|
+
}
|
|
1057
|
+
try {
|
|
1058
|
+
const res = await requestPags("POST", "/v1/remote-auth/requests", {}, built.body);
|
|
1059
|
+
writeLine(JSON.stringify({ id: res.request.id, url: `${CONSOLE}/remote-auth/${res.request.id}`, state: res.request.state, duplicate: res.duplicate }));
|
|
1060
|
+
} catch (e) {
|
|
1061
|
+
writeError(e instanceof Error ? e.message : String(e));
|
|
1062
|
+
process.exit(1);
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
var stateCommand = new Command6("state").description("Report the PAS broker state this machine observed for a relayed request").argument("<id>", "The id `pags remote-auth relay` returned (rar_\u2026)").argument("<state>", REMOTE_AUTH_STATES.join(" | ")).action(async (id, state) => {
|
|
1066
|
+
if (!REMOTE_AUTH_STATES.includes(state)) {
|
|
1067
|
+
writeError(`state must be one of: ${REMOTE_AUTH_STATES.join(", ")}`);
|
|
1068
|
+
process.exit(2);
|
|
1069
|
+
}
|
|
1070
|
+
const me = identity();
|
|
1071
|
+
try {
|
|
1072
|
+
const res = await requestPags("POST", `/v1/remote-auth/requests/${apiPathSegment(id)}/state`, {}, { state, relayed_by: { node: me.node, machine_id: me.id || null } });
|
|
1073
|
+
writeLine(JSON.stringify({ id: res.request.id, state: res.request.state, changed: res.changed }));
|
|
1074
|
+
} catch (e) {
|
|
1075
|
+
writeError(e instanceof Error ? e.message : String(e));
|
|
1076
|
+
process.exit(1);
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
var remoteAuthCommand = new Command6("remote-auth").description("Relay a ProAppStore remote MCP sign-in request to your phone (used by the PAS companion client)").addCommand(relayCommand).addCommand(stateCommand);
|
|
1080
|
+
|
|
1009
1081
|
// src/commands/publish.ts
|
|
1010
1082
|
import { execFileSync } from "child_process";
|
|
1011
1083
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
1012
1084
|
import { join as join5, resolve as resolve3 } from "path";
|
|
1013
|
-
import { Command as
|
|
1014
|
-
var publishCommand = new
|
|
1085
|
+
import { Command as Command7 } from "commander";
|
|
1086
|
+
var publishCommand = new Command7("publish").description("Publish an agent to ProAgentStore").option("-d, --dir <path>", "Agent directory", ".").action(async (opts) => {
|
|
1015
1087
|
const dir = resolve3(opts.dir);
|
|
1016
1088
|
const manifestPath = join5(dir, "agent.json");
|
|
1017
1089
|
if (!existsSync5(manifestPath)) {
|
|
@@ -1103,7 +1175,7 @@ var publishCommand = new Command6("publish").description("Publish an agent to Pr
|
|
|
1103
1175
|
// src/commands/runner/command.ts
|
|
1104
1176
|
import { spawn as spawn4 } from "child_process";
|
|
1105
1177
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
1106
|
-
import { Command as
|
|
1178
|
+
import { Command as Command8 } from "commander";
|
|
1107
1179
|
|
|
1108
1180
|
// src/commands/runner/process.ts
|
|
1109
1181
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -1209,7 +1281,7 @@ async function waitForLocalRunner(opts, timeoutMs = 15e3) {
|
|
|
1209
1281
|
}
|
|
1210
1282
|
|
|
1211
1283
|
// src/commands/runner/relay.ts
|
|
1212
|
-
import { hostname as
|
|
1284
|
+
import { hostname as hostname4 } from "os";
|
|
1213
1285
|
|
|
1214
1286
|
// src/commands/runner/resources.ts
|
|
1215
1287
|
import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, statfsSync, writeFileSync as writeFileSync4 } from "fs";
|
|
@@ -2276,7 +2348,7 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
|
|
|
2276
2348
|
const apiBase = pagsApiBase(opts.apiBase).replace(/^http/, "ws");
|
|
2277
2349
|
const pagsToken = clean(opts.pagsToken) || clean(process.env.PAGS_TOKEN) || clean(loadSession()?.token);
|
|
2278
2350
|
if (!pagsToken) throw new Error("PAGS token required for WebSocket relay");
|
|
2279
|
-
const runnerNode =
|
|
2351
|
+
const runnerNode = hostname4();
|
|
2280
2352
|
const machine = loadMachineIdentity(runnerNode);
|
|
2281
2353
|
const autoUpdateKey = machine.id ? autoUpdatePolicyKey(machine.id) : "";
|
|
2282
2354
|
const cell = new PolicyCell(autoUpdateKey ? loadAutoUpdatePolicy(autoUpdateKey) ?? { autoUpdate: false } : { autoUpdate: false }, (p) => saveAutoUpdatePolicy(autoUpdateKey, p), !!autoUpdateKey);
|
|
@@ -2536,7 +2608,7 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
|
|
|
2536
2608
|
writeLine(startup.state === "ok" ? `Runtime registered with PAGS \u2713 (${startup.agents} agents)` : `Runtime registration incomplete: ${startup.agents} agents \u2014 retried on each relay (re)connect${watchInstances ? " and every 20s while this runs" : ""}.`);
|
|
2537
2609
|
writeLine("");
|
|
2538
2610
|
writeLine("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
2539
|
-
writeLine(` \u2705 CONNECTED \u2014 WebSocket relay \xB7 ${
|
|
2611
|
+
writeLine(` \u2705 CONNECTED \u2014 WebSocket relay \xB7 ${hostname4()}`);
|
|
2540
2612
|
writeLine(` Agents: ${instanceIds.length} instance${instanceIds.length === 1 ? "" : "s"}`);
|
|
2541
2613
|
writeLine(" No cloudflared needed. Ctrl+C to disconnect.");
|
|
2542
2614
|
writeLine("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
@@ -2659,7 +2731,7 @@ async function readSessionResources(localUrl, runnerToken) {
|
|
|
2659
2731
|
}
|
|
2660
2732
|
var RTT_PROBE_PREFIX = "rtt:";
|
|
2661
2733
|
var RTT_ECHO_PREFIX = "rtt-echo:";
|
|
2662
|
-
function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, force = false, onConflict, onOpen, onControl, runnerNode =
|
|
2734
|
+
function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, force = false, onConflict, onOpen, onControl, runnerNode = hostname4(), beginMutation = () => () => void 0) {
|
|
2663
2735
|
let backoffMs = 1e3;
|
|
2664
2736
|
let reconnecting = false;
|
|
2665
2737
|
let closed = false;
|
|
@@ -2831,12 +2903,12 @@ function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, f
|
|
|
2831
2903
|
}
|
|
2832
2904
|
|
|
2833
2905
|
// src/commands/runner/command.ts
|
|
2834
|
-
import { hostname as
|
|
2906
|
+
import { hostname as hostname5 } from "os";
|
|
2835
2907
|
function collectCapability(value, previous = []) {
|
|
2836
2908
|
return [...previous, value];
|
|
2837
2909
|
}
|
|
2838
2910
|
function createRunnerCommand() {
|
|
2839
|
-
const command = new
|
|
2911
|
+
const command = new Command8("runner").description(
|
|
2840
2912
|
"Manage the local ProAgentStore browser runtime for ProAgentStore agents"
|
|
2841
2913
|
);
|
|
2842
2914
|
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 (default: first free port from 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) => {
|
|
@@ -2849,7 +2921,7 @@ function createRunnerCommand() {
|
|
|
2849
2921
|
const lockAccount = clean(process.env.PAGS_LOCK_ACCOUNT) || "";
|
|
2850
2922
|
let lockHeld = null;
|
|
2851
2923
|
if (lockAccount) {
|
|
2852
|
-
const taken = await acquireLock({ account: lockAccount, node:
|
|
2924
|
+
const taken = await acquireLock({ account: lockAccount, node: hostname5(), machineId: loadMachineIdentity().id || null, version: CLI_VERSION, port: Number(port), runnerToken });
|
|
2853
2925
|
if (!taken.ok) {
|
|
2854
2926
|
for (const line of taken.lock ? holderMessage(taken.lock, taken.verdict) : ["Another `pags up` holds this machine for this account."]) writeError(line);
|
|
2855
2927
|
process.exit(1);
|
|
@@ -3024,12 +3096,12 @@ var runnerCommand = createRunnerCommand();
|
|
|
3024
3096
|
|
|
3025
3097
|
// src/commands/up.ts
|
|
3026
3098
|
import { createRequire as createRequire2 } from "module";
|
|
3027
|
-
import { Command as
|
|
3028
|
-
import { hostname as
|
|
3099
|
+
import { Command as Command9 } from "commander";
|
|
3100
|
+
import { hostname as hostname7 } from "os";
|
|
3029
3101
|
|
|
3030
3102
|
// src/tui.ts
|
|
3031
3103
|
import chalk from "chalk";
|
|
3032
|
-
import { hostname as
|
|
3104
|
+
import { hostname as hostname6 } from "os";
|
|
3033
3105
|
import readline from "readline";
|
|
3034
3106
|
var ACCENT = "#7c3aed";
|
|
3035
3107
|
var c = chalk.hex(ACCENT);
|
|
@@ -3082,7 +3154,7 @@ function printStatus(state) {
|
|
|
3082
3154
|
clearScreen();
|
|
3083
3155
|
printLogo(state.version);
|
|
3084
3156
|
const connected = state.runner === "online" && state.tunnel === "online" && state.registration === "registered";
|
|
3085
|
-
console.log(pad + d("Signed in as ") + w(state.user) + d(" \xB7 agent: ") + w(state.activeInstance) + d(" \xB7 node: ") + w(
|
|
3157
|
+
console.log(pad + d("Signed in as ") + w(state.user) + d(" \xB7 agent: ") + w(state.activeInstance) + d(" \xB7 node: ") + w(hostname6()));
|
|
3086
3158
|
console.log("");
|
|
3087
3159
|
const row = (kind, s, override) => {
|
|
3088
3160
|
const { icon, label, note } = describe(kind, s);
|
|
@@ -3290,7 +3362,7 @@ async function replaceHolder(lock, opts = {}, deps = {}) {
|
|
|
3290
3362
|
// src/commands/up.ts
|
|
3291
3363
|
var API_BASE3 = "https://api.proagentstore.online";
|
|
3292
3364
|
var CLI_VERSION2 = createRequire2(import.meta.url)("../package.json").version;
|
|
3293
|
-
var upCommand = new
|
|
3365
|
+
var upCommand = new Command9("up").description("Start the browser runner for all your agent instances").option("--headless", "Run browser in headless mode").option("--instance <id>", "Connect to a specific instance only").option("--force", "Take over from another connected machine").option("--replace", "Stop the `pags up` already running here for this account, then take over").option("--now", "With --replace: stop it even though work is running on it (that work is lost)").action(async (opts) => {
|
|
3294
3366
|
const session = requireSession();
|
|
3295
3367
|
const state = {
|
|
3296
3368
|
user: session.user.login,
|
|
@@ -3345,7 +3417,7 @@ var upCommand = new Command8("up").description("Start the browser runner for all
|
|
|
3345
3417
|
headless: opts.headless
|
|
3346
3418
|
}).catch(() => void 0);
|
|
3347
3419
|
if (!opts.instance) {
|
|
3348
|
-
const split = partitionByPin(instances,
|
|
3420
|
+
const split = partitionByPin(instances, hostname7(), loadMachineIdentity(hostname7()).names);
|
|
3349
3421
|
instances = split.here;
|
|
3350
3422
|
elsewhere = split.elsewhere;
|
|
3351
3423
|
}
|
|
@@ -3528,7 +3600,7 @@ var upCommand = new Command8("up").description("Start the browser runner for all
|
|
|
3528
3600
|
}
|
|
3529
3601
|
}
|
|
3530
3602
|
});
|
|
3531
|
-
var downCommand = new
|
|
3603
|
+
var downCommand = new Command9("down").description("Stop the browser runner and disconnect").option("--now", "Stop it even though work is running on it (that work is lost)").action(async (opts) => {
|
|
3532
3604
|
clearScreen();
|
|
3533
3605
|
printLogo(CLI_VERSION2);
|
|
3534
3606
|
const session = requireSession();
|
|
@@ -3553,7 +3625,7 @@ var downCommand = new Command8("down").description("Stop the browser runner and
|
|
|
3553
3625
|
// src/index.ts
|
|
3554
3626
|
var require2 = createRequire3(import.meta.url);
|
|
3555
3627
|
var { version } = require2("../package.json");
|
|
3556
|
-
var program = new
|
|
3628
|
+
var program = new Command10();
|
|
3557
3629
|
program.name("pags").description(
|
|
3558
3630
|
"ProAgentStore CLI \u2014 create and publish server-powered AI agents"
|
|
3559
3631
|
).version(version);
|
|
@@ -3568,6 +3640,7 @@ program.addCommand(publishCommand);
|
|
|
3568
3640
|
program.addCommand(runnerCommand);
|
|
3569
3641
|
program.addCommand(machinesCommand);
|
|
3570
3642
|
program.addCommand(mcpCommand);
|
|
3643
|
+
program.addCommand(remoteAuthCommand);
|
|
3571
3644
|
try {
|
|
3572
3645
|
await program.parseAsync();
|
|
3573
3646
|
} catch (error) {
|