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.
- package/README.md +17 -13
- package/dist/code-fingerprint.json +2 -2
- package/dist/config/settings.d.ts +7 -0
- package/dist/config/settings.d.ts.map +1 -1
- package/dist/config/settings.js +15 -0
- package/dist/config/settings.js.map +1 -1
- package/dist/config/user-config.d.ts +7 -0
- package/dist/config/user-config.d.ts.map +1 -1
- package/dist/config/user-config.js +2 -0
- package/dist/config/user-config.js.map +1 -1
- package/dist/goal-loop/driver.d.ts +18 -0
- package/dist/goal-loop/driver.d.ts.map +1 -1
- package/dist/goal-loop/driver.js +100 -1
- package/dist/goal-loop/driver.js.map +1 -1
- package/dist/i18n.d.ts +6 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +8 -0
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/quota/resume.d.ts +66 -0
- package/dist/quota/resume.d.ts.map +1 -0
- package/dist/quota/resume.js +217 -0
- package/dist/quota/resume.js.map +1 -0
- package/dist/remote/hub-server.d.ts.map +1 -1
- package/dist/remote/hub-server.js +29 -0
- package/dist/remote/hub-server.js.map +1 -1
- package/dist/remote/system-stats.d.ts +137 -0
- package/dist/remote/system-stats.d.ts.map +1 -0
- package/dist/remote/system-stats.js +335 -0
- package/dist/remote/system-stats.js.map +1 -0
- package/dist/remote/workflow-overview.d.ts +7 -1
- package/dist/remote/workflow-overview.d.ts.map +1 -1
- package/dist/remote/workflow-overview.js +135 -2
- package/dist/remote/workflow-overview.js.map +1 -1
- package/dist/workflow/quota-resume.d.ts +135 -0
- package/dist/workflow/quota-resume.d.ts.map +1 -0
- package/dist/workflow/quota-resume.js +773 -0
- package/dist/workflow/quota-resume.js.map +1 -0
- package/docs/DEVELOPMENT.md +7 -0
- package/docs/REMOTE-CLIENTS.md +40 -5
- 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"}
|