@proagentstore/cli 0.1.22 → 0.1.24
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/browser-actions.js +10 -4
- package/dist/browser-runner/runner.js +39 -4
- package/dist/index.js +21 -15
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ import { RunnerInputError } from "./errors.js";
|
|
|
7
7
|
* matches, hidden checkboxes, and hidden file inputs. Pure over `page`; the
|
|
8
8
|
* runner passes its clickRobustly helper. The caller handles post-action settle.
|
|
9
9
|
*/
|
|
10
|
-
export async function performBrowserAction(page, action, clickRobustly) {
|
|
10
|
+
export async function performBrowserAction(page, action, clickRobustly, resumeFile) {
|
|
11
11
|
const locate = () => {
|
|
12
12
|
const role = action.role;
|
|
13
13
|
let loc = role
|
|
@@ -135,9 +135,15 @@ export async function performBrowserAction(page, action, clickRobustly) {
|
|
|
135
135
|
// Always attach via Playwright — never a native dialog. Handles both a
|
|
136
136
|
// direct <input type=file> (set files on it) and a styled "Upload"
|
|
137
137
|
// button that opens a native chooser (intercept the filechooser).
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
// The LLM doesn't know the runner's local path, so prefer the résumé the
|
|
139
|
+
// runner already resolved (downloaded from the platform); fall back to an
|
|
140
|
+
// explicit action.file only if it's a real local file.
|
|
141
|
+
const explicit = action.file ? resolve(String(action.file)) : "";
|
|
142
|
+
const file = resumeFile && existsSync(resumeFile)
|
|
143
|
+
? resumeFile
|
|
144
|
+
: explicit && existsSync(explicit) ? explicit : "";
|
|
145
|
+
if (!file)
|
|
146
|
+
throw new RunnerInputError("no résumé available to upload — upload one in the console (Knowledge → Résumé)");
|
|
141
147
|
let done = false;
|
|
142
148
|
// 1. Label-associated input (some forms).
|
|
143
149
|
if (action.name) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync, mkdirSync, rmSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { basename, dirname, join, resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
@@ -393,6 +393,37 @@ export class LocalRunner {
|
|
|
393
393
|
chooser.setFiles(filePath).catch(() => undefined);
|
|
394
394
|
});
|
|
395
395
|
}
|
|
396
|
+
resumeFileCache = new Map();
|
|
397
|
+
/**
|
|
398
|
+
* Resolve a résumé reference to a LOCAL file path. A remote runner gets a
|
|
399
|
+
* signed URL (the file lives in the platform's R2) — download it once and
|
|
400
|
+
* cache it. A same-machine run may still pass a local path.
|
|
401
|
+
*/
|
|
402
|
+
async resolveResumeFile(ref) {
|
|
403
|
+
if (/^https?:\/\//i.test(ref)) {
|
|
404
|
+
const cached = this.resumeFileCache.get(ref);
|
|
405
|
+
if (cached && existsSync(cached))
|
|
406
|
+
return cached;
|
|
407
|
+
try {
|
|
408
|
+
const res = await fetch(ref);
|
|
409
|
+
if (!res.ok)
|
|
410
|
+
return null;
|
|
411
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
412
|
+
const disp = res.headers.get("content-disposition") || "";
|
|
413
|
+
const name = (disp.match(/filename="?([^"]+)"?/i)?.[1] || "resume.pdf").replace(/[^\w.\-]/g, "_");
|
|
414
|
+
const dir = join(this.config.dataDir, "uploads");
|
|
415
|
+
mkdirSync(dir, { recursive: true });
|
|
416
|
+
const dest = join(dir, name);
|
|
417
|
+
writeFileSync(dest, buf);
|
|
418
|
+
this.resumeFileCache.set(ref, dest);
|
|
419
|
+
return dest;
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return existsSync(resolve(ref)) ? resolve(ref) : null;
|
|
426
|
+
}
|
|
396
427
|
/** End a takeover session (human finished or gave up). */
|
|
397
428
|
async endTakeover(taskId) {
|
|
398
429
|
const session = this.takeovers.get(taskId);
|
|
@@ -588,14 +619,18 @@ export class LocalRunner {
|
|
|
588
619
|
async browserAct(action, resumePath) {
|
|
589
620
|
const page = await this.getActivePage();
|
|
590
621
|
// Arm résumé auto-attach so a file chooser never blocks the flow (see method).
|
|
591
|
-
|
|
592
|
-
|
|
622
|
+
// resumePath may be a signed URL (remote runner) or a local path — resolve to
|
|
623
|
+
// a real local file either way.
|
|
624
|
+
if (resumePath) {
|
|
625
|
+
const local = await this.resolveResumeFile(resumePath);
|
|
626
|
+
if (local)
|
|
627
|
+
this.applyResumePath = local;
|
|
593
628
|
}
|
|
594
629
|
if (this.applyResumePath)
|
|
595
630
|
this.armFileAutoAttach(page, this.applyResumePath);
|
|
596
631
|
// The selector-free action switch lives in browser-actions.ts (kept this
|
|
597
632
|
// file from ballooning); the post-action settle + result stay here.
|
|
598
|
-
await performBrowserAction(page, action, (p, loc) => this.clickRobustly(p, loc));
|
|
633
|
+
await performBrowserAction(page, action, (p, loc) => this.clickRobustly(p, loc), this.applyResumePath);
|
|
599
634
|
// A click may trigger SPA navigation or open a new tab/popup. Give it a beat
|
|
600
635
|
// to settle and follow the (possibly new) active page, so the next snapshot
|
|
601
636
|
// reflects the new state — not the element the brain just clicked.
|
package/dist/index.js
CHANGED
|
@@ -1258,6 +1258,25 @@ async function waitForKey(keys) {
|
|
|
1258
1258
|
// src/commands/up.ts
|
|
1259
1259
|
var API_BASE2 = "https://api.proagentstore.online";
|
|
1260
1260
|
var CLI_VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
1261
|
+
async function stopRunnerProcesses() {
|
|
1262
|
+
if (process.platform === "win32") return false;
|
|
1263
|
+
const { execSync } = await import("child_process");
|
|
1264
|
+
const patterns = [
|
|
1265
|
+
"dist/browser-runner/index.js",
|
|
1266
|
+
"browser-runner/src/index",
|
|
1267
|
+
"runner connect",
|
|
1268
|
+
"tunnel --url http://127.0.0.1"
|
|
1269
|
+
];
|
|
1270
|
+
let stopped = false;
|
|
1271
|
+
for (const p of patterns) {
|
|
1272
|
+
try {
|
|
1273
|
+
execSync(`pkill -f ${JSON.stringify(p)}`, { stdio: "ignore" });
|
|
1274
|
+
stopped = true;
|
|
1275
|
+
} catch {
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
return stopped;
|
|
1279
|
+
}
|
|
1261
1280
|
var upCommand = new Command7("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").action(async (opts) => {
|
|
1262
1281
|
const session = requireSession();
|
|
1263
1282
|
const state = {
|
|
@@ -1301,6 +1320,7 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1301
1320
|
const target = instances[0];
|
|
1302
1321
|
state.activeInstance = target.name || target.slug || target.id.slice(0, 8);
|
|
1303
1322
|
printStep(`Connecting: ${state.activeInstance}`, "wait");
|
|
1323
|
+
await stopRunnerProcesses();
|
|
1304
1324
|
const { spawn: spawn3 } = await import("child_process");
|
|
1305
1325
|
const cliPath = process.argv[1];
|
|
1306
1326
|
const args = [cliPath, "runner", "connect", target.id];
|
|
@@ -1419,21 +1439,7 @@ var downCommand = new Command7("down").description("Stop the browser runner and
|
|
|
1419
1439
|
writeLine("");
|
|
1420
1440
|
return;
|
|
1421
1441
|
}
|
|
1422
|
-
const
|
|
1423
|
-
const patterns = [
|
|
1424
|
-
"dist/browser-runner/index.js",
|
|
1425
|
-
"browser-runner/src/index",
|
|
1426
|
-
"runner connect",
|
|
1427
|
-
"tunnel --url http://127.0.0.1"
|
|
1428
|
-
];
|
|
1429
|
-
let stopped = false;
|
|
1430
|
-
for (const p of patterns) {
|
|
1431
|
-
try {
|
|
1432
|
-
execSync(`pkill -f ${JSON.stringify(p)}`, { stdio: "ignore" });
|
|
1433
|
-
stopped = true;
|
|
1434
|
-
} catch {
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1442
|
+
const stopped = await stopRunnerProcesses();
|
|
1437
1443
|
if (stopped) {
|
|
1438
1444
|
writeLine(" \u2713 Runner stopped \u2014 you're disconnected.");
|
|
1439
1445
|
writeLine("");
|