@proagentstore/cli 0.4.21 → 0.4.22

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.
@@ -97,10 +97,11 @@ export class LocalRunner {
97
97
  card.subtitle = normalized.subtitle;
98
98
  if (normalized.description)
99
99
  card.description = normalized.description;
100
- // Agent-driven applications are steered by the remote Workflow brain via the
101
- // /browser/* endpoints — the runner never auto-executes them. The task exists
102
- // for the console board, the activity trace, and takeover keying.
103
- if (normalized.type === "job.apply_agent") {
100
+ // Agent-driven browser tasks (job applications AND generic browser tasks) are
101
+ // steered by the remote Workflow brain via the /browser/* endpoints — the runner
102
+ // never auto-executes them. The task exists for the console board, the activity
103
+ // trace, and takeover keying.
104
+ if (normalized.type === "job.apply_agent" || normalized.type === "browser.task") {
104
105
  const task = {
105
106
  id: `task_${crypto.randomUUID()}`,
106
107
  type: normalized.type,
@@ -112,7 +113,8 @@ export class LocalRunner {
112
113
  updatedAt: now,
113
114
  };
114
115
  this.store.putTask(task);
115
- this.addTaskEvent(task, "task.created", "Job application started (agent-driven)", { status: "running", url: normalized.input.url });
116
+ const startedMsg = normalized.type === "browser.task" ? "Browser task started (agent-driven)" : "Job application started (agent-driven)";
117
+ this.addTaskEvent(task, "task.created", startedMsg, { status: "running", url: normalized.input.url });
116
118
  return task;
117
119
  }
118
120
  const requiresApproval = normalized.requiresApproval || APPROVAL_REQUIRED_TASKS.has(normalized.type);
package/dist/index.js CHANGED
@@ -608,16 +608,104 @@ var publishCommand = new Command5("publish").description("Publish an agent to Pr
608
608
  writeLine();
609
609
  });
610
610
 
611
- // src/commands/runner.ts
612
- import { spawn as spawn2 } from "child_process";
611
+ // src/commands/runner/command.ts
612
+ import { spawn as spawn3 } from "child_process";
613
613
  import { randomUUID } from "crypto";
614
- import { existsSync as existsSync5 } from "fs";
614
+ import { Command as Command6 } from "commander";
615
+
616
+ // src/commands/runner/http.ts
615
617
  import { hostname } from "os";
618
+ function clean(value) {
619
+ const trimmed = value?.trim();
620
+ return trimmed || void 0;
621
+ }
622
+ function runnerBaseUrl(url) {
623
+ return (clean(url) || clean(process.env.PAGS_RUNNER_URL) || "http://127.0.0.1:49171").replace(/\/$/, "");
624
+ }
625
+ function pagsApiBase(url) {
626
+ return (clean(url) || clean(process.env.PAGS_API_BASE) || "https://api.proagentstore.online").replace(/\/$/, "");
627
+ }
628
+ function pagsHeaders(token) {
629
+ const resolved = clean(token) || clean(process.env.PAGS_TOKEN) || clean(loadSession()?.token);
630
+ return resolved ? { Authorization: `Bearer ${resolved}` } : {};
631
+ }
632
+ function runnerRequestHeaders(opts) {
633
+ const resolved = clean(opts.token) || clean(process.env.PAGS_RUNNER_TOKEN);
634
+ const headers = resolved ? { Authorization: `Bearer ${resolved}` } : {};
635
+ const instanceId = clean(opts.instanceId) || clean(process.env.PAGS_INSTANCE_ID);
636
+ if (instanceId) headers["X-PAGS-Instance-Id"] = instanceId;
637
+ return headers;
638
+ }
639
+ function apiPathSegment(value) {
640
+ return encodeURIComponent(value);
641
+ }
642
+ function buildRuntimeRegistrationBody(opts, capabilities = []) {
643
+ return {
644
+ endpointUrl: clean(opts.endpointUrl) || opts.endpointUrl,
645
+ token: clean(opts.runnerToken) || clean(opts.token) || clean(process.env.PAGS_RUNNER_TOKEN),
646
+ placement: opts.placement === "managed" ? "managed" : "local",
647
+ capabilities,
648
+ runnerVersion: clean(opts.runnerVersion) || "",
649
+ runnerNode: hostname()
650
+ };
651
+ }
652
+ async function requestRunner(method, path, opts, body) {
653
+ const headers = {
654
+ ...runnerRequestHeaders(opts)
655
+ };
656
+ if (body !== void 0) headers["Content-Type"] = "application/json";
657
+ const res = await fetch(`${runnerBaseUrl(opts.url)}${path}`, {
658
+ method,
659
+ headers,
660
+ body: body === void 0 ? void 0 : JSON.stringify(body)
661
+ });
662
+ const { text, data } = await readResponse(res);
663
+ if (!res.ok) {
664
+ const message = responseErrorMessage(data, text, res.statusText);
665
+ throw new Error(`${res.status} ${message}`);
666
+ }
667
+ return data;
668
+ }
669
+ async function requestPags(method, path, opts, body) {
670
+ const headers = {
671
+ ...pagsHeaders(opts.pagsToken)
672
+ };
673
+ if (!headers.Authorization) {
674
+ throw new Error("PAGS token required. Set PAGS_TOKEN or pass --pags-token.");
675
+ }
676
+ if (body !== void 0) headers["Content-Type"] = "application/json";
677
+ const res = await fetch(`${pagsApiBase(opts.apiBase)}${path}`, {
678
+ method,
679
+ headers,
680
+ body: body === void 0 ? void 0 : JSON.stringify(body)
681
+ });
682
+ const { text, data } = await readResponse(res);
683
+ if (!res.ok) {
684
+ const message = responseErrorMessage(data, text, res.statusText);
685
+ throw new Error(`${res.status} ${message}`);
686
+ }
687
+ return data;
688
+ }
689
+ async function readResponse(res) {
690
+ const text = await res.text();
691
+ if (!text) return { text, data: {} };
692
+ try {
693
+ return { text, data: JSON.parse(text) };
694
+ } catch {
695
+ return { text, data: {} };
696
+ }
697
+ }
698
+ function responseErrorMessage(data, text, statusText) {
699
+ return typeof data.error === "string" ? data.error : text || statusText;
700
+ }
701
+
702
+ // src/commands/runner/process.ts
703
+ import { spawn as spawn2 } from "child_process";
704
+ import { existsSync as existsSync5 } from "fs";
616
705
  import { resolve as resolve4 } from "path";
617
706
  import { createServer as createServer2 } from "net";
618
707
  import { fileURLToPath as fileURLToPath2 } from "url";
619
708
  import { createRequire } from "module";
620
- import { Command as Command6 } from "commander";
621
709
  var CLI_VERSION = (() => {
622
710
  try {
623
711
  return createRequire(import.meta.url)("../package.json").version;
@@ -637,27 +725,6 @@ async function findFreePort2(start) {
637
725
  }
638
726
  return start;
639
727
  }
640
- var runnerCommand = createRunnerCommand();
641
- function runnerBaseUrl(url) {
642
- return (clean(url) || clean(process.env.PAGS_RUNNER_URL) || "http://127.0.0.1:49171").replace(/\/$/, "");
643
- }
644
- function pagsApiBase(url) {
645
- return (clean(url) || clean(process.env.PAGS_API_BASE) || "https://api.proagentstore.online").replace(/\/$/, "");
646
- }
647
- function pagsHeaders(token) {
648
- const resolved = clean(token) || clean(process.env.PAGS_TOKEN) || clean(loadSession()?.token);
649
- return resolved ? { Authorization: `Bearer ${resolved}` } : {};
650
- }
651
- function runnerRequestHeaders(opts) {
652
- const resolved = clean(opts.token) || clean(process.env.PAGS_RUNNER_TOKEN);
653
- const headers = resolved ? { Authorization: `Bearer ${resolved}` } : {};
654
- const instanceId = clean(opts.instanceId) || clean(process.env.PAGS_INSTANCE_ID);
655
- if (instanceId) headers["X-PAGS-Instance-Id"] = instanceId;
656
- return headers;
657
- }
658
- function apiPathSegment(value) {
659
- return encodeURIComponent(value);
660
- }
661
728
  function buildRunnerArgs(opts) {
662
729
  const args = [];
663
730
  if (clean(opts.host)) args.push("--host", clean(opts.host));
@@ -668,20 +735,6 @@ function buildRunnerArgs(opts) {
668
735
  if (opts.headless) args.push("--headless");
669
736
  return args;
670
737
  }
671
- function buildRuntimeRegistrationBody(opts, capabilities = []) {
672
- return {
673
- endpointUrl: clean(opts.endpointUrl) || opts.endpointUrl,
674
- token: clean(opts.runnerToken) || clean(opts.token) || clean(process.env.PAGS_RUNNER_TOKEN),
675
- placement: opts.placement === "managed" ? "managed" : "local",
676
- capabilities,
677
- runnerVersion: clean(opts.runnerVersion) || "",
678
- runnerNode: hostname()
679
- };
680
- }
681
- function clean(value) {
682
- const trimmed = value?.trim();
683
- return trimmed || void 0;
684
- }
685
738
  function findWorkspaceRoot() {
686
739
  let dir = process.cwd();
687
740
  for (let i = 0; i < 8; i++) {
@@ -742,63 +795,14 @@ async function waitForLocalRunner(opts, timeoutMs = 15e3) {
742
795
  }
743
796
  throw new Error(`runner did not become healthy: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
744
797
  }
745
- async function requestRunner(method, path, opts, body) {
746
- const headers = {
747
- ...runnerRequestHeaders(opts)
748
- };
749
- if (body !== void 0) headers["Content-Type"] = "application/json";
750
- const res = await fetch(`${runnerBaseUrl(opts.url)}${path}`, {
751
- method,
752
- headers,
753
- body: body === void 0 ? void 0 : JSON.stringify(body)
754
- });
755
- const { text, data } = await readResponse(res);
756
- if (!res.ok) {
757
- const message = responseErrorMessage(data, text, res.statusText);
758
- throw new Error(`${res.status} ${message}`);
759
- }
760
- return data;
761
- }
762
- async function requestPags(method, path, opts, body) {
763
- const headers = {
764
- ...pagsHeaders(opts.pagsToken)
765
- };
766
- if (!headers.Authorization) {
767
- throw new Error("PAGS token required. Set PAGS_TOKEN or pass --pags-token.");
768
- }
769
- if (body !== void 0) headers["Content-Type"] = "application/json";
770
- const res = await fetch(`${pagsApiBase(opts.apiBase)}${path}`, {
771
- method,
772
- headers,
773
- body: body === void 0 ? void 0 : JSON.stringify(body)
774
- });
775
- const { text, data } = await readResponse(res);
776
- if (!res.ok) {
777
- const message = responseErrorMessage(data, text, res.statusText);
778
- throw new Error(`${res.status} ${message}`);
779
- }
780
- return data;
781
- }
782
- async function readResponse(res) {
783
- const text = await res.text();
784
- if (!text) return { text, data: {} };
785
- try {
786
- return { text, data: JSON.parse(text) };
787
- } catch {
788
- return { text, data: {} };
789
- }
790
- }
791
- function responseErrorMessage(data, text, statusText) {
792
- return typeof data.error === "string" ? data.error : text || statusText;
793
- }
794
- function collectCapability(value, previous = []) {
795
- return [...previous, value];
796
- }
798
+
799
+ // src/commands/runner/relay.ts
800
+ import { hostname as hostname2 } from "os";
797
801
  async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force = false) {
798
802
  const apiBase = pagsApiBase(opts.apiBase).replace(/^http/, "ws");
799
803
  const pagsToken = clean(opts.pagsToken) || clean(process.env.PAGS_TOKEN) || clean(loadSession()?.token);
800
804
  if (!pagsToken) throw new Error("PAGS token required for WebSocket relay");
801
- const runnerNode = hostname();
805
+ const runnerNode = hostname2();
802
806
  const capabilities = await requestRunner("GET", "/capabilities", { url: localUrl, token: runnerToken, instanceId: instanceIds[0] });
803
807
  const caps = Array.isArray(capabilities.capabilities) ? capabilities.capabilities.filter((item) => typeof item === "string") : [];
804
808
  for (const id of instanceIds) {
@@ -824,7 +828,7 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
824
828
  writeLine("Runtime registered with PAGS \u2713");
825
829
  writeLine("");
826
830
  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");
827
- writeLine(` \u2705 CONNECTED \u2014 WebSocket relay \xB7 ${hostname()}`);
831
+ writeLine(` \u2705 CONNECTED \u2014 WebSocket relay \xB7 ${hostname2()}`);
828
832
  writeLine(` Agents: ${instanceIds.length} instance${instanceIds.length === 1 ? "" : "s"}`);
829
833
  writeLine(" No cloudflared needed. Ctrl+C to disconnect.");
830
834
  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");
@@ -860,7 +864,7 @@ function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, f
860
864
  backoffMs = Math.min(backoffMs * 2, 3e4);
861
865
  return;
862
866
  }
863
- const params = new URLSearchParams({ token: relayToken, node: hostname() });
867
+ const params = new URLSearchParams({ token: relayToken, node: hostname2() });
864
868
  if (force) params.set("force", "1");
865
869
  const url = `${wsBase}/v1/relay/${encodeURIComponent(instanceId)}/connect?${params.toString()}`;
866
870
  const ws = new WebSocket(url);
@@ -930,6 +934,11 @@ function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, f
930
934
  };
931
935
  connect();
932
936
  }
937
+
938
+ // src/commands/runner/command.ts
939
+ function collectCapability(value, previous = []) {
940
+ return [...previous, value];
941
+ }
933
942
  function createRunnerCommand() {
934
943
  const command = new Command6("runner").description(
935
944
  "Manage the local ProAgentStore browser runtime for ProAgentStore agents"
@@ -945,7 +954,7 @@ function createRunnerCommand() {
945
954
  const primary = instanceIds[0];
946
955
  const runnerOpts = { ...opts, host, port, token: runnerToken };
947
956
  const spec = runnerSpawnSpec(runnerOpts);
948
- const runner = spawn2(spec.command, spec.args, {
957
+ const runner = spawn3(spec.command, spec.args, {
949
958
  cwd: spec.cwd,
950
959
  stdio: ["ignore", "pipe", "pipe"],
951
960
  shell: process.platform === "win32"
@@ -1091,13 +1100,16 @@ function createRunnerCommand() {
1091
1100
  return command;
1092
1101
  }
1093
1102
 
1103
+ // src/commands/runner.ts
1104
+ var runnerCommand = createRunnerCommand();
1105
+
1094
1106
  // src/commands/up.ts
1095
1107
  import { createRequire as createRequire2 } from "module";
1096
1108
  import { Command as Command7 } from "commander";
1097
1109
 
1098
1110
  // src/tui.ts
1099
1111
  import chalk from "chalk";
1100
- import { hostname as hostname2 } from "os";
1112
+ import { hostname as hostname3 } from "os";
1101
1113
  import readline from "readline";
1102
1114
  var ACCENT = "#7c3aed";
1103
1115
  var c = chalk.hex(ACCENT);
@@ -1139,7 +1151,7 @@ function printStatus(state) {
1139
1151
  clearScreen();
1140
1152
  printLogo(state.version);
1141
1153
  const connected = state.runner === "online" && state.tunnel === "online" && state.registration === "registered";
1142
- console.log(pad + d("Signed in as ") + w(state.user) + d(" \xB7 agent: ") + w(state.activeInstance) + d(" \xB7 node: ") + w(hostname2()));
1154
+ console.log(pad + d("Signed in as ") + w(state.user) + d(" \xB7 agent: ") + w(state.activeInstance) + d(" \xB7 node: ") + w(hostname3()));
1143
1155
  console.log("");
1144
1156
  const row = (kind, s) => {
1145
1157
  const { icon, label, note } = describe(kind, s);
@@ -1202,7 +1214,7 @@ var API_BASE2 = "https://api.proagentstore.online";
1202
1214
  var CLI_VERSION2 = createRequire2(import.meta.url)("../package.json").version;
1203
1215
  async function stopRunnerProcesses() {
1204
1216
  if (process.platform === "win32") return false;
1205
- const { execSync } = await import("child_process");
1217
+ const { execFileSync: execFileSync2 } = await import("child_process");
1206
1218
  const patterns = [
1207
1219
  "dist/browser-runner/index.js",
1208
1220
  "browser-runner/src/index",
@@ -1211,7 +1223,7 @@ async function stopRunnerProcesses() {
1211
1223
  let stopped = false;
1212
1224
  for (const p of patterns) {
1213
1225
  try {
1214
- execSync(`pkill -f ${JSON.stringify(p)}`, { stdio: "ignore" });
1226
+ execFileSync2("pkill", ["-f", p], { stdio: "ignore" });
1215
1227
  stopped = true;
1216
1228
  } catch {
1217
1229
  }
@@ -1270,12 +1282,12 @@ var upCommand = new Command7("up").description("Start the browser runner for all
1270
1282
  state.activeInstance = instances.length === 1 ? instances[0].name || instances[0].slug || instances[0].id.slice(0, 8) : `${instances.length} agents`;
1271
1283
  printStep(`Connecting ${state.activeInstance}\u2026`, "wait");
1272
1284
  await stopRunnerProcesses();
1273
- const { spawn: spawn3 } = await import("child_process");
1285
+ const { spawn: spawn4 } = await import("child_process");
1274
1286
  const cliPath = process.argv[1];
1275
1287
  const args = [cliPath, "runner", "connect", ...instances.map((i) => i.id)];
1276
1288
  if (opts.headless) args.push("--headless");
1277
1289
  if (opts.force) args.push("--force");
1278
- const child = spawn3(process.execPath, args, {
1290
+ const child = spawn4(process.execPath, args, {
1279
1291
  stdio: ["ignore", "pipe", "pipe"],
1280
1292
  env: { ...process.env, PAGS_TOKEN: session.token }
1281
1293
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.4.21",
3
+ "version": "0.4.22",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",