@narumitw/pi-usage 0.54.0 → 0.58.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 +137 -64
- package/dist/index.ts +783 -173
- package/dist/index.ts.map +4 -4
- package/package.json +10 -10
- package/src/codex-fast-runtime.ts +34 -26
- package/src/format.ts +126 -7
- package/src/index.ts +9 -0
- package/src/providers/deepseek.ts +85 -0
- package/src/providers/fireworks.ts +198 -0
- package/src/query.ts +199 -13
- package/src/settings.ts +26 -6
- package/src/types.ts +19 -0
- package/src/usage-helpers.ts +2 -2
- package/src/usage-settings-ui.ts +130 -39
- package/src/usage.ts +156 -94
package/src/usage.ts
CHANGED
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
import { showUsageSettings } from "./usage-settings-ui.js";
|
|
57
57
|
|
|
58
58
|
const CACHE_TTL_MS = 5 * 60 * 1000;
|
|
59
|
+
const STATUS_COUNTDOWN_REFRESH_MS = 60 * 1000;
|
|
59
60
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
60
61
|
const ALL_PROVIDER_CONCURRENCY = 2;
|
|
61
62
|
const FAILURE_BACKOFF_MS = 30_000;
|
|
@@ -103,23 +104,26 @@ export default function usageExtension(
|
|
|
103
104
|
let sessionActive = false;
|
|
104
105
|
let statusGeneration = 0;
|
|
105
106
|
let sessionGeneration = 0;
|
|
106
|
-
let xaiSettingsGeneration = 0;
|
|
107
107
|
let statusRefreshTimer: ReturnType<typeof setTimeout> | undefined;
|
|
108
|
+
let statusCountdownTimer: ReturnType<typeof setTimeout> | undefined;
|
|
108
109
|
let statusController: AbortController | undefined;
|
|
109
110
|
let fastRuntime: ReturnType<typeof registerCodexFastMode>;
|
|
110
111
|
|
|
111
|
-
const
|
|
112
|
-
const state = settingsRuntime.get();
|
|
113
|
-
return state.kind !== "invalid" && state.settings.xaiUsage;
|
|
114
|
-
};
|
|
115
|
-
const activeAdapterForProvider = (providerId: string | undefined) =>
|
|
116
|
-
adapterForProvider(providerId, xaiUsageEnabled());
|
|
117
|
-
|
|
118
|
-
const clearStatusTimer = () => {
|
|
112
|
+
const clearStatusRefreshTimer = () => {
|
|
119
113
|
if (statusRefreshTimer) clearTimeout(statusRefreshTimer);
|
|
120
114
|
statusRefreshTimer = undefined;
|
|
121
115
|
};
|
|
122
116
|
|
|
117
|
+
const clearStatusCountdownTimer = () => {
|
|
118
|
+
if (statusCountdownTimer) clearTimeout(statusCountdownTimer);
|
|
119
|
+
statusCountdownTimer = undefined;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const clearStatusTimers = () => {
|
|
123
|
+
clearStatusRefreshTimer();
|
|
124
|
+
clearStatusCountdownTimer();
|
|
125
|
+
};
|
|
126
|
+
|
|
123
127
|
const safeSetStatus = (ctx: ExtensionContext, value: string | undefined): boolean => {
|
|
124
128
|
try {
|
|
125
129
|
ctx.ui.setStatus(STATUS_KEY, value);
|
|
@@ -134,12 +138,12 @@ export default function usageExtension(
|
|
|
134
138
|
statusGeneration += 1;
|
|
135
139
|
statusController?.abort();
|
|
136
140
|
statusController = undefined;
|
|
137
|
-
|
|
141
|
+
clearStatusTimers();
|
|
138
142
|
safeSetStatus(ctx, undefined);
|
|
139
143
|
};
|
|
140
144
|
|
|
141
145
|
const scheduleStatusRefresh = (ctx: ExtensionContext, model: PiModel) => {
|
|
142
|
-
|
|
146
|
+
clearStatusRefreshTimer();
|
|
143
147
|
const generation = statusGeneration;
|
|
144
148
|
statusRefreshTimer = setTimeout(() => {
|
|
145
149
|
statusRefreshTimer = undefined;
|
|
@@ -155,13 +159,14 @@ export default function usageExtension(
|
|
|
155
159
|
model: PiModel,
|
|
156
160
|
shouldSchedule: boolean,
|
|
157
161
|
) => {
|
|
158
|
-
|
|
159
|
-
|
|
162
|
+
clearStatusCountdownTimer();
|
|
163
|
+
if (adapterForProvider(model.provider)?.publishesStatusline === false) {
|
|
164
|
+
clearStatusRefreshTimer();
|
|
160
165
|
safeSetStatus(ctx, undefined);
|
|
161
166
|
return;
|
|
162
167
|
}
|
|
163
168
|
if (outcome.state.status === "unsupported") {
|
|
164
|
-
|
|
169
|
+
clearStatusRefreshTimer();
|
|
165
170
|
safeSetStatus(ctx, undefined);
|
|
166
171
|
return;
|
|
167
172
|
}
|
|
@@ -176,10 +181,43 @@ export default function usageExtension(
|
|
|
176
181
|
}
|
|
177
182
|
return;
|
|
178
183
|
}
|
|
179
|
-
const
|
|
184
|
+
const showCodexResetCountdown =
|
|
185
|
+
outcome.state.report.providerId === "openai-codex" &&
|
|
186
|
+
settingsRuntime.get().settings.codexStatusResetCountdown;
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
const rawValue = formatUsageStatusline(
|
|
189
|
+
outcome.state.report,
|
|
190
|
+
model,
|
|
191
|
+
now,
|
|
192
|
+
showCodexResetCountdown,
|
|
193
|
+
);
|
|
180
194
|
const value = rawValue ? fastRuntime.decorateStatus(model, rawValue) : undefined;
|
|
181
195
|
if (!safeSetStatus(ctx, value)) return;
|
|
182
196
|
if (shouldSchedule && sessionActive) scheduleStatusRefresh(ctx, model);
|
|
197
|
+
if (
|
|
198
|
+
sessionActive &&
|
|
199
|
+
showCodexResetCountdown &&
|
|
200
|
+
outcome.state.report.buckets.some(
|
|
201
|
+
(bucket) =>
|
|
202
|
+
bucket.resetsAt !== undefined &&
|
|
203
|
+
Number.isFinite(bucket.resetsAt) &&
|
|
204
|
+
bucket.resetsAt * 1_000 > now,
|
|
205
|
+
)
|
|
206
|
+
) {
|
|
207
|
+
const generation = statusGeneration;
|
|
208
|
+
statusCountdownTimer = setTimeout(() => {
|
|
209
|
+
statusCountdownTimer = undefined;
|
|
210
|
+
if (
|
|
211
|
+
!sessionActive ||
|
|
212
|
+
generation !== statusGeneration ||
|
|
213
|
+
modelIdentity(ctx.model) !== modelIdentity(model)
|
|
214
|
+
) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
publishStatus(ctx, outcome, model, false);
|
|
218
|
+
}, STATUS_COUNTDOWN_REFRESH_MS);
|
|
219
|
+
statusCountdownTimer.unref?.();
|
|
220
|
+
}
|
|
183
221
|
};
|
|
184
222
|
|
|
185
223
|
const invalidateProviderState = (providerId: string) => {
|
|
@@ -210,18 +248,22 @@ export default function usageExtension(
|
|
|
210
248
|
displayState: UsageDisplayState,
|
|
211
249
|
force: boolean,
|
|
212
250
|
signal: AbortSignal,
|
|
251
|
+
authRetry = 0,
|
|
252
|
+
deadlineAt = Date.now() + DEFAULT_TIMEOUT_MS,
|
|
213
253
|
): Promise<QueryOutcome> => {
|
|
214
|
-
const startedAt = Date.now();
|
|
215
254
|
const expectedSessionGeneration = sessionGeneration;
|
|
216
|
-
const expectedXaiSettingsGeneration = xaiSettingsGeneration;
|
|
217
255
|
const expectedSessionId = ctx.sessionManager.getSessionId();
|
|
218
256
|
const expectedModelIdentity = modelIdentity(ctx.model);
|
|
257
|
+
const expectedFireworksAccountId =
|
|
258
|
+
adapter.id === "fireworks" ? settingsRuntime.get().settings.fireworksAccountId : undefined;
|
|
259
|
+
const querySettings =
|
|
260
|
+
adapter.id === "fireworks" ? { fireworksAccountId: expectedFireworksAccountId } : undefined;
|
|
219
261
|
let auth: ResolvedUsageAuth | undefined;
|
|
220
262
|
try {
|
|
221
263
|
auth = await awaitWithDeadline(
|
|
222
264
|
resolveUsageAuth(ctx, adapter, undefined, credentialReader, credentialCandidates),
|
|
223
265
|
signal,
|
|
224
|
-
|
|
266
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
225
267
|
`resolving ${adapter.displayName} runtime auth`,
|
|
226
268
|
);
|
|
227
269
|
} catch (error) {
|
|
@@ -239,16 +281,14 @@ export default function usageExtension(
|
|
|
239
281
|
},
|
|
240
282
|
};
|
|
241
283
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
)
|
|
250
|
-
throw abortError();
|
|
251
|
-
}
|
|
284
|
+
const requiresRequestBoundaryGuard = ["deepseek", "fireworks", "xai"].includes(adapter.id);
|
|
285
|
+
const requestContextChanged = () =>
|
|
286
|
+
expectedSessionGeneration !== sessionGeneration ||
|
|
287
|
+
ctx.sessionManager.getSessionId() !== expectedSessionId ||
|
|
288
|
+
modelIdentity(ctx.model) !== expectedModelIdentity ||
|
|
289
|
+
(adapter.id === "fireworks" &&
|
|
290
|
+
settingsRuntime.get().settings.fireworksAccountId !== expectedFireworksAccountId);
|
|
291
|
+
if (requiresRequestBoundaryGuard && requestContextChanged()) throw abortError();
|
|
252
292
|
if (!auth) {
|
|
253
293
|
if (displayState === "current") {
|
|
254
294
|
transitionCurrentIdentity(`${adapter.id}:unavailable`, adapter.id);
|
|
@@ -264,11 +304,15 @@ export default function usageExtension(
|
|
|
264
304
|
authState: "unavailable",
|
|
265
305
|
};
|
|
266
306
|
}
|
|
307
|
+
const queryFingerprint =
|
|
308
|
+
adapter.id === "fireworks"
|
|
309
|
+
? `${auth.fingerprint}:account:${expectedFireworksAccountId ?? "auto"}`
|
|
310
|
+
: auth.fingerprint;
|
|
267
311
|
if (displayState === "current") {
|
|
268
|
-
transitionCurrentIdentity(`${adapter.id}:${
|
|
312
|
+
transitionCurrentIdentity(`${adapter.id}:${queryFingerprint}`, adapter.id);
|
|
269
313
|
}
|
|
270
314
|
|
|
271
|
-
const cached = !force ? cache.get(adapter.id,
|
|
315
|
+
const cached = !force ? cache.get(adapter.id, queryFingerprint) : undefined;
|
|
272
316
|
if (cached) {
|
|
273
317
|
return {
|
|
274
318
|
state: {
|
|
@@ -282,7 +326,7 @@ export default function usageExtension(
|
|
|
282
326
|
};
|
|
283
327
|
}
|
|
284
328
|
|
|
285
|
-
const failureKey = `${adapter.id}:${
|
|
329
|
+
const failureKey = `${adapter.id}:${queryFingerprint}`;
|
|
286
330
|
const previousFailure = failureBackoff.get(failureKey);
|
|
287
331
|
if (!force && previousFailure && previousFailure.until > Date.now()) {
|
|
288
332
|
return {
|
|
@@ -301,44 +345,39 @@ export default function usageExtension(
|
|
|
301
345
|
const queryId = querySequence;
|
|
302
346
|
setBoundedMap(latestQueries, failureKey, queryId, MAX_ACCOUNT_STATES);
|
|
303
347
|
|
|
348
|
+
let deepSeekAuthChanged = false;
|
|
304
349
|
try {
|
|
305
|
-
const remainingMs = Math.max(1,
|
|
306
|
-
const guard =
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
resolveUsageAuth(ctx, adapter, undefined, credentialReader, credentialCandidates),
|
|
321
|
-
signal,
|
|
322
|
-
Math.max(1, DEFAULT_TIMEOUT_MS - (Date.now() - startedAt)),
|
|
323
|
-
"revalidating xAI runtime auth",
|
|
324
|
-
);
|
|
325
|
-
if (
|
|
326
|
-
signal.aborted ||
|
|
327
|
-
expectedSessionGeneration !== sessionGeneration ||
|
|
328
|
-
expectedXaiSettingsGeneration !== xaiSettingsGeneration ||
|
|
329
|
-
!xaiUsageEnabled() ||
|
|
330
|
-
ctx.sessionManager.getSessionId() !== expectedSessionId ||
|
|
331
|
-
modelIdentity(ctx.model) !== expectedModelIdentity ||
|
|
332
|
-
revalidated?.fingerprint !== auth.fingerprint
|
|
333
|
-
) {
|
|
334
|
-
throw abortError();
|
|
350
|
+
const remainingMs = Math.max(1, deadlineAt - Date.now());
|
|
351
|
+
const guard = requiresRequestBoundaryGuard
|
|
352
|
+
? async () => {
|
|
353
|
+
if (signal.aborted || requestContextChanged()) throw abortError();
|
|
354
|
+
const revalidated = await awaitWithDeadline(
|
|
355
|
+
resolveUsageAuth(ctx, adapter, undefined, credentialReader, credentialCandidates),
|
|
356
|
+
signal,
|
|
357
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
358
|
+
`revalidating ${adapter.displayName} runtime auth`,
|
|
359
|
+
);
|
|
360
|
+
if (signal.aborted || requestContextChanged()) throw abortError();
|
|
361
|
+
if (revalidated?.fingerprint !== auth.fingerprint) {
|
|
362
|
+
if (adapter.id === "deepseek") {
|
|
363
|
+
deepSeekAuthChanged = true;
|
|
364
|
+
throw new Error("DeepSeek runtime credential changed during the balance query.");
|
|
335
365
|
}
|
|
366
|
+
throw abortError();
|
|
336
367
|
}
|
|
337
|
-
|
|
338
|
-
|
|
368
|
+
}
|
|
369
|
+
: undefined;
|
|
370
|
+
const report = await queryProviderUsage(
|
|
371
|
+
adapter,
|
|
372
|
+
auth,
|
|
373
|
+
signal,
|
|
374
|
+
remainingMs,
|
|
375
|
+
guard,
|
|
376
|
+
querySettings,
|
|
377
|
+
);
|
|
339
378
|
if (guard) await guard();
|
|
340
379
|
if (latestQueries.get(failureKey) === queryId) {
|
|
341
|
-
cache.set(adapter.id,
|
|
380
|
+
cache.set(adapter.id, queryFingerprint, report);
|
|
342
381
|
failureBackoff.delete(failureKey);
|
|
343
382
|
}
|
|
344
383
|
return {
|
|
@@ -353,6 +392,24 @@ export default function usageExtension(
|
|
|
353
392
|
};
|
|
354
393
|
} catch (error) {
|
|
355
394
|
if (isStaleExtensionContextError(error) || isAbortError(error)) throw error;
|
|
395
|
+
if (
|
|
396
|
+
deepSeekAuthChanged &&
|
|
397
|
+
authRetry === 0 &&
|
|
398
|
+
!signal.aborted &&
|
|
399
|
+
!requestContextChanged() &&
|
|
400
|
+
Date.now() < deadlineAt
|
|
401
|
+
) {
|
|
402
|
+
if (latestQueries.get(failureKey) === queryId) latestQueries.delete(failureKey);
|
|
403
|
+
return queryAdapterState(
|
|
404
|
+
ctx,
|
|
405
|
+
adapter,
|
|
406
|
+
displayState,
|
|
407
|
+
true,
|
|
408
|
+
signal,
|
|
409
|
+
authRetry + 1,
|
|
410
|
+
deadlineAt,
|
|
411
|
+
);
|
|
412
|
+
}
|
|
356
413
|
const message = errorMessage(error);
|
|
357
414
|
const now = Date.now();
|
|
358
415
|
for (const [key, failure] of failureBackoff) {
|
|
@@ -385,7 +442,7 @@ export default function usageExtension(
|
|
|
385
442
|
force: boolean,
|
|
386
443
|
signal: AbortSignal,
|
|
387
444
|
): Promise<QueryOutcome> => {
|
|
388
|
-
const adapter =
|
|
445
|
+
const adapter = adapterForProvider(model?.provider);
|
|
389
446
|
if (!adapter) {
|
|
390
447
|
const providerId = model?.provider ?? "none";
|
|
391
448
|
transitionCurrentIdentity(`unsupported:${providerId}`, providerId);
|
|
@@ -395,12 +452,9 @@ export default function usageExtension(
|
|
|
395
452
|
providerName: providerDisplayName(ctx, providerId),
|
|
396
453
|
displayState: "current",
|
|
397
454
|
status: "unsupported",
|
|
398
|
-
message:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
: model
|
|
402
|
-
? `Usage reporting is not supported for ${providerDisplayName(ctx, providerId)}.`
|
|
403
|
-
: "No model is selected.",
|
|
455
|
+
message: model
|
|
456
|
+
? `Usage reporting is not supported for ${providerDisplayName(ctx, providerId)}.`
|
|
457
|
+
: "No model is selected.",
|
|
404
458
|
},
|
|
405
459
|
};
|
|
406
460
|
}
|
|
@@ -412,7 +466,7 @@ export default function usageExtension(
|
|
|
412
466
|
model: PiModel | undefined,
|
|
413
467
|
force: boolean,
|
|
414
468
|
) => {
|
|
415
|
-
const adapter =
|
|
469
|
+
const adapter = adapterForProvider(model?.provider);
|
|
416
470
|
if (!adapter || !model) {
|
|
417
471
|
const providerId = model?.provider ?? "none";
|
|
418
472
|
transitionCurrentIdentity(`unsupported:${providerId}`, providerId);
|
|
@@ -425,6 +479,7 @@ export default function usageExtension(
|
|
|
425
479
|
}
|
|
426
480
|
statusGeneration += 1;
|
|
427
481
|
const generation = statusGeneration;
|
|
482
|
+
clearStatusCountdownTimer();
|
|
428
483
|
statusController?.abort();
|
|
429
484
|
const controller = new AbortController();
|
|
430
485
|
statusController = controller;
|
|
@@ -494,7 +549,7 @@ export default function usageExtension(
|
|
|
494
549
|
if (generation !== statusGeneration || modelIdentity(ctx.model) !== modelIdentity(model)) {
|
|
495
550
|
return false;
|
|
496
551
|
}
|
|
497
|
-
const adapter =
|
|
552
|
+
const adapter = adapterForProvider(model?.provider);
|
|
498
553
|
if (outcome.authState === "unavailable") {
|
|
499
554
|
if (!adapter) return false;
|
|
500
555
|
try {
|
|
@@ -569,7 +624,7 @@ export default function usageExtension(
|
|
|
569
624
|
const menuGeneration = statusGeneration;
|
|
570
625
|
statusController?.abort();
|
|
571
626
|
statusController = undefined;
|
|
572
|
-
|
|
627
|
+
clearStatusTimers();
|
|
573
628
|
const controller = new AbortController();
|
|
574
629
|
activeControllers.add(controller);
|
|
575
630
|
try {
|
|
@@ -668,7 +723,7 @@ export default function usageExtension(
|
|
|
668
723
|
providers: () => ({
|
|
669
724
|
kind: "actions",
|
|
670
725
|
title: "Select a configured provider",
|
|
671
|
-
items: configuredAdapters(ctx
|
|
726
|
+
items: configuredAdapters(ctx)
|
|
672
727
|
.filter((adapter) => adapter.id !== ctx.model?.provider)
|
|
673
728
|
.map((adapter) => ({
|
|
674
729
|
id: adapter.id,
|
|
@@ -742,14 +797,14 @@ export default function usageExtension(
|
|
|
742
797
|
settingsRuntime,
|
|
743
798
|
controller.signal,
|
|
744
799
|
() => statusGeneration === menuGeneration && !controller.signal.aborted,
|
|
745
|
-
(id
|
|
746
|
-
if (
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
800
|
+
(id) => {
|
|
801
|
+
if (
|
|
802
|
+
id === "codexStatusResetCountdown" &&
|
|
803
|
+
stableCurrent &&
|
|
804
|
+
statusGeneration === menuGeneration &&
|
|
805
|
+
!controller.signal.aborted
|
|
806
|
+
) {
|
|
807
|
+
publishStableCurrent(ctx, stableCurrent);
|
|
753
808
|
}
|
|
754
809
|
},
|
|
755
810
|
);
|
|
@@ -946,7 +1001,7 @@ export default function usageExtension(
|
|
|
946
1001
|
return { kind: "stay" };
|
|
947
1002
|
},
|
|
948
1003
|
another: async () => {
|
|
949
|
-
const others = configuredAdapters(ctx
|
|
1004
|
+
const others = configuredAdapters(ctx).filter(
|
|
950
1005
|
(adapter) => adapter.id !== ctx.model?.provider,
|
|
951
1006
|
);
|
|
952
1007
|
if (others.length === 0) {
|
|
@@ -956,7 +1011,7 @@ export default function usageExtension(
|
|
|
956
1011
|
return { kind: "to", screen: "providers" };
|
|
957
1012
|
},
|
|
958
1013
|
provider: async ({ itemId }) => {
|
|
959
|
-
const adapter = configuredAdapters(ctx
|
|
1014
|
+
const adapter = configuredAdapters(ctx).find(
|
|
960
1015
|
(candidate) => candidate.id === itemId && candidate.id !== ctx.model?.provider,
|
|
961
1016
|
);
|
|
962
1017
|
if (!adapter) return { kind: "back" };
|
|
@@ -984,7 +1039,7 @@ export default function usageExtension(
|
|
|
984
1039
|
return { kind: "back" };
|
|
985
1040
|
},
|
|
986
1041
|
all: async () => {
|
|
987
|
-
const adapters = configuredAdapters(ctx
|
|
1042
|
+
const adapters = configuredAdapters(ctx);
|
|
988
1043
|
const currentProviderId = ctx.model?.provider;
|
|
989
1044
|
const settled = await runMenuOperation(
|
|
990
1045
|
ctx,
|
|
@@ -1065,16 +1120,21 @@ export default function usageExtension(
|
|
|
1065
1120
|
}
|
|
1066
1121
|
},
|
|
1067
1122
|
});
|
|
1068
|
-
pi.on("session_start", (_event, ctx) => {
|
|
1123
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
1069
1124
|
sessionGeneration += 1;
|
|
1070
|
-
xaiSettingsGeneration += 1;
|
|
1071
1125
|
statusGeneration += 1;
|
|
1072
|
-
|
|
1126
|
+
clearStatusTimers();
|
|
1073
1127
|
for (const controller of activeControllers) controller.abort();
|
|
1074
1128
|
activeControllers.clear();
|
|
1075
1129
|
statusController = undefined;
|
|
1076
1130
|
sessionActive = true;
|
|
1077
|
-
|
|
1131
|
+
const ownerGeneration = sessionGeneration;
|
|
1132
|
+
try {
|
|
1133
|
+
await fastRuntime.prepareSession(ctx);
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
if (isStaleExtensionContextError(error) || ownerGeneration !== sessionGeneration) return;
|
|
1136
|
+
throw error;
|
|
1137
|
+
}
|
|
1078
1138
|
});
|
|
1079
1139
|
pi.on("session_tree", (_event, ctx) => {
|
|
1080
1140
|
startStatusRefresh(ctx, ctx.model, false);
|
|
@@ -1088,9 +1148,8 @@ export default function usageExtension(
|
|
|
1088
1148
|
pi.on("session_shutdown", (_event, ctx) => {
|
|
1089
1149
|
sessionActive = false;
|
|
1090
1150
|
sessionGeneration += 1;
|
|
1091
|
-
xaiSettingsGeneration += 1;
|
|
1092
1151
|
statusGeneration += 1;
|
|
1093
|
-
|
|
1152
|
+
clearStatusTimers();
|
|
1094
1153
|
for (const controller of activeControllers) controller.abort();
|
|
1095
1154
|
activeControllers.clear();
|
|
1096
1155
|
statusController = undefined;
|
|
@@ -1101,7 +1160,10 @@ export default function usageExtension(
|
|
|
1101
1160
|
safeSetStatus(ctx, undefined);
|
|
1102
1161
|
});
|
|
1103
1162
|
|
|
1104
|
-
fastRuntime = registerCodexFastMode(
|
|
1105
|
-
|
|
1163
|
+
fastRuntime = registerCodexFastMode(
|
|
1164
|
+
pi,
|
|
1165
|
+
settingsRuntime,
|
|
1166
|
+
(ctx) => startStatusRefresh(ctx, ctx.model, false),
|
|
1167
|
+
{ registerSessionStart: false },
|
|
1106
1168
|
);
|
|
1107
1169
|
}
|