@eiei114/pi-sub-bar 1.5.1
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/CHANGELOG.md +201 -0
- package/README.md +200 -0
- package/index.ts +1103 -0
- package/package.json +39 -0
- package/src/core-settings.ts +25 -0
- package/src/dividers.ts +48 -0
- package/src/errors.ts +71 -0
- package/src/formatting.ts +937 -0
- package/src/paths.ts +21 -0
- package/src/providers/extras.ts +21 -0
- package/src/providers/metadata.ts +199 -0
- package/src/providers/settings.ts +359 -0
- package/src/providers/windows.ts +23 -0
- package/src/settings/display.ts +786 -0
- package/src/settings/menu.ts +183 -0
- package/src/settings/themes.ts +378 -0
- package/src/settings/ui.ts +1388 -0
- package/src/settings-types.ts +651 -0
- package/src/settings-ui.ts +5 -0
- package/src/settings.ts +176 -0
- package/src/share.ts +75 -0
- package/src/status.ts +103 -0
- package/src/storage.ts +61 -0
- package/src/types.ts +25 -0
- package/src/ui/keybindings.ts +92 -0
- package/src/ui/settings-list.ts +304 -0
- package/src/usage/types.ts +5 -0
- package/src/utils.ts +42 -0
- package/test/all.test.ts +6 -0
- package/test/dividers.test.ts +34 -0
- package/test/formatting.test.ts +437 -0
- package/test/keybindings.test.ts +59 -0
- package/test/providers.test.ts +42 -0
- package/test/settings.test.ts +336 -0
- package/test/status.test.ts +27 -0
- package/tsconfig.json +5 -0
package/src/paths.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared path helpers for sub-bar settings storage.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const SETTINGS_FILE_NAME = "pi-sub-bar-settings.json";
|
|
10
|
+
|
|
11
|
+
export function getExtensionDir(): string {
|
|
12
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getSettingsPath(): string {
|
|
16
|
+
return join(getAgentDir(), SETTINGS_FILE_NAME);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getLegacySettingsPath(): string {
|
|
20
|
+
return join(getExtensionDir(), "settings.json");
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-specific extra usage lines (non-window info).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { UsageSnapshot } from "../types.js";
|
|
6
|
+
import type { Settings } from "../settings-types.js";
|
|
7
|
+
import { PROVIDER_METADATA, type UsageExtra } from "./metadata.js";
|
|
8
|
+
|
|
9
|
+
export type { UsageExtra } from "./metadata.js";
|
|
10
|
+
|
|
11
|
+
export function getUsageExtras(
|
|
12
|
+
usage: UsageSnapshot,
|
|
13
|
+
settings?: Settings,
|
|
14
|
+
modelId?: string
|
|
15
|
+
): UsageExtra[] {
|
|
16
|
+
const handler = PROVIDER_METADATA[usage.provider]?.getExtras;
|
|
17
|
+
if (handler) {
|
|
18
|
+
return handler(usage, settings, modelId);
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider metadata shared across the extension.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { RateWindow, UsageSnapshot, ProviderName, ModelInfo } from "../types.js";
|
|
6
|
+
import type { Settings } from "../settings-types.js";
|
|
7
|
+
import { getModelMultiplier, normalizeTokens } from "../utils.js";
|
|
8
|
+
import { PROVIDER_METADATA as BASE_METADATA, type ProviderMetadata as BaseProviderMetadata } from "@eiei114/pi-sub-shared";
|
|
9
|
+
|
|
10
|
+
export { PROVIDERS, PROVIDER_DISPLAY_NAMES } from "@eiei114/pi-sub-shared";
|
|
11
|
+
export type { ProviderStatusConfig, ProviderDetectionConfig } from "@eiei114/pi-sub-shared";
|
|
12
|
+
|
|
13
|
+
export interface UsageExtra {
|
|
14
|
+
label: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ProviderMetadata extends BaseProviderMetadata {
|
|
18
|
+
isWindowVisible?: (usage: UsageSnapshot, window: RateWindow, settings?: Settings, model?: ModelInfo) => boolean;
|
|
19
|
+
getExtras?: (usage: UsageSnapshot, settings?: Settings, modelId?: string) => UsageExtra[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const anthropicWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, _model) => {
|
|
23
|
+
if (!settings) return true;
|
|
24
|
+
const ps = settings.providers.anthropic;
|
|
25
|
+
if (window.label === "5h") return ps.windows.show5h;
|
|
26
|
+
if (window.label === "Week") return ps.windows.show7d;
|
|
27
|
+
if (window.label.startsWith("Extra [")) return ps.windows.showExtra;
|
|
28
|
+
return true;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const copilotWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, _model) => {
|
|
32
|
+
if (!settings) return true;
|
|
33
|
+
const ps = settings.providers.copilot;
|
|
34
|
+
if (window.label === "Month") return ps.windows.showMonth;
|
|
35
|
+
return true;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const geminiWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, _model) => {
|
|
39
|
+
if (!settings) return true;
|
|
40
|
+
const ps = settings.providers.gemini;
|
|
41
|
+
if (window.label === "Pro") return ps.windows.showPro;
|
|
42
|
+
if (window.label === "Flash") return ps.windows.showFlash;
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const antigravityWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, model) => {
|
|
47
|
+
if (!settings) return true;
|
|
48
|
+
const ps = settings.providers.antigravity;
|
|
49
|
+
const label = window.label.trim();
|
|
50
|
+
const normalized = label.toLowerCase().replace(/\s+/g, "_");
|
|
51
|
+
if (normalized === "tab_flash_lite_preview") return false;
|
|
52
|
+
|
|
53
|
+
const labelTokens = normalizeTokens(label);
|
|
54
|
+
|
|
55
|
+
const modelProvider = model?.provider?.toLowerCase() ?? "";
|
|
56
|
+
const modelId = model?.id;
|
|
57
|
+
const providerMatches = modelProvider.includes("antigravity");
|
|
58
|
+
if (ps.showCurrentModel && providerMatches && modelId) {
|
|
59
|
+
const modelTokens = normalizeTokens(modelId);
|
|
60
|
+
const match = modelTokens.length > 0 && modelTokens.every((token) => labelTokens.includes(token));
|
|
61
|
+
if (match) return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (ps.showScopedModels) {
|
|
65
|
+
const scopedPatterns = model?.scopedModelPatterns ?? [];
|
|
66
|
+
const matchesScoped = scopedPatterns.some((pattern) => {
|
|
67
|
+
if (!pattern) return false;
|
|
68
|
+
const [rawPattern] = pattern.split(":");
|
|
69
|
+
const trimmed = rawPattern?.trim();
|
|
70
|
+
if (!trimmed) return false;
|
|
71
|
+
const hasProvider = trimmed.includes("/");
|
|
72
|
+
if (!hasProvider) return false;
|
|
73
|
+
const providerPart = trimmed.slice(0, trimmed.indexOf("/")).trim().toLowerCase();
|
|
74
|
+
if (!providerPart.includes("antigravity")) return false;
|
|
75
|
+
const base = trimmed.slice(trimmed.lastIndexOf("/") + 1);
|
|
76
|
+
const tokens = normalizeTokens(base);
|
|
77
|
+
return tokens.length > 0 && tokens.every((token) => labelTokens.includes(token));
|
|
78
|
+
});
|
|
79
|
+
if (matchesScoped) return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const visibility = ps.modelVisibility?.[label];
|
|
83
|
+
return visibility === true;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const codexWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, model) => {
|
|
87
|
+
if (!settings) return true;
|
|
88
|
+
const ps = settings.providers.codex;
|
|
89
|
+
const isSparkModel = isCodexSparkModel(model);
|
|
90
|
+
const isSparkWindow = isCodexSparkWindow(window);
|
|
91
|
+
if (isSparkWindow) {
|
|
92
|
+
if (!isSparkModel) return false;
|
|
93
|
+
return shouldShowCodexWindowBySetting(ps, window);
|
|
94
|
+
}
|
|
95
|
+
if (isSparkModel) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return shouldShowCodexWindowBySetting(ps, window);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const isCodexSparkModel = (model?: ModelInfo): boolean => {
|
|
102
|
+
const tokens = normalizeTokens(model?.id ?? "");
|
|
103
|
+
return tokens.includes("codex") && tokens.includes("spark");
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const isCodexSparkWindow = (window: RateWindow): boolean => {
|
|
107
|
+
const tokens = normalizeTokens(window.label ?? "");
|
|
108
|
+
return tokens.includes("codex") && tokens.includes("spark");
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const shouldShowCodexWindowBySetting = (
|
|
112
|
+
ps: Settings["providers"]["codex"],
|
|
113
|
+
window: RateWindow
|
|
114
|
+
): boolean => {
|
|
115
|
+
if (window.label === "") return true;
|
|
116
|
+
if (/\b\d+h$/.test(window.label.trim())) {
|
|
117
|
+
return ps.windows.showPrimary;
|
|
118
|
+
}
|
|
119
|
+
if (window.label === "Day" || window.label === "Week" || /\b(day|week)\b/.test(window.label.toLowerCase())) {
|
|
120
|
+
return ps.windows.showSecondary;
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const kiroWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, _model) => {
|
|
126
|
+
if (!settings) return true;
|
|
127
|
+
const ps = settings.providers.kiro;
|
|
128
|
+
if (window.label === "Credits") return ps.windows.showCredits;
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const zaiWindowVisible: ProviderMetadata["isWindowVisible"] = (_usage, window, settings, _model) => {
|
|
133
|
+
if (!settings) return true;
|
|
134
|
+
const ps = settings.providers.zai;
|
|
135
|
+
if (window.label === "Tokens") return ps.windows.showTokens;
|
|
136
|
+
if (window.label === "Monthly") return ps.windows.showMonthly;
|
|
137
|
+
return true;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const anthropicExtras: ProviderMetadata["getExtras"] = (usage, settings) => {
|
|
141
|
+
const extras: UsageExtra[] = [];
|
|
142
|
+
const showExtraWindow = settings?.providers.anthropic.windows.showExtra ?? true;
|
|
143
|
+
if (showExtraWindow && usage.extraUsageEnabled === false) {
|
|
144
|
+
extras.push({ label: "Extra [off]" });
|
|
145
|
+
}
|
|
146
|
+
return extras;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const copilotExtras: ProviderMetadata["getExtras"] = (usage, settings, modelId) => {
|
|
150
|
+
const extras: UsageExtra[] = [];
|
|
151
|
+
const showMultiplier = settings?.providers.copilot.showMultiplier ?? true;
|
|
152
|
+
const showRequestsLeft = settings?.providers.copilot.showRequestsLeft ?? true;
|
|
153
|
+
if (!showMultiplier) return extras;
|
|
154
|
+
|
|
155
|
+
const multiplier = getModelMultiplier(modelId);
|
|
156
|
+
const remaining = usage.requestsRemaining;
|
|
157
|
+
if (multiplier !== undefined) {
|
|
158
|
+
let multiplierStr = `Model multiplier: ${multiplier}x`;
|
|
159
|
+
if (showRequestsLeft && remaining !== undefined) {
|
|
160
|
+
const leftCount = Math.floor(remaining / Math.max(multiplier, 0.0001));
|
|
161
|
+
multiplierStr += ` (${leftCount} req. left)`;
|
|
162
|
+
}
|
|
163
|
+
extras.push({ label: multiplierStr });
|
|
164
|
+
}
|
|
165
|
+
return extras;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export const PROVIDER_METADATA: Record<ProviderName, ProviderMetadata> = {
|
|
169
|
+
anthropic: {
|
|
170
|
+
...BASE_METADATA.anthropic,
|
|
171
|
+
isWindowVisible: anthropicWindowVisible,
|
|
172
|
+
getExtras: anthropicExtras,
|
|
173
|
+
},
|
|
174
|
+
copilot: {
|
|
175
|
+
...BASE_METADATA.copilot,
|
|
176
|
+
isWindowVisible: copilotWindowVisible,
|
|
177
|
+
getExtras: copilotExtras,
|
|
178
|
+
},
|
|
179
|
+
gemini: {
|
|
180
|
+
...BASE_METADATA.gemini,
|
|
181
|
+
isWindowVisible: geminiWindowVisible,
|
|
182
|
+
},
|
|
183
|
+
antigravity: {
|
|
184
|
+
...BASE_METADATA.antigravity,
|
|
185
|
+
isWindowVisible: antigravityWindowVisible,
|
|
186
|
+
},
|
|
187
|
+
codex: {
|
|
188
|
+
...BASE_METADATA.codex,
|
|
189
|
+
isWindowVisible: codexWindowVisible,
|
|
190
|
+
},
|
|
191
|
+
kiro: {
|
|
192
|
+
...BASE_METADATA.kiro,
|
|
193
|
+
isWindowVisible: kiroWindowVisible,
|
|
194
|
+
},
|
|
195
|
+
zai: {
|
|
196
|
+
...BASE_METADATA.zai,
|
|
197
|
+
isWindowVisible: zaiWindowVisible,
|
|
198
|
+
},
|
|
199
|
+
};
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-specific settings helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SettingItem } from "@mariozechner/pi-tui";
|
|
6
|
+
import type { ProviderName } from "../types.js";
|
|
7
|
+
import type {
|
|
8
|
+
Settings,
|
|
9
|
+
BaseProviderSettings,
|
|
10
|
+
AnthropicProviderSettings,
|
|
11
|
+
CopilotProviderSettings,
|
|
12
|
+
GeminiProviderSettings,
|
|
13
|
+
AntigravityProviderSettings,
|
|
14
|
+
CodexProviderSettings,
|
|
15
|
+
KiroProviderSettings,
|
|
16
|
+
ZaiProviderSettings,
|
|
17
|
+
} from "../settings-types.js";
|
|
18
|
+
|
|
19
|
+
function buildBaseProviderItems(ps: BaseProviderSettings): SettingItem[] {
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
id: "showStatus",
|
|
23
|
+
label: "Show Status Indicator",
|
|
24
|
+
currentValue: ps.showStatus ? "on" : "off",
|
|
25
|
+
values: ["on", "off"],
|
|
26
|
+
description: "Show status indicator for this provider.",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function applyBaseProviderSetting(ps: BaseProviderSettings, id: string, value: string): boolean {
|
|
32
|
+
switch (id) {
|
|
33
|
+
case "showStatus":
|
|
34
|
+
ps.showStatus = value === "on";
|
|
35
|
+
return true;
|
|
36
|
+
default:
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build settings items for a specific provider.
|
|
43
|
+
*/
|
|
44
|
+
export function buildProviderSettingsItems(settings: Settings, provider: ProviderName): SettingItem[] {
|
|
45
|
+
const ps = settings.providers[provider];
|
|
46
|
+
const items: SettingItem[] = [...buildBaseProviderItems(ps)];
|
|
47
|
+
|
|
48
|
+
if (provider === "anthropic") {
|
|
49
|
+
const anthroSettings = ps as AnthropicProviderSettings;
|
|
50
|
+
items.push(
|
|
51
|
+
{
|
|
52
|
+
id: "show5h",
|
|
53
|
+
label: "Show 5h Window",
|
|
54
|
+
currentValue: anthroSettings.windows.show5h ? "on" : "off",
|
|
55
|
+
values: ["on", "off"],
|
|
56
|
+
description: "Show the 5-hour usage window.",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "show7d",
|
|
60
|
+
label: "Show Week Window",
|
|
61
|
+
currentValue: anthroSettings.windows.show7d ? "on" : "off",
|
|
62
|
+
values: ["on", "off"],
|
|
63
|
+
description: "Show the weekly usage window.",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "showExtra",
|
|
67
|
+
label: "Show Extra Window",
|
|
68
|
+
currentValue: anthroSettings.windows.showExtra ? "on" : "off",
|
|
69
|
+
values: ["on", "off"],
|
|
70
|
+
description: "Show the extra usage window.",
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (provider === "copilot") {
|
|
76
|
+
const copilotSettings = ps as CopilotProviderSettings;
|
|
77
|
+
items.push(
|
|
78
|
+
{
|
|
79
|
+
id: "showMultiplier",
|
|
80
|
+
label: "Show Model Multiplier",
|
|
81
|
+
currentValue: copilotSettings.showMultiplier ? "on" : "off",
|
|
82
|
+
values: ["on", "off"],
|
|
83
|
+
description: "Show request cost multiplier for the current model.",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "showRequestsLeft",
|
|
87
|
+
label: "Show Requests Remaining",
|
|
88
|
+
currentValue: copilotSettings.showRequestsLeft ? "on" : "off",
|
|
89
|
+
values: ["on", "off"],
|
|
90
|
+
description: "Estimate requests remaining based on the multiplier.",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "quotaDisplay",
|
|
94
|
+
label: "Show Quota in",
|
|
95
|
+
currentValue: copilotSettings.quotaDisplay,
|
|
96
|
+
values: ["percentage", "requests"],
|
|
97
|
+
description: "Display Copilot usage as percentage or requests.",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "showMonth",
|
|
101
|
+
label: "Show Month Window",
|
|
102
|
+
currentValue: copilotSettings.windows.showMonth ? "on" : "off",
|
|
103
|
+
values: ["on", "off"],
|
|
104
|
+
description: "Show the monthly usage window.",
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (provider === "gemini") {
|
|
110
|
+
const geminiSettings = ps as GeminiProviderSettings;
|
|
111
|
+
items.push(
|
|
112
|
+
{
|
|
113
|
+
id: "showPro",
|
|
114
|
+
label: "Show Pro Window",
|
|
115
|
+
currentValue: geminiSettings.windows.showPro ? "on" : "off",
|
|
116
|
+
values: ["on", "off"],
|
|
117
|
+
description: "Show the Pro quota window.",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "showFlash",
|
|
121
|
+
label: "Show Flash Window",
|
|
122
|
+
currentValue: geminiSettings.windows.showFlash ? "on" : "off",
|
|
123
|
+
values: ["on", "off"],
|
|
124
|
+
description: "Show the Flash quota window.",
|
|
125
|
+
},
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (provider === "antigravity") {
|
|
130
|
+
const antigravitySettings = ps as AntigravityProviderSettings;
|
|
131
|
+
items.push(
|
|
132
|
+
{
|
|
133
|
+
id: "showCurrentModel",
|
|
134
|
+
label: "Always Show Current Model",
|
|
135
|
+
currentValue: antigravitySettings.showCurrentModel ? "on" : "off",
|
|
136
|
+
values: ["on", "off"],
|
|
137
|
+
description: "Show the active Antigravity model even if hidden.",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: "showScopedModels",
|
|
141
|
+
label: "Show Scoped Models",
|
|
142
|
+
currentValue: antigravitySettings.showScopedModels ? "on" : "off",
|
|
143
|
+
values: ["on", "off"],
|
|
144
|
+
description: "Show Antigravity models that are in the scoped model rotation.",
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const modelVisibility = antigravitySettings.modelVisibility ?? {};
|
|
149
|
+
const modelOrder = antigravitySettings.modelOrder?.length
|
|
150
|
+
? antigravitySettings.modelOrder
|
|
151
|
+
: Object.keys(modelVisibility).sort((a, b) => a.localeCompare(b));
|
|
152
|
+
const seenModels = new Set<string>();
|
|
153
|
+
|
|
154
|
+
for (const model of modelOrder) {
|
|
155
|
+
if (!model || seenModels.has(model)) continue;
|
|
156
|
+
seenModels.add(model);
|
|
157
|
+
const normalized = model.toLowerCase().replace(/\s+/g, "_");
|
|
158
|
+
if (normalized === "tab_flash_lite_preview") continue;
|
|
159
|
+
const visible = modelVisibility[model] !== false;
|
|
160
|
+
items.push({
|
|
161
|
+
id: `model:${model}`,
|
|
162
|
+
label: model,
|
|
163
|
+
currentValue: visible ? "on" : "off",
|
|
164
|
+
values: ["on", "off"],
|
|
165
|
+
description: "Toggle this model window.",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (provider === "codex") {
|
|
171
|
+
const codexSettings = ps as CodexProviderSettings;
|
|
172
|
+
items.push(
|
|
173
|
+
{
|
|
174
|
+
id: "invertUsage",
|
|
175
|
+
label: "Invert Usage",
|
|
176
|
+
currentValue: codexSettings.invertUsage ? "on" : "off",
|
|
177
|
+
values: ["on", "off"],
|
|
178
|
+
description: "Show remaining-style usage for Codex.",
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: "showPrimary",
|
|
182
|
+
label: "Show Primary Window",
|
|
183
|
+
currentValue: codexSettings.windows.showPrimary ? "on" : "off",
|
|
184
|
+
values: ["on", "off"],
|
|
185
|
+
description: "Show the primary usage window.",
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: "showSecondary",
|
|
189
|
+
label: "Show Secondary Window",
|
|
190
|
+
currentValue: codexSettings.windows.showSecondary ? "on" : "off",
|
|
191
|
+
values: ["on", "off"],
|
|
192
|
+
description: "Show secondary windows (day/week).",
|
|
193
|
+
},
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (provider === "kiro") {
|
|
198
|
+
const kiroSettings = ps as KiroProviderSettings;
|
|
199
|
+
items.push({
|
|
200
|
+
id: "showCredits",
|
|
201
|
+
label: "Show Credits Window",
|
|
202
|
+
currentValue: kiroSettings.windows.showCredits ? "on" : "off",
|
|
203
|
+
values: ["on", "off"],
|
|
204
|
+
description: "Show the credits usage window.",
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (provider === "zai") {
|
|
209
|
+
const zaiSettings = ps as ZaiProviderSettings;
|
|
210
|
+
items.push(
|
|
211
|
+
{
|
|
212
|
+
id: "showTokens",
|
|
213
|
+
label: "Show Tokens Window",
|
|
214
|
+
currentValue: zaiSettings.windows.showTokens ? "on" : "off",
|
|
215
|
+
values: ["on", "off"],
|
|
216
|
+
description: "Show the tokens usage window.",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
id: "showMonthly",
|
|
220
|
+
label: "Show Monthly Window",
|
|
221
|
+
currentValue: zaiSettings.windows.showMonthly ? "on" : "off",
|
|
222
|
+
values: ["on", "off"],
|
|
223
|
+
description: "Show the monthly usage window.",
|
|
224
|
+
},
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return items;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Apply a provider settings change in-place.
|
|
233
|
+
*/
|
|
234
|
+
export function applyProviderSettingsChange(
|
|
235
|
+
settings: Settings,
|
|
236
|
+
provider: ProviderName,
|
|
237
|
+
id: string,
|
|
238
|
+
value: string
|
|
239
|
+
): Settings {
|
|
240
|
+
const ps = settings.providers[provider];
|
|
241
|
+
if (applyBaseProviderSetting(ps, id, value)) {
|
|
242
|
+
return settings;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (provider === "anthropic") {
|
|
246
|
+
const anthroSettings = ps as AnthropicProviderSettings;
|
|
247
|
+
switch (id) {
|
|
248
|
+
case "show5h":
|
|
249
|
+
anthroSettings.windows.show5h = value === "on";
|
|
250
|
+
break;
|
|
251
|
+
case "show7d":
|
|
252
|
+
anthroSettings.windows.show7d = value === "on";
|
|
253
|
+
break;
|
|
254
|
+
case "showExtra":
|
|
255
|
+
anthroSettings.windows.showExtra = value === "on";
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (provider === "copilot") {
|
|
261
|
+
const copilotSettings = ps as CopilotProviderSettings;
|
|
262
|
+
switch (id) {
|
|
263
|
+
case "showMultiplier":
|
|
264
|
+
copilotSettings.showMultiplier = value === "on";
|
|
265
|
+
break;
|
|
266
|
+
case "showRequestsLeft":
|
|
267
|
+
copilotSettings.showRequestsLeft = value === "on";
|
|
268
|
+
break;
|
|
269
|
+
case "quotaDisplay":
|
|
270
|
+
copilotSettings.quotaDisplay = value as "percentage" | "requests";
|
|
271
|
+
break;
|
|
272
|
+
case "showMonth":
|
|
273
|
+
copilotSettings.windows.showMonth = value === "on";
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (provider === "gemini") {
|
|
279
|
+
const geminiSettings = ps as GeminiProviderSettings;
|
|
280
|
+
switch (id) {
|
|
281
|
+
case "showPro":
|
|
282
|
+
geminiSettings.windows.showPro = value === "on";
|
|
283
|
+
break;
|
|
284
|
+
case "showFlash":
|
|
285
|
+
geminiSettings.windows.showFlash = value === "on";
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (provider === "antigravity") {
|
|
291
|
+
const antigravitySettings = ps as AntigravityProviderSettings;
|
|
292
|
+
switch (id) {
|
|
293
|
+
case "showModels":
|
|
294
|
+
antigravitySettings.windows.showModels = value === "on";
|
|
295
|
+
break;
|
|
296
|
+
case "showCurrentModel":
|
|
297
|
+
antigravitySettings.showCurrentModel = value === "on";
|
|
298
|
+
break;
|
|
299
|
+
case "showScopedModels":
|
|
300
|
+
antigravitySettings.showScopedModels = value === "on";
|
|
301
|
+
break;
|
|
302
|
+
default:
|
|
303
|
+
if (id.startsWith("model:")) {
|
|
304
|
+
const model = id.slice("model:".length);
|
|
305
|
+
if (model) {
|
|
306
|
+
if (!antigravitySettings.modelVisibility) {
|
|
307
|
+
antigravitySettings.modelVisibility = {};
|
|
308
|
+
}
|
|
309
|
+
antigravitySettings.modelVisibility[model] = value === "on";
|
|
310
|
+
if (!antigravitySettings.modelOrder) {
|
|
311
|
+
antigravitySettings.modelOrder = [];
|
|
312
|
+
}
|
|
313
|
+
if (!antigravitySettings.modelOrder.includes(model)) {
|
|
314
|
+
antigravitySettings.modelOrder.push(model);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (provider === "codex") {
|
|
323
|
+
const codexSettings = ps as CodexProviderSettings;
|
|
324
|
+
switch (id) {
|
|
325
|
+
case "invertUsage":
|
|
326
|
+
codexSettings.invertUsage = value === "on";
|
|
327
|
+
break;
|
|
328
|
+
case "showPrimary":
|
|
329
|
+
codexSettings.windows.showPrimary = value === "on";
|
|
330
|
+
break;
|
|
331
|
+
case "showSecondary":
|
|
332
|
+
codexSettings.windows.showSecondary = value === "on";
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (provider === "kiro") {
|
|
338
|
+
const kiroSettings = ps as KiroProviderSettings;
|
|
339
|
+
switch (id) {
|
|
340
|
+
case "showCredits":
|
|
341
|
+
kiroSettings.windows.showCredits = value === "on";
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (provider === "zai") {
|
|
347
|
+
const zaiSettings = ps as ZaiProviderSettings;
|
|
348
|
+
switch (id) {
|
|
349
|
+
case "showTokens":
|
|
350
|
+
zaiSettings.windows.showTokens = value === "on";
|
|
351
|
+
break;
|
|
352
|
+
case "showMonthly":
|
|
353
|
+
zaiSettings.windows.showMonthly = value === "on";
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return settings;
|
|
359
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-specific window visibility rules.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { RateWindow, UsageSnapshot, ModelInfo } from "../types.js";
|
|
6
|
+
import type { Settings } from "../settings-types.js";
|
|
7
|
+
import { PROVIDER_METADATA } from "./metadata.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if a window should be shown based on settings.
|
|
11
|
+
*/
|
|
12
|
+
export function shouldShowWindow(
|
|
13
|
+
usage: UsageSnapshot,
|
|
14
|
+
window: RateWindow,
|
|
15
|
+
settings?: Settings,
|
|
16
|
+
model?: ModelInfo
|
|
17
|
+
): boolean {
|
|
18
|
+
const handler = PROVIDER_METADATA[usage.provider]?.isWindowVisible;
|
|
19
|
+
if (handler) {
|
|
20
|
+
return handler(usage, window, settings, model);
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|