@songsid/agend 2.1.4 → 2.1.5-beta.10
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/backend/claude-code.js +2 -2
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/types.d.ts +22 -0
- package/dist/backend/types.js +23 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +2 -0
- package/dist/channel/adapters/discord.js +25 -3
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +5 -0
- package/dist/channel/adapters/telegram.js +11 -0
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/types.d.ts +7 -0
- package/dist/cli.js +37 -37
- package/dist/cli.js.map +1 -1
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +38 -0
- package/dist/daemon.js +95 -43
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +5 -0
- package/dist/fleet-manager.d.ts +126 -0
- package/dist/fleet-manager.js +688 -95
- package/dist/fleet-manager.js.map +1 -1
- package/dist/full-restart.d.ts +20 -0
- package/dist/full-restart.js +39 -0
- package/dist/full-restart.js.map +1 -0
- package/dist/locale.js +72 -2
- package/dist/locale.js.map +1 -1
- package/dist/login-controller.d.ts +127 -0
- package/dist/login-controller.js +450 -0
- package/dist/login-controller.js.map +1 -0
- package/dist/login-flows.d.ts +41 -3
- package/dist/login-flows.js +37 -5
- package/dist/login-flows.js.map +1 -1
- package/dist/login-manager.d.ts +12 -1
- package/dist/login-manager.js +64 -7
- package/dist/login-manager.js.map +1 -1
- package/dist/login-window-lock.d.ts +26 -0
- package/dist/login-window-lock.js +64 -0
- package/dist/login-window-lock.js.map +1 -0
- package/dist/restart-progress.d.ts +35 -5
- package/dist/restart-progress.js +195 -34
- package/dist/restart-progress.js.map +1 -1
- package/dist/service-restart-selection.d.ts +27 -0
- package/dist/service-restart-selection.js +25 -0
- package/dist/service-restart-selection.js.map +1 -0
- package/dist/tmux-manager.d.ts +19 -0
- package/dist/tmux-manager.js +79 -12
- package/dist/tmux-manager.js.map +1 -1
- package/dist/topic-commands.js +23 -7
- package/dist/topic-commands.js.map +1 -1
- package/dist/types.d.ts +18 -0
- package/dist/ui/web-terminal/terminal.css +17 -0
- package/dist/ui/web-terminal/terminal.html +44 -0
- package/dist/ui/web-terminal/terminal.js +148 -0
- package/dist/ui/web-terminal/vendor/LICENSE.addon-fit +19 -0
- package/dist/ui/web-terminal/vendor/LICENSE.addon-web-links +19 -0
- package/dist/ui/web-terminal/vendor/LICENSE.xterm +21 -0
- package/dist/ui/web-terminal/vendor/VENDORED.md +22 -0
- package/dist/ui/web-terminal/vendor/addon-fit.js +1 -0
- package/dist/ui/web-terminal/vendor/addon-web-links.js +1 -0
- package/dist/ui/web-terminal/vendor/xterm.css +285 -0
- package/dist/ui/web-terminal/vendor/xterm.js +1 -0
- package/dist/update-marker.d.ts +11 -1
- package/dist/update-marker.js +19 -4
- package/dist/update-marker.js.map +1 -1
- package/dist/update-progress.d.ts +1 -1
- package/dist/update-progress.js +12 -0
- package/dist/update-progress.js.map +1 -1
- package/dist/usage/providers.d.ts +39 -0
- package/dist/usage/providers.js +69 -3
- package/dist/usage/providers.js.map +1 -1
- package/dist/web-terminal-http.d.ts +61 -0
- package/dist/web-terminal-http.js +422 -0
- package/dist/web-terminal-http.js.map +1 -0
- package/dist/web-terminal.d.ts +336 -0
- package/dist/web-terminal.js +888 -0
- package/dist/web-terminal.js.map +1 -0
- package/dist/ws-server.d.ts +69 -0
- package/dist/ws-server.js +392 -0
- package/dist/ws-server.js.map +1 -0
- package/package.json +1 -1
package/dist/login-flows.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-flows.js","sourceRoot":"","sources":["../src/login-flows.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"login-flows.js","sourceRoot":"","sources":["../src/login-flows.ts"],"names":[],"mappings":"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"}
|
package/dist/login-manager.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { Logger } from "./logger.js";
|
|
|
11
11
|
import { type LoginFlow } from "./login-flows.js";
|
|
12
12
|
/** The slice of TmuxManager a login session drives (injectable for tests). */
|
|
13
13
|
export interface LoginTmux {
|
|
14
|
+
/** Must complete or fail within a hard bound; a window it may have created is reachable by `windowName` even if the id was never learned. */
|
|
14
15
|
createWindow(command: string, cwd: string, windowName?: string): Promise<string>;
|
|
15
16
|
setRemainOnExit(): Promise<void>;
|
|
16
17
|
capturePaneJoined(lines?: number): Promise<string>;
|
|
@@ -19,6 +20,8 @@ export interface LoginTmux {
|
|
|
19
20
|
exitCode?: number;
|
|
20
21
|
} | null>;
|
|
21
22
|
killWindow(): Promise<void>;
|
|
23
|
+
/** Kill the window and CONFIRM it is gone; false when it may still exist. TmuxManager.killWindow() alone swallows errors. */
|
|
24
|
+
killWindowConfirmed?(): Promise<boolean>;
|
|
22
25
|
sendSpecialKey(key: "Enter" | "Escape" | "Up" | "Down" | "Right" | "Left" | "C-c" | "C-q"): Promise<boolean>;
|
|
23
26
|
pasteText(text: string, opts?: {
|
|
24
27
|
retryEnter?: boolean;
|
|
@@ -31,10 +34,11 @@ export interface LoginSessionEvents {
|
|
|
31
34
|
onAuthHint(url: string, code: string | null): void | Promise<void>;
|
|
32
35
|
/** The CLI is waiting for admin-supplied text (`/login code <text>`). */
|
|
33
36
|
onNeedInput(promptExcerpt: string): void | Promise<void>;
|
|
34
|
-
/** Terminal state — exactly once per session. */
|
|
37
|
+
/** Terminal state — exactly once per session. cleanupFailed: the window could not be confirmed removed. */
|
|
35
38
|
onDone(result: {
|
|
36
39
|
ok: boolean;
|
|
37
40
|
detail: string;
|
|
41
|
+
cleanupFailed?: boolean;
|
|
38
42
|
}): void | Promise<void>;
|
|
39
43
|
}
|
|
40
44
|
export type LoginSessionState = "starting" | "menu" | "waiting" | "input" | "done";
|
|
@@ -50,6 +54,10 @@ export declare class LoginSession {
|
|
|
50
54
|
private sentUrl;
|
|
51
55
|
private lastInputPrompt;
|
|
52
56
|
private finished;
|
|
57
|
+
/** Single-flight teardown: every cancel/finish caller — and start() — joins this one promise. */
|
|
58
|
+
private finishing;
|
|
59
|
+
/** The createWindow() in flight, so finish() can wait for the window to exist before killing it. */
|
|
60
|
+
private startInFlight;
|
|
53
61
|
constructor(flow: LoginFlow, tmux: LoginTmux, events: LoginSessionEvents, logger: Logger, pollIntervalMs?: number);
|
|
54
62
|
start(): Promise<void>;
|
|
55
63
|
/** Admin picked menu option N: Down×N then Enter, matching the CLI selector. */
|
|
@@ -59,5 +67,8 @@ export declare class LoginSession {
|
|
|
59
67
|
cancel(reason?: string): Promise<void>;
|
|
60
68
|
private schedulePoll;
|
|
61
69
|
private poll;
|
|
70
|
+
/** Remove whatever the startup may have created; true only when confirmed absent. */
|
|
71
|
+
private rollbackWindow;
|
|
62
72
|
private finish;
|
|
73
|
+
private doFinish;
|
|
63
74
|
}
|
package/dist/login-manager.js
CHANGED
|
@@ -13,6 +13,10 @@ export class LoginSession {
|
|
|
13
13
|
sentUrl = null;
|
|
14
14
|
lastInputPrompt = null;
|
|
15
15
|
finished = false;
|
|
16
|
+
/** Single-flight teardown: every cancel/finish caller — and start() — joins this one promise. */
|
|
17
|
+
finishing = null;
|
|
18
|
+
/** The createWindow() in flight, so finish() can wait for the window to exist before killing it. */
|
|
19
|
+
startInFlight = null;
|
|
16
20
|
constructor(flow, tmux, events, logger, pollIntervalMs = POLL_INTERVAL_MS) {
|
|
17
21
|
this.flow = flow;
|
|
18
22
|
this.tmux = tmux;
|
|
@@ -25,8 +29,37 @@ export class LoginSession {
|
|
|
25
29
|
// prints "Successfully logged in" and exits is still observable; without it
|
|
26
30
|
// the window vanishes between polls and success is indistinguishable from a
|
|
27
31
|
// crash.
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
// finish() waits for this before its one confirmed kill, so a cancel that
|
|
33
|
+
// races createWindow still removes the window — and reports if it cannot.
|
|
34
|
+
this.startInFlight = this.tmux.createWindow(this.flow.command, process.env.HOME ?? "/", `agend-login-${this.flow.backend}`);
|
|
35
|
+
try {
|
|
36
|
+
await this.startInFlight;
|
|
37
|
+
// finish() owns the cleanup; start() must not return before it completes,
|
|
38
|
+
// or the caller would publish "started" for a window being torn down.
|
|
39
|
+
if (this.finishing) {
|
|
40
|
+
await this.finishing;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
await this.tmux.setRemainOnExit();
|
|
44
|
+
if (this.finishing) {
|
|
45
|
+
await this.finishing;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
if (this.finishing) {
|
|
51
|
+
await this.finishing;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Plain startup failure (no cancel in flight): new-window may have
|
|
55
|
+
// succeeded server-side before the client timed out, or setRemainOnExit
|
|
56
|
+
// failed after the window existed. Roll back — by id or by name — and
|
|
57
|
+
// say so if it cannot be confirmed.
|
|
58
|
+
const confirmed = await this.rollbackWindow();
|
|
59
|
+
if (!confirmed)
|
|
60
|
+
err.cleanupFailed = true;
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
30
63
|
this.timeoutTimer = setTimeout(() => {
|
|
31
64
|
void this.finish(false, "timeout");
|
|
32
65
|
}, this.flow.timeoutMs);
|
|
@@ -115,17 +148,41 @@ export class LoginSession {
|
|
|
115
148
|
}
|
|
116
149
|
this.schedulePoll();
|
|
117
150
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
151
|
+
/** Remove whatever the startup may have created; true only when confirmed absent. */
|
|
152
|
+
async rollbackWindow() {
|
|
153
|
+
if (this.tmux.killWindowConfirmed)
|
|
154
|
+
return this.tmux.killWindowConfirmed().catch(() => false);
|
|
155
|
+
return this.tmux.killWindow().then(() => true, () => false);
|
|
156
|
+
}
|
|
157
|
+
finish(ok, detail) {
|
|
158
|
+
if (this.finishing)
|
|
159
|
+
return this.finishing; // second cancel / shutdown joins the same teardown
|
|
160
|
+
this.finishing = this.doFinish(ok, detail);
|
|
161
|
+
return this.finishing;
|
|
162
|
+
}
|
|
163
|
+
async doFinish(ok, detail) {
|
|
121
164
|
this.finished = true;
|
|
122
165
|
this.state = "done";
|
|
123
166
|
if (this.pollTimer)
|
|
124
167
|
clearTimeout(this.pollTimer);
|
|
125
168
|
if (this.timeoutTimer)
|
|
126
169
|
clearTimeout(this.timeoutTimer);
|
|
127
|
-
|
|
128
|
-
|
|
170
|
+
// Wait for an in-flight createWindow to settle — no timer race: the
|
|
171
|
+
// primitive itself is bounded (TmuxManager gives the exec a hard timeout),
|
|
172
|
+
// and a window it created without reporting its id is still found by name.
|
|
173
|
+
if (this.startInFlight)
|
|
174
|
+
await this.startInFlight.catch(() => { });
|
|
175
|
+
let cleanupFailed = false;
|
|
176
|
+
if (this.tmux.killWindowConfirmed) {
|
|
177
|
+
cleanupFailed = !(await this.tmux.killWindowConfirmed().catch(() => false));
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
await this.tmux.killWindow().catch(() => { cleanupFailed = true; });
|
|
181
|
+
}
|
|
182
|
+
if (cleanupFailed)
|
|
183
|
+
this.logger.warn({ backend: this.flow.backend }, "login window could not be confirmed removed");
|
|
184
|
+
// Present only when true: existing consumers compare the payload exactly.
|
|
185
|
+
await this.events.onDone(cleanupFailed ? { ok, detail, cleanupFailed: true } : { ok, detail });
|
|
129
186
|
}
|
|
130
187
|
}
|
|
131
188
|
function delay(ms) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-manager.js","sourceRoot":"","sources":["../src/login-manager.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,gBAAgB,EAAkB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"login-manager.js","sourceRoot":"","sources":["../src/login-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type LoginWindowKind = "web" | "relay" | "install";
|
|
2
|
+
export interface LoginWindowClaim {
|
|
3
|
+
readonly id: number;
|
|
4
|
+
readonly kind: LoginWindowKind;
|
|
5
|
+
readonly backend: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class LoginWindowLock {
|
|
8
|
+
private owner;
|
|
9
|
+
private seq;
|
|
10
|
+
private closed;
|
|
11
|
+
get current(): LoginWindowClaim | null;
|
|
12
|
+
get isHeld(): boolean;
|
|
13
|
+
get isClosed(): boolean;
|
|
14
|
+
/** Take the window now, or null when it is held or the lock is closed. Never awaits. */
|
|
15
|
+
tryClaim(kind: LoginWindowKind, backend: string): LoginWindowClaim | null;
|
|
16
|
+
/** True while `claim` is the live owner and the lock is open — the condition for continuing after an await. */
|
|
17
|
+
isCurrent(claim: LoginWindowClaim | null | undefined): boolean;
|
|
18
|
+
/** Release only if `claim` is the current owner. Returns whether it was. */
|
|
19
|
+
release(claim: LoginWindowClaim | null | undefined): boolean;
|
|
20
|
+
/** Fleet shutdown: invalidate whatever is held (its continuation will see !isCurrent) and refuse new claims. */
|
|
21
|
+
close(): void;
|
|
22
|
+
/** In-process restart: accept claims again. */
|
|
23
|
+
reopen(): void;
|
|
24
|
+
/** The user-facing reason a new window cannot open right now. */
|
|
25
|
+
busyMessage(): string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fleet-wide "one login/install window at a time" reservation.
|
|
3
|
+
*
|
|
4
|
+
* Web login, the legacy relay login and /install-cli all share this lock. The
|
|
5
|
+
* claim is SYNCHRONOUS and must be taken before the caller's first await
|
|
6
|
+
* (auth pre-check, tmux ensureSession, …) — a check-then-await-then-claim
|
|
7
|
+
* sequence lets two concurrent starts both pass (sol B1, round 1).
|
|
8
|
+
*
|
|
9
|
+
* Ownership rules (sol round 2):
|
|
10
|
+
* - every post-claim exit must release, or transfer the claim to a published
|
|
11
|
+
* session that releases it on its own end — callers wrap the region in
|
|
12
|
+
* try/finally so a throwing factory/ensureSession cannot leak it;
|
|
13
|
+
* - release is identity-safe: only the exact claim object frees the slot;
|
|
14
|
+
* - `close()` (fleet shutdown) invalidates the current claim and refuses new
|
|
15
|
+
* ones; a continuation that resumes after an await must check
|
|
16
|
+
* `isCurrent(claim)` before publishing/starting anything. `reopen()`
|
|
17
|
+
* serves an in-process restart.
|
|
18
|
+
*/
|
|
19
|
+
import { t } from "./locale.js";
|
|
20
|
+
export class LoginWindowLock {
|
|
21
|
+
owner = null;
|
|
22
|
+
seq = 0;
|
|
23
|
+
closed = false;
|
|
24
|
+
get current() { return this.owner; }
|
|
25
|
+
get isHeld() { return this.owner !== null; }
|
|
26
|
+
get isClosed() { return this.closed; }
|
|
27
|
+
/** Take the window now, or null when it is held or the lock is closed. Never awaits. */
|
|
28
|
+
tryClaim(kind, backend) {
|
|
29
|
+
if (this.closed || this.owner)
|
|
30
|
+
return null;
|
|
31
|
+
this.owner = { id: ++this.seq, kind, backend };
|
|
32
|
+
return this.owner;
|
|
33
|
+
}
|
|
34
|
+
/** True while `claim` is the live owner and the lock is open — the condition for continuing after an await. */
|
|
35
|
+
isCurrent(claim) {
|
|
36
|
+
return !!claim && this.owner === claim && !this.closed;
|
|
37
|
+
}
|
|
38
|
+
/** Release only if `claim` is the current owner. Returns whether it was. */
|
|
39
|
+
release(claim) {
|
|
40
|
+
if (!claim || this.owner !== claim)
|
|
41
|
+
return false;
|
|
42
|
+
this.owner = null;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
/** Fleet shutdown: invalidate whatever is held (its continuation will see !isCurrent) and refuse new claims. */
|
|
46
|
+
close() {
|
|
47
|
+
this.closed = true;
|
|
48
|
+
this.owner = null;
|
|
49
|
+
}
|
|
50
|
+
/** In-process restart: accept claims again. */
|
|
51
|
+
reopen() {
|
|
52
|
+
this.closed = false;
|
|
53
|
+
}
|
|
54
|
+
/** The user-facing reason a new window cannot open right now. */
|
|
55
|
+
busyMessage() {
|
|
56
|
+
if (this.closed)
|
|
57
|
+
return t("login.web_shutting_down");
|
|
58
|
+
const o = this.owner;
|
|
59
|
+
if (!o)
|
|
60
|
+
return t("login.no_session");
|
|
61
|
+
return o.kind === "install" ? t("install.busy") : t("login.busy", o.backend);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=login-window-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-window-lock.js","sourceRoot":"","sources":["../src/login-window-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,aAAa,CAAC;AAUhC,MAAM,OAAO,eAAe;IAClB,KAAK,GAA4B,IAAI,CAAC;IACtC,GAAG,GAAG,CAAC,CAAC;IACR,MAAM,GAAG,KAAK,CAAC;IAEvB,IAAI,OAAO,KAA8B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,IAAI,MAAM,KAAc,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC;IACrD,IAAI,QAAQ,KAAc,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAE/C,wFAAwF;IACxF,QAAQ,CAAC,IAAqB,EAAE,OAAe;QAC7C,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,+GAA+G;IAC/G,SAAS,CAAC,KAA0C;QAClD,OAAO,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IACzD,CAAC;IAED,4EAA4E;IAC5E,OAAO,CAAC,KAA0C;QAChD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gHAAgH;IAChH,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,+CAA+C;IAC/C,MAAM;QACJ,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,iEAAiE;IACjE,WAAW;QACT,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,yBAAyB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,IAAI,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC;QACrC,OAAO,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/E,CAAC;CACF"}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { ChannelAdapter } from "./channel/types.js";
|
|
2
2
|
export interface RestartProgressTarget {
|
|
3
|
-
adapter
|
|
3
|
+
/** Initial adapter generation, when one already exists. Update recovery may
|
|
4
|
+
* start with no adapter object and rely solely on resolveAdapter(). */
|
|
5
|
+
adapter?: ChannelAdapter;
|
|
6
|
+
/**
|
|
7
|
+
* Re-resolve the adapter at delivery time. Adapter startup recovery replaces
|
|
8
|
+
* a failed adapter object in FleetManager, so a progress message adopted
|
|
9
|
+
* across process restart must not stay pinned to the stopped generation.
|
|
10
|
+
*/
|
|
11
|
+
resolveAdapter?: () => ChannelAdapter | undefined;
|
|
4
12
|
chatId: string;
|
|
5
13
|
threadId?: string;
|
|
6
14
|
}
|
|
@@ -15,10 +23,15 @@ export interface RestartProgressSummary {
|
|
|
15
23
|
}
|
|
16
24
|
type ProgressLogger = {
|
|
17
25
|
warn(data: unknown, message: string): void;
|
|
26
|
+
error?(data: unknown, message: string): void;
|
|
18
27
|
};
|
|
19
28
|
export interface RestartProgressOptions {
|
|
20
|
-
mode?:
|
|
29
|
+
mode?: RestartProgressMode;
|
|
21
30
|
}
|
|
31
|
+
export type RestartProgressMode = "restart" | "update" | "reload";
|
|
32
|
+
export declare const RESTART_PROGRESS_TERMINAL_TIMEOUT_MS = 30000;
|
|
33
|
+
/** One terminal text shared by the in-place edit and FleetManager fallback. */
|
|
34
|
+
export declare function formatRestartProgressCompletion(mode: RestartProgressMode, summary: RestartProgressSummary, startedAt: number, now?: number): string;
|
|
22
35
|
/** One General-topic message that is edited throughout a fleet startup. */
|
|
23
36
|
export declare class RestartProgress {
|
|
24
37
|
readonly total: number;
|
|
@@ -30,7 +43,10 @@ export declare class RestartProgress {
|
|
|
30
43
|
private messageId;
|
|
31
44
|
private lastReportedReady;
|
|
32
45
|
private updateTimer;
|
|
33
|
-
|
|
46
|
+
/** At most one provider edit is active and one newest progress frame waits
|
|
47
|
+
* behind it. This prevents a slow adapter from accumulating 1 Hz history. */
|
|
48
|
+
private progressEditWorker;
|
|
49
|
+
private pendingProgressText;
|
|
34
50
|
private finished;
|
|
35
51
|
private readonly mode;
|
|
36
52
|
constructor(total: number, startedAt: number, logger: ProgressLogger, options?: RestartProgressOptions);
|
|
@@ -40,10 +56,24 @@ export declare class RestartProgress {
|
|
|
40
56
|
start(target: RestartProgressTarget | null): Promise<boolean>;
|
|
41
57
|
/** Adopt the pre-update message after the new fleet process reconnects. */
|
|
42
58
|
resume(target: RestartProgressTarget | null, messageId: string): Promise<boolean>;
|
|
43
|
-
/**
|
|
59
|
+
/** Deliver the terminal state. Returns true only after an edit or fresh fallback succeeds. */
|
|
44
60
|
finish(summary?: RestartProgressSummary): Promise<boolean>;
|
|
45
61
|
get readyCount(): number;
|
|
46
62
|
private queueProgressEdit;
|
|
47
|
-
private
|
|
63
|
+
private resolveAdapter;
|
|
64
|
+
private adapterReady;
|
|
65
|
+
/** Tail-only coalescing for non-terminal progress. */
|
|
66
|
+
private scheduleProgressEdit;
|
|
67
|
+
private drainProgressEdits;
|
|
68
|
+
/**
|
|
69
|
+
* A terminal state must mean "delivered", not merely "had a message id".
|
|
70
|
+
* Wait through a bounded adapter-recovery window, re-resolving replacement
|
|
71
|
+
* adapter objects each time. If editing the adopted message fails, post a
|
|
72
|
+
* fresh completion message so the user is never left at the last X/N update.
|
|
73
|
+
*/
|
|
74
|
+
private deliverTerminal;
|
|
75
|
+
private waitForReadyAdapter;
|
|
76
|
+
private beforeDeadline;
|
|
77
|
+
private terminalDeliveryFailed;
|
|
48
78
|
}
|
|
49
79
|
export {};
|