@songsid/agend 2.1.5-beta.2 → 2.1.5-beta.4

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.
@@ -1,6 +1,14 @@
1
1
  import type { ChannelAdapter } from "./channel/types.js";
2
2
  export interface RestartProgressTarget {
3
- adapter: ChannelAdapter;
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,12 @@ 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
29
  mode?: "restart" | "update";
21
30
  }
31
+ export declare const RESTART_PROGRESS_TERMINAL_TIMEOUT_MS = 30000;
22
32
  /** One General-topic message that is edited throughout a fleet startup. */
23
33
  export declare class RestartProgress {
24
34
  readonly total: number;
@@ -30,7 +40,10 @@ export declare class RestartProgress {
30
40
  private messageId;
31
41
  private lastReportedReady;
32
42
  private updateTimer;
33
- private editChain;
43
+ /** At most one provider edit is active and one newest progress frame waits
44
+ * behind it. This prevents a slow adapter from accumulating 1 Hz history. */
45
+ private progressEditWorker;
46
+ private pendingProgressText;
34
47
  private finished;
35
48
  private readonly mode;
36
49
  constructor(total: number, startedAt: number, logger: ProgressLogger, options?: RestartProgressOptions);
@@ -40,10 +53,24 @@ export declare class RestartProgress {
40
53
  start(target: RestartProgressTarget | null): Promise<boolean>;
41
54
  /** Adopt the pre-update message after the new fleet process reconnects. */
42
55
  resume(target: RestartProgressTarget | null, messageId: string): Promise<boolean>;
43
- /** Edit the original message to its terminal state. Returns true if it existed. */
56
+ /** Deliver the terminal state. Returns true only after an edit or fresh fallback succeeds. */
44
57
  finish(summary?: RestartProgressSummary): Promise<boolean>;
45
58
  get readyCount(): number;
46
59
  private queueProgressEdit;
47
- private enqueueEdit;
60
+ private resolveAdapter;
61
+ private adapterReady;
62
+ /** Tail-only coalescing for non-terminal progress. */
63
+ private scheduleProgressEdit;
64
+ private drainProgressEdits;
65
+ /**
66
+ * A terminal state must mean "delivered", not merely "had a message id".
67
+ * Wait through a bounded adapter-recovery window, re-resolving replacement
68
+ * adapter objects each time. If editing the adopted message fails, post a
69
+ * fresh completion message so the user is never left at the last X/N update.
70
+ */
71
+ private deliverTerminal;
72
+ private waitForReadyAdapter;
73
+ private beforeDeadline;
74
+ private terminalDeliveryFailed;
48
75
  }
49
76
  export {};
@@ -1,5 +1,7 @@
1
1
  import { t } from "./locale.js";
2
2
  import { updateElapsedSeconds } from "./update-progress.js";
3
+ const TERMINAL_DELIVERY_RETRY_MS = 1_000;
4
+ export const RESTART_PROGRESS_TERMINAL_TIMEOUT_MS = 30_000;
3
5
  function formatElapsed(ms) {
4
6
  const seconds = Math.max(0, Math.floor(ms / 1000));
5
7
  const minutes = Math.floor(seconds / 60);
@@ -17,7 +19,10 @@ export class RestartProgress {
17
19
  messageId = null;
18
20
  lastReportedReady = 0;
19
21
  updateTimer = null;
20
- editChain = Promise.resolve();
22
+ /** At most one provider edit is active and one newest progress frame waits
23
+ * behind it. This prevents a slow adapter from accumulating 1 Hz history. */
24
+ progressEditWorker = null;
25
+ pendingProgressText = null;
21
26
  finished = false;
22
27
  mode;
23
28
  constructor(total, startedAt, logger, options = {}) {
@@ -40,9 +45,12 @@ export class RestartProgress {
40
45
  async start(target) {
41
46
  if (!this.enabled || !target || this.messageId || this.finished)
42
47
  return false;
48
+ const adapter = this.resolveAdapter(target);
49
+ if (!adapter)
50
+ return false;
43
51
  this.target = target;
44
52
  try {
45
- const sent = await target.adapter.sendText(target.chatId, `🔄 Fleet restarting — ${this.total} instances starting...`, { threadId: target.threadId });
53
+ const sent = await adapter.sendText(target.chatId, `🔄 Fleet restarting — ${this.total} instances starting...`, { threadId: target.threadId });
46
54
  this.messageId = sent.messageId;
47
55
  if (this.ready >= 5)
48
56
  this.queueProgressEdit();
@@ -60,19 +68,27 @@ export class RestartProgress {
60
68
  async resume(target, messageId) {
61
69
  if (!this.enabled || this.mode !== "update" || !target || !messageId || this.finished)
62
70
  return false;
71
+ if (!target.adapter && !target.resolveAdapter)
72
+ return false;
63
73
  this.target = target;
64
74
  this.messageId = messageId;
65
- this.enqueueEdit(t("update.progress.starting", updateElapsedSeconds(this.startedAt)));
66
- await this.editChain;
75
+ // Do not let a stuck provider call hold fleet startup. The coalescing worker
76
+ // owns this best-effort progress frame; finish() has its own hard deadline.
77
+ this.scheduleProgressEdit(t("update.progress.starting", updateElapsedSeconds(this.startedAt)));
67
78
  this.updateTimer = setInterval(() => this.queueProgressEdit(), 1_000);
68
79
  this.updateTimer.unref?.();
69
80
  return true;
70
81
  }
71
- /** Edit the original message to its terminal state. Returns true if it existed. */
82
+ /** Deliver the terminal state. Returns true only after an edit or fresh fallback succeeds. */
72
83
  async finish(summary) {
73
84
  if (!this.enabled)
74
85
  return false;
86
+ // Capture the current worker before preventing it from starting any newer
87
+ // pending frame. The terminal path waits for this exact edit so the final
88
+ // edit cannot overtake an ordinary, healthy provider round trip.
89
+ const progressEditWorker = this.progressEditWorker;
75
90
  this.finished = true;
91
+ this.pendingProgressText = null;
76
92
  if (this.updateTimer) {
77
93
  clearInterval(this.updateTimer);
78
94
  this.updateTimer = null;
@@ -94,9 +110,7 @@ export class RestartProgress {
94
110
  if (this.mode === "update" && summary?.tipText) {
95
111
  lines.push("", summary.tipText);
96
112
  }
97
- this.enqueueEdit(lines.join("\n"));
98
- await this.editChain;
99
- return true;
113
+ return this.deliverTerminal(lines.join("\n"), progressEditWorker);
100
114
  }
101
115
  get readyCount() { return this.ready; }
102
116
  queueProgressEdit() {
@@ -106,16 +120,153 @@ export class RestartProgress {
106
120
  const text = this.mode === "update"
107
121
  ? t("update.progress.instances", this.ready, this.total, updateElapsedSeconds(this.startedAt))
108
122
  : `🔄 Fleet restarting — ${this.ready}/${this.total} ready...`;
109
- this.enqueueEdit(text);
123
+ this.scheduleProgressEdit(text);
110
124
  }
111
- enqueueEdit(text) {
112
- const target = this.target;
113
- const messageId = this.messageId;
114
- if (!target || !messageId)
125
+ resolveAdapter(target = this.target) {
126
+ if (!target)
127
+ return undefined;
128
+ return target.resolveAdapter ? target.resolveAdapter() : target.adapter;
129
+ }
130
+ adapterReady(adapter) {
131
+ const health = adapter.getHealthSnapshot?.();
132
+ return !health || health.isReady;
133
+ }
134
+ /** Tail-only coalescing for non-terminal progress. */
135
+ scheduleProgressEdit(text) {
136
+ if (this.finished || !this.target || !this.messageId)
115
137
  return;
116
- this.editChain = this.editChain
117
- .then(() => target.adapter.editMessage(target.chatId, messageId, text, target.threadId))
118
- .catch(err => this.logger.warn({ err }, "Failed to edit fleet restart progress"));
138
+ this.pendingProgressText = text;
139
+ if (this.progressEditWorker)
140
+ return;
141
+ const worker = this.drainProgressEdits();
142
+ this.progressEditWorker = worker;
143
+ const complete = () => {
144
+ if (this.progressEditWorker === worker)
145
+ this.progressEditWorker = null;
146
+ if (!this.finished && this.pendingProgressText != null)
147
+ this.scheduleProgressEdit(this.pendingProgressText);
148
+ };
149
+ void worker.then(complete, err => {
150
+ this.logger.warn({ err }, "Fleet restart progress worker failed");
151
+ complete();
152
+ });
153
+ }
154
+ async drainProgressEdits() {
155
+ while (!this.finished) {
156
+ const text = this.pendingProgressText;
157
+ if (text == null)
158
+ return;
159
+ this.pendingProgressText = null;
160
+ const target = this.target;
161
+ const messageId = this.messageId;
162
+ const adapter = this.resolveAdapter(target);
163
+ if (!target || !messageId || !adapter || !this.adapterReady(adapter))
164
+ continue;
165
+ try {
166
+ await adapter.editMessage(target.chatId, messageId, text, target.threadId);
167
+ }
168
+ catch (err) {
169
+ this.logger.warn({ err }, "Failed to edit fleet restart progress");
170
+ }
171
+ }
172
+ }
173
+ /**
174
+ * A terminal state must mean "delivered", not merely "had a message id".
175
+ * Wait through a bounded adapter-recovery window, re-resolving replacement
176
+ * adapter objects each time. If editing the adopted message fails, post a
177
+ * fresh completion message so the user is never left at the last X/N update.
178
+ */
179
+ async deliverTerminal(text, progressEditWorker) {
180
+ const target = this.target;
181
+ if (!target || !this.messageId)
182
+ return false;
183
+ const deadline = Date.now() + RESTART_PROGRESS_TERMINAL_TIMEOUT_MS;
184
+ if (progressEditWorker) {
185
+ const drained = await this.beforeDeadline(() => progressEditWorker, deadline);
186
+ if (drained.status === "timeout") {
187
+ this.logger.warn({}, "Timed out waiting for the in-flight fleet progress edit before terminal delivery");
188
+ return this.terminalDeliveryFailed();
189
+ }
190
+ if (drained.status === "rejected") {
191
+ this.logger.warn({ err: drained.reason }, "Fleet progress edit worker rejected before terminal delivery");
192
+ }
193
+ }
194
+ let adapter = await this.waitForReadyAdapter(deadline);
195
+ if (!adapter)
196
+ return this.terminalDeliveryFailed();
197
+ const editAdapter = adapter;
198
+ const edit = await this.beforeDeadline(() => editAdapter.editMessage(target.chatId, this.messageId, text, target.threadId), deadline);
199
+ if (edit.status === "fulfilled")
200
+ return true;
201
+ if (edit.status === "rejected") {
202
+ this.logger.warn({ err: edit.reason }, "Failed to edit fleet restart progress terminal state");
203
+ }
204
+ else {
205
+ this.logger.warn({}, "Timed out editing fleet restart progress terminal state");
206
+ }
207
+ // The edit may have failed because the gateway dropped between the first
208
+ // readiness probe and the write. Re-check and, if necessary, wait for the
209
+ // replacement generation before the one and only fresh-send attempt.
210
+ adapter = await this.waitForReadyAdapter(deadline);
211
+ if (!adapter)
212
+ return this.terminalDeliveryFailed();
213
+ const sendAdapter = adapter;
214
+ const sent = await this.beforeDeadline(() => sendAdapter.sendText(target.chatId, text, { threadId: target.threadId }), deadline);
215
+ if (sent.status === "fulfilled") {
216
+ this.logger.warn({}, "Posted fresh fleet completion after terminal progress edit was unavailable");
217
+ return true;
218
+ }
219
+ if (sent.status === "rejected") {
220
+ this.logger.warn({ err: sent.reason }, "Failed to post fresh fleet completion after edit failure");
221
+ }
222
+ else {
223
+ this.logger.warn({}, "Timed out posting fresh fleet completion after edit failure");
224
+ }
225
+ return this.terminalDeliveryFailed();
226
+ }
227
+ async waitForReadyAdapter(deadline) {
228
+ while (true) {
229
+ const remaining = deadline - Date.now();
230
+ if (remaining <= 0)
231
+ return undefined;
232
+ const adapter = this.resolveAdapter();
233
+ if (adapter && this.adapterReady(adapter))
234
+ return adapter;
235
+ await new Promise(resolve => {
236
+ const timer = setTimeout(resolve, Math.min(TERMINAL_DELIVERY_RETRY_MS, remaining));
237
+ timer.unref?.();
238
+ });
239
+ }
240
+ }
241
+ async beforeDeadline(start, deadline) {
242
+ const remaining = deadline - Date.now();
243
+ if (remaining <= 0)
244
+ return { status: "timeout" };
245
+ let work;
246
+ try {
247
+ work = start();
248
+ }
249
+ catch (reason) {
250
+ return { status: "rejected", reason };
251
+ }
252
+ let timer;
253
+ const timeout = new Promise(resolve => {
254
+ timer = setTimeout(() => resolve({ status: "timeout" }), remaining);
255
+ timer.unref?.();
256
+ });
257
+ const settled = work.then(value => ({ status: "fulfilled", value }), reason => ({ status: "rejected", reason }));
258
+ const result = await Promise.race([settled, timeout]);
259
+ if (timer)
260
+ clearTimeout(timer);
261
+ return result;
262
+ }
263
+ terminalDeliveryFailed() {
264
+ const data = { timeout_ms: RESTART_PROGRESS_TERMINAL_TIMEOUT_MS };
265
+ if (this.logger.error)
266
+ this.logger.error(data, "Fleet completion could not be delivered after adapter recovery wait");
267
+ else
268
+ this.logger.warn(data, "Fleet completion could not be delivered after adapter recovery wait");
269
+ return false;
119
270
  }
120
271
  }
121
272
  //# sourceMappingURL=restart-progress.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"restart-progress.js","sourceRoot":"","sources":["../src/restart-progress.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"restart-progress.js","sourceRoot":"","sources":["../src/restart-progress.ts"],"names":[],"mappings":"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"}
@@ -142,6 +142,45 @@ export type KiroAuthKind = "q-developer-pro" | "builder-id";
142
142
  export declare function kiroAuthKind(token: KiroToken): KiroAuthKind;
143
143
  /** Exported for tests: the Q-Pro and expired paths return without any network call. */
144
144
  export declare function fetchKiroUsage(): Promise<Omit<ProviderUsage, "id" | "name">>;
145
+ type UsageProvider = {
146
+ id: string;
147
+ name: string;
148
+ fetch: () => Promise<Omit<ProviderUsage, "id" | "name">>;
149
+ };
150
+ /** Test seam: a provider that hangs cannot be simulated with real vendors. */
151
+ export declare function setUsageProvidersForTests(providers: UsageProvider[] | null): void;
152
+ /**
153
+ * Upper bound on one provider's whole chain.
154
+ *
155
+ * Every individual fetch already carries an AbortSignal timeout, but several
156
+ * providers chain them and nothing bounded the total: grok can refresh, query,
157
+ * re-refresh on a 401 and query again (up to ~50s), and antigravity refreshes
158
+ * its token then tries each Cloud Code base in turn (up to ~45s). Since
159
+ * fetchAllUsage waits for the slowest provider, and usage-api.ts shares a single
160
+ * in-flight promise across /api/ai-usage, the /usage command and the get_usage
161
+ * tool, one slow vendor stalled every surface at once — and a provider that
162
+ * never settled left that in-flight promise uncleared, so the stall persisted
163
+ * and retries simply joined the same dead promise.
164
+ *
165
+ * This deadline is what guarantees the snapshot always settles.
166
+ *
167
+ * It is set just above the longest *legitimate* single operation — a token
168
+ * refresh carries a 15s AbortSignal timeout — so a refresh that is slow but
169
+ * would have succeeded is not cut short and reported as unreachable. The hangs
170
+ * this bounds are 45–50s and come from *chains* of such operations, and since
171
+ * the deadline wraps a provider's whole chain, 16s still cuts those down
172
+ * drastically. A tighter value (8s was tried) bounds the snapshot harder but
173
+ * manufactures false "could not be reached" rows for slow-but-healthy refreshes.
174
+ */
175
+ export declare const DEFAULT_PROVIDER_DEADLINE_MS = 16000;
176
+ /**
177
+ * The longest AbortSignal timeout any single legitimate operation carries (the
178
+ * token refreshes). The deadline above must stay greater than this, or a slow
179
+ * refresh that would have succeeded gets reported as unreachable.
180
+ */
181
+ export declare const LONGEST_SINGLE_FETCH_MS = 15000;
182
+ /** Test seam: keeps the deadline regression fast. */
183
+ export declare function setUsageProviderDeadlineForTests(ms: number | null): void;
145
184
  /** Fetch every provider in parallel. Providers without local credentials are
146
185
  * skipped (per the panel's contract: absent CLIs simply don't show). */
147
186
  export declare function fetchAllUsage(): Promise<{
@@ -1109,20 +1109,86 @@ export async function fetchKiroUsage() {
1109
1109
  }
1110
1110
  return { status: "ok", plan, metrics };
1111
1111
  }
1112
- // ── Registry ─────────────────────────────────────────────────────────────────
1113
- const PROVIDERS = [
1112
+ const DEFAULT_PROVIDERS = [
1114
1113
  { id: "claude", name: "Claude", fetch: fetchClaudeUsage },
1115
1114
  { id: "codex", name: "Codex", fetch: fetchCodexUsage },
1116
1115
  { id: "grok", name: "Grok", fetch: fetchGrokUsage },
1117
1116
  { id: "kiro", name: "Kiro", fetch: fetchKiroUsage },
1118
1117
  { id: "antigravity", name: "Antigravity", fetch: fetchAntigravityUsage },
1119
1118
  ];
1119
+ let PROVIDERS = DEFAULT_PROVIDERS;
1120
+ /** Test seam: a provider that hangs cannot be simulated with real vendors. */
1121
+ export function setUsageProvidersForTests(providers) {
1122
+ PROVIDERS = providers ?? DEFAULT_PROVIDERS;
1123
+ }
1124
+ /**
1125
+ * Upper bound on one provider's whole chain.
1126
+ *
1127
+ * Every individual fetch already carries an AbortSignal timeout, but several
1128
+ * providers chain them and nothing bounded the total: grok can refresh, query,
1129
+ * re-refresh on a 401 and query again (up to ~50s), and antigravity refreshes
1130
+ * its token then tries each Cloud Code base in turn (up to ~45s). Since
1131
+ * fetchAllUsage waits for the slowest provider, and usage-api.ts shares a single
1132
+ * in-flight promise across /api/ai-usage, the /usage command and the get_usage
1133
+ * tool, one slow vendor stalled every surface at once — and a provider that
1134
+ * never settled left that in-flight promise uncleared, so the stall persisted
1135
+ * and retries simply joined the same dead promise.
1136
+ *
1137
+ * This deadline is what guarantees the snapshot always settles.
1138
+ *
1139
+ * It is set just above the longest *legitimate* single operation — a token
1140
+ * refresh carries a 15s AbortSignal timeout — so a refresh that is slow but
1141
+ * would have succeeded is not cut short and reported as unreachable. The hangs
1142
+ * this bounds are 45–50s and come from *chains* of such operations, and since
1143
+ * the deadline wraps a provider's whole chain, 16s still cuts those down
1144
+ * drastically. A tighter value (8s was tried) bounds the snapshot harder but
1145
+ * manufactures false "could not be reached" rows for slow-but-healthy refreshes.
1146
+ */
1147
+ export const DEFAULT_PROVIDER_DEADLINE_MS = 16_000;
1148
+ /**
1149
+ * The longest AbortSignal timeout any single legitimate operation carries (the
1150
+ * token refreshes). The deadline above must stay greater than this, or a slow
1151
+ * refresh that would have succeeded gets reported as unreachable.
1152
+ */
1153
+ export const LONGEST_SINGLE_FETCH_MS = 15_000;
1154
+ let providerDeadlineMs = DEFAULT_PROVIDER_DEADLINE_MS;
1155
+ /** Test seam: keeps the deadline regression fast. */
1156
+ export function setUsageProviderDeadlineForTests(ms) {
1157
+ providerDeadlineMs = ms ?? DEFAULT_PROVIDER_DEADLINE_MS;
1158
+ }
1159
+ const DEADLINE_EXCEEDED = Symbol("usage-provider-deadline");
1160
+ async function withDeadline(work, ms) {
1161
+ // Once the deadline wins the race, a late rejection from the abandoned chain
1162
+ // would otherwise surface as an unhandled rejection.
1163
+ work.catch(() => { });
1164
+ let timer;
1165
+ const deadline = new Promise(resolve => {
1166
+ timer = setTimeout(() => resolve(DEADLINE_EXCEEDED), ms);
1167
+ });
1168
+ try {
1169
+ return await Promise.race([work, deadline]);
1170
+ }
1171
+ finally {
1172
+ clearTimeout(timer);
1173
+ }
1174
+ }
1120
1175
  /** Fetch every provider in parallel. Providers without local credentials are
1121
1176
  * skipped (per the panel's contract: absent CLIs simply don't show). */
1122
1177
  export async function fetchAllUsage() {
1123
1178
  const results = await Promise.all(PROVIDERS.map(async (p) => {
1124
1179
  try {
1125
- return { id: p.id, name: p.name, ...(await p.fetch()) };
1180
+ const outcome = await withDeadline(p.fetch(), providerDeadlineMs);
1181
+ if (outcome === DEADLINE_EXCEEDED) {
1182
+ // Fail soft: this row says it could not be read, the rest still answer,
1183
+ // and the snapshot returns in bounded time.
1184
+ return {
1185
+ id: p.id, name: p.name, status: "error",
1186
+ error: `Could not reach ${p.name}.`,
1187
+ errorI18n: i18n("usage.error.unreachable", p.name),
1188
+ metrics: [],
1189
+ };
1190
+ }
1191
+ return { id: p.id, name: p.name, ...outcome };
1126
1192
  }
1127
1193
  catch (err) {
1128
1194
  return { id: p.id, name: p.name, status: "error", error: String(err?.message ?? err), metrics: [] };