zcode-acp-server 0.60.0 → 0.62.0

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.
Files changed (43) hide show
  1. package/README.md +17 -13
  2. package/dist/code-fingerprint.json +2 -2
  3. package/dist/config/settings.d.ts +7 -0
  4. package/dist/config/settings.d.ts.map +1 -1
  5. package/dist/config/settings.js +15 -0
  6. package/dist/config/settings.js.map +1 -1
  7. package/dist/config/user-config.d.ts +7 -0
  8. package/dist/config/user-config.d.ts.map +1 -1
  9. package/dist/config/user-config.js +2 -0
  10. package/dist/config/user-config.js.map +1 -1
  11. package/dist/goal-loop/driver.d.ts +18 -0
  12. package/dist/goal-loop/driver.d.ts.map +1 -1
  13. package/dist/goal-loop/driver.js +100 -1
  14. package/dist/goal-loop/driver.js.map +1 -1
  15. package/dist/i18n.d.ts +6 -0
  16. package/dist/i18n.d.ts.map +1 -1
  17. package/dist/i18n.js +8 -0
  18. package/dist/i18n.js.map +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +23 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/quota/resume.d.ts +66 -0
  23. package/dist/quota/resume.d.ts.map +1 -0
  24. package/dist/quota/resume.js +217 -0
  25. package/dist/quota/resume.js.map +1 -0
  26. package/dist/remote/hub-server.d.ts.map +1 -1
  27. package/dist/remote/hub-server.js +29 -0
  28. package/dist/remote/hub-server.js.map +1 -1
  29. package/dist/remote/system-stats.d.ts +137 -0
  30. package/dist/remote/system-stats.d.ts.map +1 -0
  31. package/dist/remote/system-stats.js +335 -0
  32. package/dist/remote/system-stats.js.map +1 -0
  33. package/dist/remote/workflow-overview.d.ts +7 -1
  34. package/dist/remote/workflow-overview.d.ts.map +1 -1
  35. package/dist/remote/workflow-overview.js +135 -2
  36. package/dist/remote/workflow-overview.js.map +1 -1
  37. package/dist/workflow/quota-resume.d.ts +135 -0
  38. package/dist/workflow/quota-resume.d.ts.map +1 -0
  39. package/dist/workflow/quota-resume.js +773 -0
  40. package/dist/workflow/quota-resume.js.map +1 -0
  41. package/docs/DEVELOPMENT.md +7 -0
  42. package/docs/REMOTE-CLIENTS.md +40 -5
  43. package/package.json +1 -1
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Quota auto-resume watchdog for dynamic-workflow runs.
3
+ *
4
+ * Why: when a workflow subagent hits a usage cap (GLM 1308 …), upstream stops
5
+ * the WHOLE run as `stopped(provider)` with a `ProviderStopDetails{kind:
6
+ * "quota"}` and its notification instructs the agent to call
7
+ * ResumeWorkflowRun AFTER the reset (workflow-notification-copy.ts:55-64).
8
+ * Nothing schedules that "after" — the run sits stopped until a human acts.
9
+ * The bridge owns the process that can wait, so it does: a small persisted
10
+ * registry of pending resumes, a periodic scan over the project's run journal,
11
+ * and a timer per entry.
12
+ *
13
+ * Detection is deliberately journal-first: the v4 session summary carries the
14
+ * failure message (with the provider's business code in brackets) but NOT the
15
+ * structured providerStop/resetAt, and the workflow progress poller gives up
16
+ * after 10 minutes — long runs would never be seen there. The scan reads
17
+ * `workflows/runs` (one session-less RPC), keeps rows that are
18
+ * `stopped(provider)`, and only then resolves the few parent sessions through
19
+ * `v4/conversation/workflowRuns` to read their failure messages.
20
+ *
21
+ * Firing is defensive at every step: quota card first (a known future reset
22
+ * defers without burning an attempt), then a live state read (a run that is
23
+ * running again / finished / no longer resumable drops the entry), then the
24
+ * same `resumeWorkflowRun` command the App's Resume button uses. An accepted
25
+ * resume is re-verified after {@link VERIFY_AFTER_MS}; only a stopped-again run
26
+ * with no known reset burns an attempt and backs off.
27
+ *
28
+ * Store: `~/.zcode/v2/acp-quota-resumes.json`, shared by every bridge process
29
+ * and written only via temp+rename with merge-at-write (the dismissals-store
30
+ * discipline — a torn write would lose every pending resume).
31
+ */
32
+ import type { QuotaResult } from "../quota/types.js";
33
+ import type { ZcodeAcpServer } from "../server.js";
34
+ /** Scan cadence for newly quota-stopped runs. */
35
+ export declare const QUOTA_RESUME_SCAN_INTERVAL_MS: number;
36
+ /** One pending auto-resume. `attempts` counts resume attempts that did not stick. */
37
+ export interface QuotaResumeEntry {
38
+ runId: string;
39
+ /** Parent backend session (the run's journal parentSessionId). */
40
+ zcodeSid: string;
41
+ /** Workspace the run belongs to — bridges re-arm only their own project's entries. */
42
+ cwd: string;
43
+ /** ACP alias when known at schedule time (re-resolved at fire time anyway). */
44
+ acpSid?: string;
45
+ name?: string;
46
+ /** Epoch ms of the next fire. */
47
+ resumeAt: number;
48
+ /** Failed-attempt counter (drives the backoff ladder). */
49
+ attempts: number;
50
+ /** True while the previous resume attempt is inside its verify window. */
51
+ awaitingVerify?: boolean;
52
+ /**
53
+ * Terminal give-up reason. The journal row stays `stopped(provider)+quota`
54
+ * forever, so without this marker the scan would re-schedule the same run
55
+ * every cycle — a retry/give-up loop. A gave-up entry is skipped by scans,
56
+ * re-arms, and the idle-exit predicate; it expires via the TTL, by which
57
+ * time the row is out of the backfill window anyway.
58
+ */
59
+ gaveUp?: string;
60
+ /**
61
+ * In-flight fire claim (cross-process single-flight). Written under the
62
+ * settings file lock by {@link claimFire}; every normal mutation (updateEntry
63
+ * / reschedule / markGaveUp) clears it. Without it, two bridges of the same
64
+ * workspace (editor + serve/TUI) could both resume one run — a money-level
65
+ * double execution.
66
+ */
67
+ firing?: {
68
+ pid: number;
69
+ at: number;
70
+ };
71
+ scheduledAt: number;
72
+ updatedAt: number;
73
+ }
74
+ export interface QuotaResumeInput {
75
+ runId: string;
76
+ zcodeSid: string;
77
+ cwd: string;
78
+ name?: string;
79
+ acpSid?: string;
80
+ /** Provider-reported reset (Retry-After). Absent → the first fire re-derives. */
81
+ resetAt?: number;
82
+ }
83
+ /**
84
+ * Register (or merge) a pending auto-resume. Idempotent per runId; an earlier
85
+ * resumeAt wins so a duplicate detection never delays an armed timer.
86
+ *
87
+ * The whole read-decide-write runs under the store file lock: the merge must
88
+ * see the CURRENT record (a sibling's in-flight fire claim included — which it
89
+ * must never stomp) rather than a snapshot read before the lock was taken.
90
+ */
91
+ export declare function scheduleQuotaResume(server: ZcodeAcpServer, input: QuotaResumeInput): Promise<void>;
92
+ /**
93
+ * One scan over the project's journal for quota-stopped runs. Best-effort and
94
+ * side-effect free when nothing matches; never spawns a backend (the scan is
95
+ * discovery — only a fire may act).
96
+ */
97
+ export declare function scanQuotaStoppedRuns(server: ZcodeAcpServer): Promise<void>;
98
+ export interface QuotaResumeDeps {
99
+ /** Injectable for tests; defaults to the real quota card. */
100
+ queryQuota?: () => Promise<QuotaResult>;
101
+ }
102
+ /**
103
+ * Fire one pending entry. Everything is re-checked here because the state may
104
+ * have moved since scheduling (user resumed/stopped/dismissed the run, quota
105
+ * already recovered, bridge slept past the reset).
106
+ *
107
+ * Cross-process single-flight: the side-effecting tail runs only under a
108
+ * locked fire claim (see {@link claimFire}); a sibling bridge that loses the
109
+ * claim re-arms its local timer and lets the winner's store write (reschedule
110
+ * / retire) become the truth.
111
+ */
112
+ export declare function fire(server: ZcodeAcpServer, runId: string, deps?: QuotaResumeDeps): Promise<void>;
113
+ /**
114
+ * Arm the watchdog for one bridge: re-arm its project's persisted entries and
115
+ * start the periodic scan. Idempotent per server. Scans never spawn a backend
116
+ * and never throw; a bridge that never sees a backend stays silent.
117
+ */
118
+ export declare function armQuotaResumeWatchdog(server: ZcodeAcpServer): void;
119
+ /** Is a resume armed for this run? (test/observability hook) */
120
+ export declare function quotaResumePending(runId: string): boolean;
121
+ /**
122
+ * Is any resume pending for a workspace? The headless serve bridge consults
123
+ * this in its idle decision: exiting would kill the backend the pending
124
+ * resume must act on, breaking "the bridge owns the wait" exactly when the
125
+ * app is asleep (the case the watchdog exists for). Retired (gave-up) entries
126
+ * do not hold a serve bridge alive.
127
+ */
128
+ export declare function hasQuotaResumePendingForCwd(cwd: string): boolean;
129
+ /** Read one entry (test hook). */
130
+ export declare function quotaResumeEntryForTest(runId: string): QuotaResumeEntry | undefined;
131
+ /** Patch an entry and drop its timer (test hook; patches may include `firing`). */
132
+ export declare function updateQuotaResumeEntryForTest(runId: string, patch: Partial<QuotaResumeEntry>): void;
133
+ /** Drop every timer and the store file (test hook). */
134
+ export declare function resetQuotaResumeForTest(): void;
135
+ //# sourceMappingURL=quota-resume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-resume.d.ts","sourceRoot":"","sources":["../../src/workflow/quota-resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAyBH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,iDAAiD;AACjD,eAAO,MAAM,6BAA6B,QAAa,CAAC;AA8CxD,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AA8QD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,IAAI,CAAC,CAyDf;AA0CD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EhF;AAED,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACzC;AAED;;;;;;;;;GASG;AACH,wBAAsB,IAAI,CACxB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAqIf;AAmED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CA2BnE;AAED,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKhE;AAED,kCAAkC;AAClC,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEnF;AAED,mFAAmF;AACnF,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAC/B,IAAI,CAQN;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,IAAI,IAAI,CAQ9C"}