@proagentstore/cli 0.3.0 → 0.3.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.
@@ -377,7 +377,9 @@ export class LocalRunner {
377
377
  this.store.putTask(task);
378
378
  this.addTaskEvent(task, "task.completed", `Task completed: ${task.type}`, output);
379
379
  await this.endTakeover(taskId);
380
- return { submitted: true, output };
380
+ // This path only CLEARED a challenge — the form was NOT submitted (output.submitted
381
+ // is false). Report it accurately so the console doesn't show a false "submitted".
382
+ return { submitted: false, resumed: true, output };
381
383
  }
382
384
  /**
383
385
  * Always attach files via Playwright, never a native OS dialog: intercept any
@@ -584,6 +586,19 @@ export class LocalRunner {
584
586
  }
585
587
  });
586
588
  }
589
+ /** Close every page except the active one. ATS forms open popups/extra tabs that
590
+ * otherwise stay open in the persistent context until shutdown; over many
591
+ * applications they accumulate (memory/handles). Called when a task finishes. */
592
+ async closeStalePages() {
593
+ const ctx = this.browserContext;
594
+ if (!ctx)
595
+ return;
596
+ for (const p of ctx.pages()) {
597
+ if (p !== this.activePage && !p.isClosed()) {
598
+ await p.close().catch(() => undefined);
599
+ }
600
+ }
601
+ }
587
602
  /** The page the brain drives and the human takes over — created on demand. */
588
603
  async getActivePage() {
589
604
  const context = await this.getBrowserContext();
@@ -716,28 +731,39 @@ export class LocalRunner {
716
731
  /** Whether the brain can resume: a solved captcha (auto), a human "Resume" for a stuck step, or a provided value. */
717
732
  async browserHandoffStatus(taskId) {
718
733
  const session = this.takeovers.get(taskId);
719
- const page = session?.page ?? (await this.getActivePage());
734
+ // No live takeover session (the runner restarted mid-handoff, or it expired): stay
735
+ // UNRESOLVED. The old code fell through and relaunched a blank page via
736
+ // getActivePage(), which detected no challenge and reported solved:true — so the
737
+ // brain resumed the application WITHOUT the human's captcha/value. A status poll
738
+ // must never relaunch the browser or claim a lost handoff is done.
739
+ if (!session)
740
+ return { solved: false, challenge: null };
741
+ const page = session.page;
720
742
  if (page.isClosed())
721
743
  return { solved: true, challenge: null };
722
744
  // A needs_input handoff resumes once the user supplies the value.
723
- if (session?.reason === "needs_input")
745
+ if (session.reason === "needs_input")
724
746
  return { solved: !!session.inputValue, challenge: null, value: session.inputValue };
725
747
  // A stuck handoff resumes only when the human explicitly clicks Resume —
726
748
  // there's nothing to auto-detect.
727
- if (session?.reason === "stuck")
749
+ if (session.reason === "stuck")
728
750
  return { solved: !!session.humanDone, challenge: null };
729
751
  // A challenge resumes when the token/widget clears OR the human clicks Done —
730
752
  // custom captchas (e.g. PageUp's "not a robot") have no detectable token, so
731
753
  // the human's explicit Done is the authority; never strand them.
732
754
  const challenge = await detectHumanChallenge(page);
733
- const solved = !challenge || (await challengeSolved(page)) || !!session?.humanDone;
755
+ const solved = !challenge || (await challengeSolved(page)) || !!session.humanDone;
734
756
  return { solved, challenge };
735
757
  }
736
758
  /** The user supplied the value the agent asked for (ask-and-hold). */
737
759
  browserSubmitInput(taskId, value) {
738
760
  const session = this.takeovers.get(taskId);
739
- if (session)
740
- session.inputValue = value;
761
+ // No live takeover (session expired / runner restarted): the value can't be
762
+ // delivered. Don't discard it silently AND resurrect the already-terminal task as
763
+ // "running" — report failure so the console can say "session expired, re-run".
764
+ if (!session)
765
+ return { ok: false };
766
+ session.inputValue = value;
741
767
  const task = this.store.getTask(taskId);
742
768
  if (task) {
743
769
  task.status = "running";
@@ -777,6 +803,7 @@ export class LocalRunner {
777
803
  this.store.putTask(task);
778
804
  this.addTaskEvent(task, success ? "task.completed" : "task.failed", detail || `Application ${outcome}`, { outcome, detail });
779
805
  }
806
+ await this.closeStalePages().catch(() => undefined);
780
807
  return { ok: true };
781
808
  }
782
809
  ensureChromiumInstalled() {
package/dist/index.js CHANGED
@@ -171,6 +171,7 @@ var initCommand = new Command2("init").description("Scaffold a new ProAgentStore
171
171
  category: "general",
172
172
  model: "@cf/meta/llama-3.2-3b-instruct",
173
173
  template,
174
+ capabilities: { surfaces: [], runtime: null, workflow: null },
174
175
  serverConfig: {
175
176
  durableObject: template === "worker",
176
177
  cron: template === "cron" ? "0 8 * * *" : void 0,
@@ -378,7 +379,6 @@ import { Command as Command3 } from "commander";
378
379
  var CONFIG_DIR = join3(homedir(), ".config", "proagentstore");
379
380
  var TOKEN_FILE = join3(CONFIG_DIR, "session.json");
380
381
  var API_BASE = "https://api.proagentstore.online";
381
- var FAS_API = "https://api.freeappstore.online";
382
382
  function loadSession() {
383
383
  try {
384
384
  if (!existsSync3(TOKEN_FILE)) return null;
@@ -421,34 +421,32 @@ var loginCommand = new Command3("login").description("Sign in with Google or Git
421
421
  res.end();
422
422
  return;
423
423
  }
424
- const fasSession = url.searchParams.get("fas_session");
425
- if (!fasSession) {
424
+ const session = url.searchParams.get("session");
425
+ if (!session) {
426
426
  res.writeHead(400, { "Content-Type": "text/html" });
427
427
  res.end("<h1>Sign-in failed</h1><p>No session received.</p>");
428
428
  clearTimeout(timeout);
429
429
  server.close();
430
- reject(new Error("No fas_session in callback"));
430
+ reject(new Error("No session in callback"));
431
431
  return;
432
432
  }
433
433
  try {
434
- const exchangeRes = await fetch(`${API_BASE}/v1/auth/exchange`, {
435
- method: "POST",
436
- headers: { "Content-Type": "application/json" },
437
- body: JSON.stringify({ fas_session: fasSession })
434
+ const meRes = await fetch(`${API_BASE}/v1/auth/me`, {
435
+ headers: { Authorization: `Bearer ${session}` }
438
436
  });
439
- const data = await exchangeRes.json();
440
- if (!data.token) throw new Error(data.error || "Exchange failed");
437
+ if (!meRes.ok) throw new Error("Session validation failed");
438
+ const me = await meRes.json();
441
439
  saveSession({
442
- token: data.token,
443
- user: data.user,
440
+ token: session,
441
+ user: { id: me.id, login: me.login, avatar: me.avatar },
444
442
  expiresAt: Date.now() + 29 * 24 * 60 * 60 * 1e3
445
443
  // ~29 days
446
444
  });
447
445
  res.writeHead(200, { "Content-Type": "text/html" });
448
- res.end(`<h1>Signed in as ${data.user?.login}</h1><p>You can close this tab and return to the terminal.</p><script>window.close()</script>`);
446
+ res.end(`<h1>Signed in as ${me.login}</h1><p>You can close this tab and return to the terminal.</p><script>window.close()</script>`);
449
447
  clearTimeout(timeout);
450
448
  server.close();
451
- resolve5(data.token);
449
+ resolve5(session);
452
450
  } catch (err) {
453
451
  res.writeHead(500, { "Content-Type": "text/html" });
454
452
  res.end(`<h1>Sign-in failed</h1><p>${err instanceof Error ? err.message : String(err)}</p>`);
@@ -459,8 +457,8 @@ var loginCommand = new Command3("login").description("Sign in with Google or Git
459
457
  });
460
458
  server.listen(port, "127.0.0.1");
461
459
  });
462
- const oauthBase = provider === "google" ? `${FAS_API}/v1/auth/google/start` : `${FAS_API}/v1/auth/github/start`;
463
- const oauthUrl = `${oauthBase}?app_id=pags-cli&response_mode=query&return_to=${encodeURIComponent(callbackUrl)}`;
460
+ const oauthBase = provider === "google" ? `${API_BASE}/v1/auth/google/start` : `${API_BASE}/v1/auth/github/start`;
461
+ const oauthUrl = `${oauthBase}?return_to=${encodeURIComponent(callbackUrl)}`;
464
462
  const open = (await import("child_process")).exec;
465
463
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
466
464
  open(`${cmd} "${oauthUrl}"`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",