@proagentstore/cli 0.4.147 → 0.4.149

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.
@@ -610,6 +610,18 @@ export class ApplyBridge {
610
610
  this.host.emit({ type: "browser.blocked", url: state.url, domain: host, detail: { reason: "login_required" } });
611
611
  this.blocked = { reason: "login_required", questions: [signInQuestion(siteKeyOf(host))] };
612
612
  }
613
+ // Nothing entered, no sign-in, no other blocker (#1133): the run never found a form it could fill — a
614
+ // layout it did not recognise, a form that never opened. That is a failure to fill, recorded with its
615
+ // reason, never `review.ready` count 0: an owner reading "awaiting review" is told a form is waiting,
616
+ // and a retry repeats the same silent no-op.
617
+ else if (!this.filled && !this.uploaded.size && !this.blocked) {
618
+ this.blocked = {
619
+ reason: "incomplete",
620
+ questions: [
621
+ `The run ended without entering anything on this application${state?.url ? ` (it stopped at ${hostOf(state.url) ?? "the site"})` : ""} — it found no form it could fill, or the form never opened. Nothing was submitted. Open the application yourself, or retry once the page shows its form.`,
622
+ ],
623
+ };
624
+ }
613
625
  // #989: "ready for review" with nothing entered is not a review state.
614
626
  //
615
627
  // The live run ended `awaiting_review` with `filled: 0, uploaded: 0` seconds after the cloud
@@ -48,6 +48,12 @@ const SAFE_ID = /^[A-Za-z0-9_.:-]{1,300}$/;
48
48
  const HASH = /^[a-f0-9]{64}$/;
49
49
  /** One application at a time per agent: two runs on one employer's form is how duplicates happen. */
50
50
  const MAX_ACTIVE = 1;
51
+ /**
52
+ * Pauses that wait on a DECISION, not on the page (#1121): the owner's stored answer satisfies them on
53
+ * a fresh fill, so a run paused on one gives the machine back. Every other pause — sign-in, CAPTCHA,
54
+ * consent, a redirect, the supervisor's checkpoint — needs this exact live page and keeps it.
55
+ */
56
+ const PARKABLE_PAUSES = new Set(["missing_answer", "screening_ambiguity"]);
51
57
  class Blocked extends Error {
52
58
  reason;
53
59
  questions;
@@ -554,6 +560,21 @@ export class LocalApplyRuntime {
554
560
  pause(run, p) {
555
561
  if (run.state === "ended" || run.cancelled)
556
562
  return Promise.resolve("stopped");
563
+ // #1121: a question only the owner can answer does not need this page — park it. The run ENDS
564
+ // `blocked` with the question, the browser and the CLI stop, and the machine's one slot is free
565
+ // for the next application. The owner's answer is stored (#1079) and re-fills this application
566
+ // from a fresh page, with the answer as a source. Never once a submit was attempted: that run
567
+ // must not be filled again (#1013, #1073), so it keeps holding the slot and its page.
568
+ if (run.state === "running" && PARKABLE_PAUSES.has(p.reason) && !run.bridge?.submitAttempted) {
569
+ this.emit(run, { type: "run.paused", pauseReason: p.reason });
570
+ this.end(run, {
571
+ outcome: "blocked",
572
+ blockReason: p.reason,
573
+ questions: p.question ? [p.question] : [],
574
+ summary: "Parked for the owner's answer; this machine was freed. Nothing was submitted.",
575
+ });
576
+ return Promise.resolve("stopped");
577
+ }
557
578
  if (run.state === "running") {
558
579
  run.activeMs += this.now() - run.activeSince;
559
580
  run.state = "paused";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.4.147",
3
+ "version": "0.4.149",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",