@narumitw/pi-usage 0.62.0 → 0.63.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 +21 -26
- package/dist/chunks/{chunk-WEXCFYZX.ts → chunk-ENCC7IBP.ts} +6 -9
- package/dist/chunks/chunk-ENCC7IBP.ts.map +7 -0
- package/dist/chunks/{openai-companion-auth-Q456G46T.ts → openai-companion-auth-6VLPFVHF.ts} +4 -6
- package/dist/chunks/openai-companion-auth-6VLPFVHF.ts.map +7 -0
- package/dist/chunks/{openai-companion-usage-Y3WTMUB2.ts → openai-companion-usage-4NOBHGP7.ts} +2 -2
- package/dist/index.ts +117 -172
- package/dist/index.ts.map +3 -3
- package/docs/providers.md +13 -11
- package/package.json +1 -1
- package/src/format.ts +10 -4
- package/src/openai-companion-auth.ts +3 -5
- package/src/providers/openai-chatgpt.ts +2 -6
- package/src/query.ts +2 -2
- package/src/settings.ts +0 -5
- package/src/types.ts +0 -1
- package/src/usage-settings-ui.ts +116 -156
- package/src/usage.ts +1 -25
- package/dist/chunks/chunk-WEXCFYZX.ts.map +0 -7
- package/dist/chunks/openai-companion-auth-Q456G46T.ts.map +0 -7
- /package/dist/chunks/{openai-companion-usage-Y3WTMUB2.ts.map → openai-companion-usage-4NOBHGP7.ts.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/openai-companion-auth.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { fingerprintResolvedAuth } from \"./core.js\";\nimport { fallbackOAuthCredentialCandidates, type OAuthCredentialCandidateReader } from \"./oauth-credential-source.js\";\nimport { openAIAuthAccessToken } from \"./providers/openai-chatgpt.js\";\nimport { adapterForProvider, resolveUsageAuth } from \"./query.js\";\nimport type { ResolvedUsageAuth } from \"./types.js\";\n\n// A native app registration is routing metadata, not cryptographic same-account proof.\n// Keep this read-only boundary separate from legacy Codex querying and reset mutation policy.\nexport async function resolveOpenAICompanionAuth(\n ctx: ExtensionContext,\n native: ResolvedUsageAuth,\n salt: Uint8Array,\n credentialReader: (providerId: string) => unknown,\n candidateReader?: OAuthCredentialCandidateReader,\n): Promise<ResolvedUsageAuth> {\n const unavailable = () => ({\n ...native,\n fingerprint: fingerprintResolvedAuth(\n { apiKey: JSON.stringify([native.fingerprint, native.openaiClientId, null]) },\n salt,\n ),\n });\n if (candidateReader?.waitUntilReady && !(await candidateReader.waitUntilReady(ctx, \"openai-codex\"))) {\n throw new Error(\"Companion Codex OAuth credential readiness failed closed.\");\n }\n const adapter = adapterForProvider(\"openai-codex\");\n if (!adapter) throw new Error(\"Companion Codex usage support is unavailable.\");\n const companion = await resolveUsageAuth(ctx, adapter, salt, credentialReader);\n if (!companion) return unavailable();\n if (companion.source !== \"OAuth\")\n throw new Error(\"Companion usage requires /login openai-codex OAuth, not an API key.\");\n // Legacy querying is more permissive. Enforce explicit Authorization removals and duplicates\n // against preserved fresh provider auth before using its normalized request headers.\n const access = openAIAuthAccessToken(companion.auth);\n if (ctx.model?.provider === \"openai-codex\") {\n const selected = await ctx.modelRegistry.getApiKeyAndHeaders(ctx.model);\n if (\n !selected.ok ||\n (selected.baseUrl && new URL(selected.baseUrl).origin !== \"https://chatgpt.com\") ||\n openAIAuthAccessToken(selected) !== access\n ) {\n throw new Error(\"Selected Codex model authorization does not match the companion OAuth credential.\");\n }\n }\n if (!access || access !== openAIAuthAccessToken(companion)) {\n throw new Error(\"Companion Codex runtime authorization did not match its OAuth credential.\");\n }\n const accountId = codexAccountId(access);\n if (!accountId) throw new Error(\"Companion Codex token did not contain a valid account ID.\");\n const offered = candidateReader\n ? await candidateReader(ctx, \"openai-codex\")\n : fallbackOAuthCredentialCandidates(\"openai-codex\", credentialReader);\n if (!offered.ok) throw new Error(\"Companion Codex OAuth credential discovery failed closed.\");\n const matches = new Set<string>();\n for (const candidate of offered.candidates) {\n const credential = object(candidate);\n if (credential?.type !== \"oauth\" || credential.access !== access) continue;\n if (\n credential.accountId !== accountId ||\n typeof credential.refresh !== \"string\" ||\n !credential.refresh ||\n typeof credential.expires !== \"number\" ||\n !Number.isFinite(credential.expires)\n ) {\n throw new Error(\"The matching companion Codex OAuth credential was incomplete or had a different account ID.\");\n }\n matches.add(credential.refresh);\n }\n if (matches.size !== 1) throw new Error(\"Companion Codex OAuth must uniquely match the fresh runtime credential.\");\n const headers = { Authorization: `Bearer ${access}`, \"ChatGPT-Account-Id\": accountId };\n return {\n ...native,\n openaiCompanion: { headers },\n fingerprint: fingerprintResolvedAuth(\n { apiKey: JSON.stringify([native.fingerprint, native.openaiClientId, companion.fingerprint, headers]) },\n salt,\n ),\n secrets: [\n ...new Set([...native.secrets, ...companion.secrets, ...matches, access, accountId, headers.Authorization]),\n ],\n };\n}\n\nfunction codexAccountId(access: string): string | undefined {\n try {\n const parts = access.split(\".\");\n if (parts.length !== 3 || !parts[1]) return undefined;\n const payload = object(JSON.parse(Buffer.from(parts[1], \"base64url\").toString(\"utf8\")));\n const account = object(payload?.[\"https://api.openai.com/auth\"])?.chatgpt_account_id;\n return typeof account === \"string\" && account.length > 0 && account.length <= 512 && /^[\\x21-\\x7e]+$/u.test(account)\n ? account\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction object(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/chunks/{openai-companion-usage-Y3WTMUB2.ts → openai-companion-usage-4NOBHGP7.ts}
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
CHATGPT_USAGE_SETTINGS_URL,
|
|
5
5
|
fetchProviderJson
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ENCC7IBP.ts";
|
|
7
7
|
|
|
8
8
|
// src/providers/openai-companion-usage.ts
|
|
9
9
|
var USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
@@ -117,4 +117,4 @@ export {
|
|
|
117
117
|
matchingOpenAIAppBuckets,
|
|
118
118
|
queryOpenAICompanionUsage
|
|
119
119
|
};
|
|
120
|
-
//# sourceMappingURL=openai-companion-usage-
|
|
120
|
+
//# sourceMappingURL=openai-companion-usage-4NOBHGP7.ts.map
|
package/dist/index.ts
CHANGED
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
runWithConcurrency,
|
|
46
46
|
sanitizeDisplayText,
|
|
47
47
|
usageAdapters
|
|
48
|
-
} from "./chunks/chunk-
|
|
48
|
+
} from "./chunks/chunk-ENCC7IBP.ts";
|
|
49
49
|
|
|
50
50
|
// src/codex-fast.ts
|
|
51
51
|
import { calculateCost, hasApi } from "@earendil-works/pi-ai";
|
|
@@ -425,7 +425,9 @@ function formatUsageStatusline(report, model, now = Date.now(), showCodexResetCo
|
|
|
425
425
|
return `chatgpt ${["chatgpt-plan", "chatgpt-app"].map((group) => {
|
|
426
426
|
const windows = report.buckets.filter((bucket) => bucket.groupId === group).map((bucket) => {
|
|
427
427
|
const reset = formatResetCountdown(bucket.resetsAt, now);
|
|
428
|
-
|
|
428
|
+
const window = reset ? `\u21BB ${reset}` : formatWindowLabel(bucket.windowMinutes, "weekly", true);
|
|
429
|
+
if (group === "chatgpt-app") return window;
|
|
430
|
+
return `${bucket.remaining === void 0 ? "unavailable" : `${bucket.remaining.toFixed(0)}%`} ${window}`;
|
|
429
431
|
});
|
|
430
432
|
return `${group === "chatgpt-plan" ? "plan" : "app"} ${windows.join(" ")}`;
|
|
431
433
|
}).join(" \xB7 ")}`;
|
|
@@ -840,9 +842,8 @@ function formatOpenAICompanionReport(lines, report) {
|
|
|
840
842
|
for (const group of ["chatgpt-plan", "chatgpt-app"]) {
|
|
841
843
|
lines.push(group === "chatgpt-plan" ? "Plan limits:" : "App limits:");
|
|
842
844
|
for (const bucket of report.buckets.filter((bucket2) => bucket2.groupId === group)) {
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
);
|
|
845
|
+
const value = group === "chatgpt-app" ? bucket.resetsAt === void 0 ? "Reset time unavailable" : `resets ${formatReset(bucket.resetsAt)}` : formatPercentBucket(bucket);
|
|
846
|
+
lines.push(`${formatWindowLabel(bucket.windowMinutes, "weekly", false).padEnd(VALUE_COLUMN)}${value}`);
|
|
846
847
|
}
|
|
847
848
|
}
|
|
848
849
|
for (const metric of report.metrics)
|
|
@@ -1000,7 +1001,6 @@ import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
|
1000
1001
|
var USAGE_SETTINGS_FILE = "pi-usage.json";
|
|
1001
1002
|
var MAX_USAGE_SETTINGS_BYTES = 64 * 1024;
|
|
1002
1003
|
var DEFAULT_USAGE_SETTINGS = Object.freeze({
|
|
1003
|
-
openaiCompanionUsage: false,
|
|
1004
1004
|
codexFastMode: false,
|
|
1005
1005
|
codexStatusResetCountdown: true,
|
|
1006
1006
|
codexStatusPercentage: "remaining",
|
|
@@ -1011,7 +1011,6 @@ function usageSettingsPath() {
|
|
|
1011
1011
|
}
|
|
1012
1012
|
function normalizeUsageSettings(value) {
|
|
1013
1013
|
if (!isRecord2(value)) return void 0;
|
|
1014
|
-
if (Object.hasOwn(value, "openaiCompanionUsage") && typeof value.openaiCompanionUsage !== "boolean") return void 0;
|
|
1015
1014
|
if (Object.hasOwn(value, "codexFastMode") && typeof value.codexFastMode !== "boolean") {
|
|
1016
1015
|
return void 0;
|
|
1017
1016
|
}
|
|
@@ -1031,7 +1030,6 @@ function normalizeUsageSettings(value) {
|
|
|
1031
1030
|
effectiveTargets.fireworks = value.fireworksAccountId;
|
|
1032
1031
|
}
|
|
1033
1032
|
return {
|
|
1034
|
-
openaiCompanionUsage: value.openaiCompanionUsage === true,
|
|
1035
1033
|
codexFastMode: typeof value.codexFastMode === "boolean" ? value.codexFastMode : DEFAULT_USAGE_SETTINGS.codexFastMode,
|
|
1036
1034
|
codexStatusResetCountdown: typeof value.codexStatusResetCountdown === "boolean" ? value.codexStatusResetCountdown : DEFAULT_USAGE_SETTINGS.codexStatusResetCountdown,
|
|
1037
1035
|
codexStatusPercentage: value.codexStatusPercentage === "used" ? "used" : DEFAULT_USAGE_SETTINGS.codexStatusPercentage,
|
|
@@ -1451,156 +1449,121 @@ async function showUsageSettings(ctx, settingsRuntime, parentSignal, isCurrent,
|
|
|
1451
1449
|
const { HorizontalRule, renderBoundedFrame } = await import("@narumitw/pi-tui-kit");
|
|
1452
1450
|
if (parentSignal.aborted || !isCurrent()) return false;
|
|
1453
1451
|
let changed = false;
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
const
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
const cancel = () => close(changed);
|
|
1501
|
-
const queueUpdate = (id, requested, display) => {
|
|
1502
|
-
saveQueue = saveQueue.then(async () => {
|
|
1503
|
-
if (signal.aborted || !isCurrent()) return;
|
|
1504
|
-
const previous = settingsRuntime.get().settings[id];
|
|
1505
|
-
if (settingsRuntime.get().kind === "invalid") {
|
|
1506
|
-
settingsList.updateValue(id, settingValueLabel(id, previous));
|
|
1507
|
-
if (!signal.aborted && isCurrent()) {
|
|
1508
|
-
ctx.ui.notify("Repair pi-usage.json and reload before changing settings.", "error");
|
|
1509
|
-
tui.requestRender();
|
|
1510
|
-
}
|
|
1511
|
-
return;
|
|
1512
|
-
}
|
|
1513
|
-
try {
|
|
1514
|
-
if (id === "openaiCompanionUsage" && requested === true && previous !== true) {
|
|
1515
|
-
selectedId = id;
|
|
1516
|
-
close("consent");
|
|
1517
|
-
return;
|
|
1518
|
-
}
|
|
1519
|
-
const patch = {};
|
|
1520
|
-
patch[id] = requested;
|
|
1521
|
-
await settingsRuntime.update(patch, signal);
|
|
1522
|
-
} catch (error) {
|
|
1523
|
-
if (signal.aborted || !isCurrent()) return;
|
|
1524
|
-
settingsList.updateValue(id, settingValueLabel(id, previous));
|
|
1525
|
-
ctx.ui.notify(`Could not save pi-usage.json: ${errorMessage(error)}`, "error");
|
|
1452
|
+
return ctx.ui.custom((tui, theme, _keybindings, done) => {
|
|
1453
|
+
const localController = new AbortController();
|
|
1454
|
+
const signal = AbortSignal.any([parentSignal, localController.signal]);
|
|
1455
|
+
let closing = false;
|
|
1456
|
+
let saveQueue = Promise.resolve();
|
|
1457
|
+
const state = settingsRuntime.get();
|
|
1458
|
+
const items = [
|
|
1459
|
+
{
|
|
1460
|
+
id: "codexFastMode",
|
|
1461
|
+
label: "Codex Fast mode",
|
|
1462
|
+
description: "Use faster Codex routing at increased plan allowance consumption.",
|
|
1463
|
+
currentValue: state.settings.codexFastMode ? ON : OFF,
|
|
1464
|
+
values: [OFF, ON]
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
id: "codexStatusResetCountdown",
|
|
1468
|
+
label: "Codex reset countdown",
|
|
1469
|
+
description: "Show time remaining until each Codex usage limit resets.",
|
|
1470
|
+
currentValue: state.settings.codexStatusResetCountdown ? ON : OFF,
|
|
1471
|
+
values: [OFF, ON]
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
id: "codexStatusPercentage",
|
|
1475
|
+
label: "Codex percentage",
|
|
1476
|
+
description: "Show remaining or used Codex quota in the statusline.",
|
|
1477
|
+
currentValue: settingValueLabel("codexStatusPercentage", state.settings.codexStatusPercentage),
|
|
1478
|
+
values: [REMAINING, USED]
|
|
1479
|
+
}
|
|
1480
|
+
];
|
|
1481
|
+
const rule = new HorizontalRule({ ruleStyle: (text) => theme.fg("border", text) });
|
|
1482
|
+
let settingsList;
|
|
1483
|
+
const close = (result) => {
|
|
1484
|
+
if (closing) return;
|
|
1485
|
+
closing = true;
|
|
1486
|
+
localController.abort();
|
|
1487
|
+
done(result);
|
|
1488
|
+
};
|
|
1489
|
+
const cancel = () => close(changed);
|
|
1490
|
+
const queueUpdate = (id, requested, display) => {
|
|
1491
|
+
saveQueue = saveQueue.then(async () => {
|
|
1492
|
+
if (signal.aborted || !isCurrent()) return;
|
|
1493
|
+
const previous = settingsRuntime.get().settings[id];
|
|
1494
|
+
if (settingsRuntime.get().kind === "invalid") {
|
|
1495
|
+
settingsList.updateValue(id, settingValueLabel(id, previous));
|
|
1496
|
+
if (!signal.aborted && isCurrent()) {
|
|
1497
|
+
ctx.ui.notify("Repair pi-usage.json and reload before changing settings.", "error");
|
|
1526
1498
|
tui.requestRender();
|
|
1527
|
-
return;
|
|
1528
|
-
}
|
|
1529
|
-
if (previous !== requested) {
|
|
1530
|
-
changed = true;
|
|
1531
|
-
onApplied(id);
|
|
1532
1499
|
}
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
try {
|
|
1503
|
+
const patch = {};
|
|
1504
|
+
patch[id] = requested;
|
|
1505
|
+
await settingsRuntime.update(patch, signal);
|
|
1506
|
+
} catch (error) {
|
|
1533
1507
|
if (signal.aborted || !isCurrent()) return;
|
|
1534
|
-
settingsList.updateValue(id,
|
|
1535
|
-
|
|
1536
|
-
});
|
|
1537
|
-
};
|
|
1538
|
-
settingsList = new SettingsList(
|
|
1539
|
-
items,
|
|
1540
|
-
items.length + 2,
|
|
1541
|
-
getSettingsListTheme(),
|
|
1542
|
-
(id, value) => {
|
|
1543
|
-
if (closing || signal.aborted || !isCurrent()) return;
|
|
1544
|
-
selectedId = id;
|
|
1545
|
-
if (id === "codexStatusPercentage") {
|
|
1546
|
-
queueUpdate(id, value === USED ? "used" : "remaining", value);
|
|
1547
|
-
} else if (id === "codexFastMode" || id === "codexStatusResetCountdown" || id === "openaiCompanionUsage") {
|
|
1548
|
-
queueUpdate(id, value === ON, value);
|
|
1549
|
-
}
|
|
1550
|
-
},
|
|
1551
|
-
cancel
|
|
1552
|
-
);
|
|
1553
|
-
if (selectedId) settingsList.selectItem(selectedId);
|
|
1554
|
-
parentSignal.addEventListener("abort", cancel, { once: true });
|
|
1555
|
-
return {
|
|
1556
|
-
render(width) {
|
|
1557
|
-
const title = new Text(theme.fg("accent", theme.bold("pi-usage Settings")), 1, 0).render(width);
|
|
1558
|
-
const content = settingsList.render(width);
|
|
1559
|
-
const focusedRow = content.findIndex((line) => /^[→›]\s/u.test(stripVTControlCharacters(line)));
|
|
1560
|
-
const terminalRows = Number.isFinite(tui.terminal?.rows) ? Math.floor(tui.terminal.rows) : 24;
|
|
1561
|
-
const [ruleLine = ""] = rule.render(width);
|
|
1562
|
-
return renderBoundedFrame({
|
|
1563
|
-
width,
|
|
1564
|
-
maxRows: Math.max(1, terminalRows - 3),
|
|
1565
|
-
rule: ruleLine,
|
|
1566
|
-
title,
|
|
1567
|
-
content,
|
|
1568
|
-
priorityRows: focusedRow < 0 ? [] : [focusedRow],
|
|
1569
|
-
focusedRow
|
|
1570
|
-
});
|
|
1571
|
-
},
|
|
1572
|
-
invalidate: () => settingsList.invalidate(),
|
|
1573
|
-
handleInput(data) {
|
|
1574
|
-
if (closing) return;
|
|
1575
|
-
if (matchesKey(data, Key.ctrl("c"))) cancel();
|
|
1576
|
-
else settingsList.handleInput(data);
|
|
1508
|
+
settingsList.updateValue(id, settingValueLabel(id, previous));
|
|
1509
|
+
ctx.ui.notify(`Could not save pi-usage.json: ${errorMessage(error)}`, "error");
|
|
1577
1510
|
tui.requestRender();
|
|
1578
|
-
|
|
1579
|
-
dispose() {
|
|
1580
|
-
localController.abort();
|
|
1581
|
-
parentSignal.removeEventListener("abort", cancel);
|
|
1511
|
+
return;
|
|
1582
1512
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1513
|
+
if (previous !== requested) {
|
|
1514
|
+
changed = true;
|
|
1515
|
+
onApplied(id);
|
|
1516
|
+
}
|
|
1517
|
+
if (signal.aborted || !isCurrent()) return;
|
|
1518
|
+
settingsList.updateValue(id, display);
|
|
1519
|
+
tui.requestRender();
|
|
1520
|
+
});
|
|
1521
|
+
};
|
|
1522
|
+
settingsList = new SettingsList(
|
|
1523
|
+
items,
|
|
1524
|
+
items.length + 2,
|
|
1525
|
+
getSettingsListTheme(),
|
|
1526
|
+
(id, value) => {
|
|
1527
|
+
if (closing || signal.aborted || !isCurrent()) return;
|
|
1528
|
+
if (id === "codexStatusPercentage") {
|
|
1529
|
+
queueUpdate(id, value === USED ? "used" : "remaining", value);
|
|
1530
|
+
} else if (id === "codexFastMode" || id === "codexStatusResetCountdown") {
|
|
1531
|
+
queueUpdate(id, value === ON, value);
|
|
1532
|
+
}
|
|
1533
|
+
},
|
|
1534
|
+
cancel
|
|
1535
|
+
);
|
|
1536
|
+
parentSignal.addEventListener("abort", cancel, { once: true });
|
|
1537
|
+
return {
|
|
1538
|
+
render(width) {
|
|
1539
|
+
const title = new Text(theme.fg("accent", theme.bold("pi-usage Settings")), 1, 0).render(width);
|
|
1540
|
+
const content = settingsList.render(width);
|
|
1541
|
+
const focusedRow = content.findIndex((line) => /^[→›]\s/u.test(stripVTControlCharacters(line)));
|
|
1542
|
+
const terminalRows = Number.isFinite(tui.terminal?.rows) ? Math.floor(tui.terminal.rows) : 24;
|
|
1543
|
+
const [ruleLine = ""] = rule.render(width);
|
|
1544
|
+
return renderBoundedFrame({
|
|
1545
|
+
width,
|
|
1546
|
+
maxRows: Math.max(1, terminalRows - 3),
|
|
1547
|
+
rule: ruleLine,
|
|
1548
|
+
title,
|
|
1549
|
+
content,
|
|
1550
|
+
priorityRows: focusedRow < 0 ? [] : [focusedRow],
|
|
1551
|
+
focusedRow
|
|
1552
|
+
});
|
|
1553
|
+
},
|
|
1554
|
+
invalidate: () => settingsList.invalidate(),
|
|
1555
|
+
handleInput(data) {
|
|
1556
|
+
if (closing) return;
|
|
1557
|
+
if (matchesKey(data, Key.ctrl("c"))) cancel();
|
|
1558
|
+
else settingsList.handleInput(data);
|
|
1559
|
+
tui.requestRender();
|
|
1560
|
+
},
|
|
1561
|
+
dispose() {
|
|
1562
|
+
localController.abort();
|
|
1563
|
+
parentSignal.removeEventListener("abort", cancel);
|
|
1597
1564
|
}
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
ctx.ui.notify(`Could not enable ChatGPT companion usage: ${errorMessage(error)}`, "error");
|
|
1601
|
-
}
|
|
1602
|
-
if (parentSignal.aborted || !isCurrent()) return changed;
|
|
1603
|
-
}
|
|
1565
|
+
};
|
|
1566
|
+
});
|
|
1604
1567
|
}
|
|
1605
1568
|
|
|
1606
1569
|
// src/usage.ts
|
|
@@ -1625,14 +1588,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
1625
1588
|
const credentialCandidates = createOAuthCredentialCandidateReader(pi, credentialReader);
|
|
1626
1589
|
const createRedemptionId = dependencies.createRedemptionId ?? randomUUID2;
|
|
1627
1590
|
const settingsRuntime = dependencies.settingsRuntime ?? createUsageSettingsRuntime();
|
|
1628
|
-
const resolveUsageAuth2 =
|
|
1629
|
-
ctx,
|
|
1630
|
-
adapter,
|
|
1631
|
-
salt,
|
|
1632
|
-
reader,
|
|
1633
|
-
candidates,
|
|
1634
|
-
settingsRuntime.get().settings.openaiCompanionUsage
|
|
1635
|
-
);
|
|
1591
|
+
const resolveUsageAuth2 = resolveUsageAuth;
|
|
1636
1592
|
const cache = new UsageCache(CACHE_TTL_MS);
|
|
1637
1593
|
const failureBackoff = /* @__PURE__ */ new Map();
|
|
1638
1594
|
const latestQueries = /* @__PURE__ */ new Map();
|
|
@@ -1754,7 +1710,6 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
1754
1710
|
const expectedSessionId = ctx.sessionManager.getSessionId();
|
|
1755
1711
|
const expectedModelIdentity = modelIdentity(ctx.model);
|
|
1756
1712
|
const expectedTargetId = adapter.targets ? settingsRuntime.get().settings.selectedTargets[adapter.id] : void 0;
|
|
1757
|
-
const expectedCompanionUsage = settingsRuntime.get().settings.openaiCompanionUsage;
|
|
1758
1713
|
const providerName = providerDisplayName(ctx, adapter.id);
|
|
1759
1714
|
let auth;
|
|
1760
1715
|
try {
|
|
@@ -1795,7 +1750,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
1795
1750
|
"zai",
|
|
1796
1751
|
"zai-coding-cn"
|
|
1797
1752
|
].includes(adapter.id);
|
|
1798
|
-
const requestContextChanged = () => expectedSessionGeneration !== sessionGeneration || ctx.sessionManager.getSessionId() !== expectedSessionId || modelIdentity(ctx.model) !== expectedModelIdentity || adapter.
|
|
1753
|
+
const requestContextChanged = () => expectedSessionGeneration !== sessionGeneration || ctx.sessionManager.getSessionId() !== expectedSessionId || modelIdentity(ctx.model) !== expectedModelIdentity || adapter.targets !== void 0 && settingsRuntime.get().settings.selectedTargets[adapter.id] !== expectedTargetId;
|
|
1799
1754
|
if (requiresRequestBoundaryGuard && requestContextChanged()) throw abortError();
|
|
1800
1755
|
if (!auth) {
|
|
1801
1756
|
if (adapter.id === "openai") invalidateProviderState(adapter.id);
|
|
@@ -2444,16 +2399,6 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
2444
2399
|
controller.signal,
|
|
2445
2400
|
() => statusGeneration === menuGeneration && !controller.signal.aborted,
|
|
2446
2401
|
(id) => {
|
|
2447
|
-
if (id === "openaiCompanionUsage" && statusGeneration === menuGeneration && !controller.signal.aborted) {
|
|
2448
|
-
for (const active of nativeQueryControllers) active.abort();
|
|
2449
|
-
invalidateProviderState("openai");
|
|
2450
|
-
if (ctx.model?.provider === "openai") {
|
|
2451
|
-
statusController?.abort();
|
|
2452
|
-
statusController = void 0;
|
|
2453
|
-
clearStatusTimers();
|
|
2454
|
-
safeSetStatus(ctx, void 0);
|
|
2455
|
-
}
|
|
2456
|
-
}
|
|
2457
2402
|
if ((id === "codexStatusResetCountdown" || id === "codexStatusPercentage") && stableCurrent && statusGeneration === menuGeneration && !controller.signal.aborted) {
|
|
2458
2403
|
publishStableCurrent(ctx, stableCurrent);
|
|
2459
2404
|
}
|