dsh-plugin-subscription-usage 0.0.0-stage → 0.2.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.
Files changed (169) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +50 -2
  3. package/cordis.patch.yml +5 -0
  4. package/icon.svg +9 -0
  5. package/lib/auth/claude-code-creds.d.ts +23 -0
  6. package/lib/auth/claude-code-creds.js +172 -0
  7. package/lib/auth/device-flow.d.ts +55 -0
  8. package/lib/auth/device-flow.js +177 -0
  9. package/lib/auth/jwt.d.ts +10 -0
  10. package/lib/auth/jwt.js +25 -0
  11. package/lib/auth/oauth-flow.d.ts +91 -0
  12. package/lib/auth/oauth-flow.js +227 -0
  13. package/lib/auth/pkce.d.ts +31 -0
  14. package/lib/auth/pkce.js +35 -0
  15. package/lib/auth/rpc.d.ts +233 -0
  16. package/lib/auth/rpc.js +501 -0
  17. package/lib/auth/store.d.ts +198 -0
  18. package/lib/auth/store.js +473 -0
  19. package/lib/client/Footer.d.ts +3 -0
  20. package/lib/client/Footer.js +73 -0
  21. package/lib/client/Gauge.d.ts +28 -0
  22. package/lib/client/Gauge.js +139 -0
  23. package/lib/client/ImageGallery.d.ts +54 -0
  24. package/lib/client/ImageGallery.js +112 -0
  25. package/lib/client/ImageGenerateToolview.d.ts +48 -0
  26. package/lib/client/ImageGenerateToolview.js +130 -0
  27. package/lib/client/Notice.d.ts +15 -0
  28. package/lib/client/Notice.js +93 -0
  29. package/lib/client/ProviderCard.d.ts +35 -0
  30. package/lib/client/ProviderCard.js +240 -0
  31. package/lib/client/SpeedSelect.d.ts +72 -0
  32. package/lib/client/SpeedSelect.js +214 -0
  33. package/lib/client/Usage.d.ts +7 -0
  34. package/lib/client/Usage.js +83 -0
  35. package/lib/client/VideoGenerateToolview.d.ts +42 -0
  36. package/lib/client/VideoGenerateToolview.js +172 -0
  37. package/lib/client/context.d.ts +16 -0
  38. package/lib/client/context.js +11 -0
  39. package/lib/client/fast-command.d.ts +2 -0
  40. package/lib/client/fast-command.js +4 -0
  41. package/lib/client/hooks.d.ts +2 -0
  42. package/lib/client/hooks.js +10 -0
  43. package/lib/client/index.d.ts +3 -0
  44. package/lib/client/index.js +113 -0
  45. package/lib/client/locales.d.ts +139 -0
  46. package/lib/client/locales.js +267 -0
  47. package/lib/client/meter.d.ts +91 -0
  48. package/lib/client/meter.js +196 -0
  49. package/lib/client/prefs.d.ts +51 -0
  50. package/lib/client/prefs.js +71 -0
  51. package/lib/client/rpc.d.ts +161 -0
  52. package/lib/client/rpc.js +31 -0
  53. package/lib/client/store.d.ts +67 -0
  54. package/lib/client/store.js +129 -0
  55. package/lib/client/styles.d.ts +7 -0
  56. package/lib/client/styles.js +176 -0
  57. package/lib/client.js +3933 -0
  58. package/lib/client.js.map +1 -0
  59. package/lib/compat.d.ts +55 -0
  60. package/lib/compat.js +20 -0
  61. package/lib/http.d.ts +134 -0
  62. package/lib/http.js +431 -0
  63. package/lib/index.d.ts +121 -0
  64. package/lib/index.js +13399 -0
  65. package/lib/json-text.d.ts +2 -0
  66. package/lib/json-text.js +4 -0
  67. package/lib/model-defaults.d.ts +23 -0
  68. package/lib/model-defaults.js +238 -0
  69. package/lib/model-speeds.d.ts +10 -0
  70. package/lib/model-speeds.js +48 -0
  71. package/lib/models-directory.d.ts +17 -0
  72. package/lib/models-directory.js +25 -0
  73. package/lib/provider-settings.d.ts +55 -0
  74. package/lib/provider-settings.js +215 -0
  75. package/lib/providers/account-preferences.d.ts +46 -0
  76. package/lib/providers/account-preferences.js +188 -0
  77. package/lib/providers/accounts.d.ts +113 -0
  78. package/lib/providers/accounts.js +142 -0
  79. package/lib/providers/antigravity-oauth-client.d.ts +7 -0
  80. package/lib/providers/antigravity-oauth-client.js +7 -0
  81. package/lib/providers/antigravity.d.ts +119 -0
  82. package/lib/providers/antigravity.js +552 -0
  83. package/lib/providers/catalog-refresh.d.ts +4 -0
  84. package/lib/providers/catalog-refresh.js +30 -0
  85. package/lib/providers/catalog-store.d.ts +47 -0
  86. package/lib/providers/catalog-store.js +283 -0
  87. package/lib/providers/claude-cli-version.d.ts +15 -0
  88. package/lib/providers/claude-cli-version.js +24 -0
  89. package/lib/providers/claude.d.ts +212 -0
  90. package/lib/providers/claude.js +726 -0
  91. package/lib/providers/codex-client-version.d.ts +8 -0
  92. package/lib/providers/codex-client-version.js +17 -0
  93. package/lib/providers/codex-search.d.ts +29 -0
  94. package/lib/providers/codex-search.js +198 -0
  95. package/lib/providers/codex.d.ts +253 -0
  96. package/lib/providers/codex.js +930 -0
  97. package/lib/providers/common.d.ts +415 -0
  98. package/lib/providers/common.js +679 -0
  99. package/lib/providers/copilot.d.ts +365 -0
  100. package/lib/providers/copilot.js +956 -0
  101. package/lib/providers/grok.d.ts +214 -0
  102. package/lib/providers/grok.js +750 -0
  103. package/lib/providers/image-pool.d.ts +30 -0
  104. package/lib/providers/image-pool.js +89 -0
  105. package/lib/providers/npm-cli-version.d.ts +56 -0
  106. package/lib/providers/npm-cli-version.js +98 -0
  107. package/lib/providers/pool-family.d.ts +56 -0
  108. package/lib/providers/pool-family.js +45 -0
  109. package/lib/providers/pool-health.d.ts +91 -0
  110. package/lib/providers/pool-health.js +164 -0
  111. package/lib/providers/pool-usage.d.ts +106 -0
  112. package/lib/providers/pool-usage.js +302 -0
  113. package/lib/providers/pool.d.ts +115 -0
  114. package/lib/providers/pool.js +461 -0
  115. package/lib/providers/rate-limit.d.ts +192 -0
  116. package/lib/providers/rate-limit.js +338 -0
  117. package/lib/providers/replay.d.ts +4 -0
  118. package/lib/providers/replay.js +37 -0
  119. package/lib/providers/reset-redemption.d.ts +20 -0
  120. package/lib/providers/reset-redemption.js +70 -0
  121. package/lib/tools/image-generate.d.ts +128 -0
  122. package/lib/tools/image-generate.js +438 -0
  123. package/lib/tools/registration.d.ts +16 -0
  124. package/lib/tools/registration.js +25 -0
  125. package/lib/tools/usage.d.ts +62 -0
  126. package/lib/tools/usage.js +89 -0
  127. package/lib/tools/video-generate.d.ts +89 -0
  128. package/lib/tools/video-generate.js +257 -0
  129. package/lib/tools/x-search.d.ts +58 -0
  130. package/lib/tools/x-search.js +197 -0
  131. package/lib/translate/anthropic.d.ts +180 -0
  132. package/lib/translate/anthropic.js +534 -0
  133. package/lib/translate/antigravity-images.d.ts +11 -0
  134. package/lib/translate/antigravity-images.js +62 -0
  135. package/lib/translate/antigravity-schema.d.ts +4 -0
  136. package/lib/translate/antigravity-schema.js +145 -0
  137. package/lib/translate/antigravity-thinking.d.ts +5 -0
  138. package/lib/translate/antigravity-thinking.js +44 -0
  139. package/lib/translate/antigravity.d.ts +120 -0
  140. package/lib/translate/antigravity.js +412 -0
  141. package/lib/translate/chat-completions.d.ts +120 -0
  142. package/lib/translate/chat-completions.js +382 -0
  143. package/lib/translate/resolved.d.ts +98 -0
  144. package/lib/translate/resolved.js +186 -0
  145. package/lib/translate/responses.d.ts +192 -0
  146. package/lib/translate/responses.js +443 -0
  147. package/lib/translate/sse.d.ts +21 -0
  148. package/lib/translate/sse.js +62 -0
  149. package/lib/usage/headers.d.ts +21 -0
  150. package/lib/usage/headers.js +64 -0
  151. package/lib/usage/pace.d.ts +53 -0
  152. package/lib/usage/pace.js +48 -0
  153. package/lib/usage/service.d.ts +64 -0
  154. package/lib/usage/service.js +104 -0
  155. package/lib/usage-providers/common.d.ts +23 -0
  156. package/lib/usage-providers/common.js +28 -0
  157. package/lib/usage-providers/index.d.ts +42 -0
  158. package/lib/usage-providers/index.js +71 -0
  159. package/lib/usage-providers/keys.d.ts +11 -0
  160. package/lib/usage-providers/keys.js +52 -0
  161. package/lib/usage-providers/kimi.d.ts +4 -0
  162. package/lib/usage-providers/kimi.js +52 -0
  163. package/lib/usage-providers/ollama-cloud.d.ts +4 -0
  164. package/lib/usage-providers/ollama-cloud.js +42 -0
  165. package/lib/usage-providers/zai.d.ts +5 -0
  166. package/lib/usage-providers/zai.js +53 -0
  167. package/locale/en.json +6 -0
  168. package/locale/zh.json +6 -0
  169. package/package.json +115 -4
@@ -0,0 +1,113 @@
1
+ import { en, zh, LOCALE_NS } from './locales.js';
2
+ import { css } from './styles.js';
3
+ import { SubscriptionsStore } from './store.js';
4
+ import { PrefsStore } from './prefs.js';
5
+ import { ProviderCard } from './ProviderCard.js';
6
+ import { Footer } from './Footer.js';
7
+ import { Usage, UsageNavIcon } from './Usage.js';
8
+ import { Gauge } from './Gauge.js';
9
+ import { Notice } from './Notice.js';
10
+ import { ImageGenerateToolview, createImageLoader } from './ImageGenerateToolview.js';
11
+ import { VideoGenerateToolview, createVideoLoader } from './VideoGenerateToolview.js';
12
+ import { SpeedSelect, createSpeedLoader, createSpeedSetter } from './SpeedSelect.js';
13
+ import { fastCommandDescription } from './fast-command.js';
14
+ /** The Host entry id from cordis.patch.yml; the Models page dispatches our card by it. */
15
+ const ENTRY_ID = 'subscription-models';
16
+ export const inject = ['slots', 'connection', 'locale'];
17
+ const hasMethod = (value, name) => typeof value === 'object' && value !== null && name in value && typeof value[name] === 'function';
18
+ export function apply(ctx) {
19
+ ctx.effect(() => ctx.locale.register(LOCALE_NS, { en, zh }), 'dsh-plugin-subscription-usage: copy');
20
+ ctx.effect(() => {
21
+ const style = document.createElement('style');
22
+ style.dataset.plugin = 'dsh-plugin-subscription-usage';
23
+ style.textContent = css;
24
+ document.head.appendChild(style);
25
+ return () => { style.remove(); };
26
+ }, 'dsh-plugin-subscription-usage: stylesheet');
27
+ // In the browser the `connection` key holds the full client handle.
28
+ const connection = ctx.get('connection');
29
+ const t = ctx.locale.bind(LOCALE_NS);
30
+ const store = new SubscriptionsStore(connection.rpc);
31
+ const prefs = new PrefsStore();
32
+ const surface = () => ({ store, prefs, rpc: connection.rpc, t });
33
+ ctx.inject(['configForms'], scope => {
34
+ const forms = scope.get('configForms');
35
+ if (!hasMethod(forms, 'get'))
36
+ return;
37
+ scope.effect(() => prefs.bind(forms.get(ENTRY_ID)), 'dsh-plugin-subscription-usage: usage preferences');
38
+ });
39
+ ctx.slots.inject('settings.models.provider-card', () => ctx.slots.register({
40
+ name: 'settings.models.provider-card', key: ENTRY_ID, inject: surface,
41
+ }, ProviderCard));
42
+ ctx.slots.inject('settings.models.footer', () => ctx.slots.register({
43
+ name: 'settings.models.footer', id: 'subscription-models', order: 10, inject: surface,
44
+ }, Footer));
45
+ ctx.slots.inject('settings.section', () => ctx.slots.register({
46
+ name: 'settings.section', id: 'subscription-usage', order: 11, label: () => t('usage'), inject: surface,
47
+ }, Usage));
48
+ // The nav row keeps the shell's gear unless an icon is registered under the section id.
49
+ ctx.slots.inject('settings.section.icon', () => ctx.slots.register({
50
+ name: 'settings.section.icon', id: 'subscription-usage',
51
+ }, UsageNavIcon));
52
+ const models = () => {
53
+ const service = ctx.get('modelDirectories');
54
+ return hasMethod(service, 'directoryFor') ? service : undefined;
55
+ };
56
+ const gaugeInject = (sessionId) => {
57
+ let currentModel;
58
+ try {
59
+ currentModel = models()?.directoryFor(sessionId).store;
60
+ }
61
+ catch {
62
+ // An unknown session has no directory yet; the gauge then follows pinned providers only.
63
+ }
64
+ return { ...surface(), sessionId, currentModel };
65
+ };
66
+ ctx.slots.inject('conversation.composer.dock', () => ctx.slots.register({
67
+ name: 'conversation.composer.dock', id: 'subscription-models.gauge', order: 10, inject: gaugeInject,
68
+ }, Gauge));
69
+ ctx.slots.inject('conversation.hero.options', () => ctx.slots.register({
70
+ name: 'conversation.hero.options', id: 'subscription-models.gauge', order: 10, inject: gaugeInject,
71
+ }, Gauge));
72
+ ctx.slots.inject('shell.overlay', () => ctx.slots.register({
73
+ name: 'shell.overlay', id: 'subscription-models.notice', order: 50, inject: surface,
74
+ }, Notice));
75
+ ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({
76
+ name: 'tool.call.toolview', key: 'image_generate', locale: LOCALE_NS,
77
+ inject: () => ({ load: createImageLoader(connection.rpc) }),
78
+ }, ImageGenerateToolview));
79
+ ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({
80
+ name: 'tool.call.toolview', key: 'video_generate', locale: LOCALE_NS,
81
+ inject: () => ({ loadVideo: createVideoLoader(connection.rpc) }),
82
+ }, VideoGenerateToolview));
83
+ ctx.slots.inject('conversation.input.right', () => ctx.slots.register({
84
+ name: 'conversation.input.right', id: 'codex-speed', order: 0, locale: LOCALE_NS,
85
+ inject: (sessionId) => ({
86
+ loadSpeed: createSpeedLoader(connection, models, sessionId),
87
+ setSpeed: createSpeedSetter(connection, sessionId, models),
88
+ }),
89
+ }, SpeedSelect));
90
+ ctx.inject(['commandUi'], (scope) => {
91
+ const command = scope.get('commandUi');
92
+ scope.effect(() => command.register({
93
+ name: 'fast',
94
+ description: fastCommandDescription(() => t('commandFast')),
95
+ available: () => true,
96
+ ui: {
97
+ kind: 'popupSelect',
98
+ options: async (session) => {
99
+ const state = await createSpeedLoader(connection, models, session.sessionId)();
100
+ if (!state.visible)
101
+ throw new Error(t('commandFastUnavailable'));
102
+ return [
103
+ { id: 'standard', label: t('speedStandard'), detail: t('speedStandardDescription') },
104
+ { id: 'fast', label: t('speedFast'), detail: t('speedFastDescription') },
105
+ ].map(option => ({ ...option, active: option.id === state.tier }));
106
+ },
107
+ onSelect: async (option, session) => {
108
+ await createSpeedSetter(connection, session.sessionId, models)(option.id === 'fast' ? 'fast' : 'standard');
109
+ },
110
+ },
111
+ }), 'dsh-plugin-subscription-usage: /fast');
112
+ });
113
+ }
@@ -0,0 +1,139 @@
1
+ /** Copy for every Client surface of this plugin, in one locale namespace. */
2
+ export declare const en: {
3
+ readonly signIn: "Sign in";
4
+ readonly signInAgain: "Sign in";
5
+ readonly noApiKey: "No API key needed";
6
+ readonly signInExpired: "Sign-in expired";
7
+ readonly signedIn: "Signed in";
8
+ readonly signInNeeded: "Sign-in needed";
9
+ readonly manage: "Manage";
10
+ readonly modelsCount: "{visible}/{total} models";
11
+ readonly modelsCountTitle: "Models shown in the picker";
12
+ readonly refreshUsage: "Refresh usage";
13
+ readonly refreshUsageNamed: "Refresh {name} usage";
14
+ readonly refreshedWait: "Refreshed. Again in {seconds}s";
15
+ readonly defaultAccount: "Default account";
16
+ readonly servingAccount: "Serving this session";
17
+ readonly live: "live";
18
+ readonly liveTitle: "Updates with every response";
19
+ readonly agoShort: "{time} ago";
20
+ readonly staleShort: "{time} old";
21
+ readonly staleTitle: "Refresh failed. Retrying {when}";
22
+ readonly noUsageData: "No usage data";
23
+ readonly noUsageDataTitle: "This provider does not publish usage";
24
+ readonly usageUnavailable: "Usage unavailable";
25
+ readonly moreAccounts: "{count} more accounts";
26
+ readonly stepTabOpened: "Tab opened";
27
+ readonly stepApprove: "Approve access";
28
+ readonly stepLoadModels: "Load models";
29
+ readonly stepCodeIssued: "Code issued";
30
+ readonly stepWaitingGithub: "Waiting for GitHub";
31
+ readonly pasteRedirect: "Paste redirect URL instead";
32
+ readonly pastePlaceholder: "Redirect URL or code";
33
+ readonly continue: "Continue";
34
+ readonly cancel: "Cancel";
35
+ readonly copyCode: "Copy code";
36
+ readonly claudeImport: "Import Claude Code";
37
+ readonly claudeBrowser: "Browser sign-in";
38
+ readonly tabAccounts: "Accounts";
39
+ readonly tabModels: "Models";
40
+ readonly tabTools: "Tools";
41
+ readonly pool: "Pool";
42
+ readonly poolInclude: "Include {account} in the pool";
43
+ readonly makeDefault: "Make default";
44
+ readonly signOut: "Sign out";
45
+ readonly addAccount: "Add account";
46
+ readonly searchModels: "Search {count} models";
47
+ readonly showInPicker: "Show {model} in the picker";
48
+ readonly pickerCount: "{visible} of {total} in the picker";
49
+ readonly autoShowNew: "Show new models automatically";
50
+ readonly selectAll: "Select all";
51
+ readonly deselectAll: "Deselect all";
52
+ readonly effortFor: "Default effort for {model}";
53
+ readonly effortAuto: "Auto";
54
+ readonly toolWebSearch: "Web search";
55
+ readonly toolImage: "Image generation";
56
+ readonly toolVideo: "Video generation";
57
+ readonly toolXSearch: "X search";
58
+ readonly toolsNote: "Applies to new sessions";
59
+ readonly save: "Save";
60
+ readonly saving: "Saving…";
61
+ readonly saveFailed: "Could not save: {message}";
62
+ readonly loadFailed: "Could not load: {message}";
63
+ readonly window5h: "5h";
64
+ readonly window7d: "7d";
65
+ readonly windowOther: "limit";
66
+ readonly resetsIn: "in {time}";
67
+ readonly emptyAt: "empty {time}";
68
+ readonly backAt: "back {time}";
69
+ readonly tipUsedLeft: "{used}% used · {left}% left";
70
+ readonly tipElapsed: "{percent}% of the window has passed";
71
+ readonly tipPace: "Pace: ~{percent}% by reset";
72
+ readonly tipResets: "Resets {time}";
73
+ readonly tipCount: "{used} of {limit} used";
74
+ readonly notReported: "Not reported";
75
+ readonly subscriptions: "Subscriptions";
76
+ readonly addProvider: "Add a provider";
77
+ readonly apiKey: "API key";
78
+ readonly addKey: "Add";
79
+ readonly removeKey: "Remove key";
80
+ readonly keyHelp: "Paste an API key. It is checked once, then stored on this machine.";
81
+ readonly keyChecking: "Checking key…";
82
+ readonly usageEmpty: "Sign in to a subscription in Models to see its usage here.";
83
+ readonly composerUsage: "Composer usage";
84
+ readonly composerUsageNote: "Current model plus pinned";
85
+ readonly showQuotaAs: "Show quota as";
86
+ readonly displayLeft: "Left";
87
+ readonly displayUsed: "Used";
88
+ readonly paceWarnings: "Pace warnings";
89
+ readonly proxy: "Proxy";
90
+ readonly proxyOff: "Off";
91
+ readonly proxyOn: "On";
92
+ readonly configure: "Configure";
93
+ readonly proxyUrl: "Proxy URL";
94
+ readonly proxyBypass: "Bypass hosts, comma separated";
95
+ readonly proxyEnabled: "Use this proxy";
96
+ readonly proxyTest: "Test";
97
+ readonly proxyTestOk: "HTTP {status} in {ms} ms";
98
+ readonly usage: "Usage";
99
+ readonly usageLabel: "Subscription usage";
100
+ readonly refreshNow: "Refresh now";
101
+ readonly usageSettings: "Usage settings";
102
+ readonly pin: "Pin to composer";
103
+ readonly unpin: "Unpin from composer";
104
+ readonly otherProviders: "{count} more";
105
+ readonly noticeEmpty: "{provider} {window} empty around {time}";
106
+ readonly noticeOut: "{provider} {window} limit reached";
107
+ readonly noticeSwitched: "{provider} limit reached. Switched to {account}";
108
+ readonly dismiss: "Dismiss";
109
+ readonly generating: "Generating image…";
110
+ readonly generatingVideo: "Generating video…";
111
+ readonly image: "image";
112
+ readonly imageClose: "Close";
113
+ readonly imageLoadFailed: "Retry";
114
+ readonly imageLoading: "Loading…";
115
+ readonly imagePreview: "Image preview";
116
+ readonly speed: "Speed";
117
+ readonly speedStandard: "Standard";
118
+ readonly speedStandardDescription: "Default speed";
119
+ readonly speedFast: "Fast";
120
+ readonly speedFastDescription: "1.5x speed, more usage";
121
+ readonly videoLoadFailed: "Video failed to load: {message}";
122
+ readonly videoLoading: "Loading video…";
123
+ readonly viewImage: "View image";
124
+ readonly viewImageNamed: "View {name}";
125
+ readonly commandFast: "Switch the Codex speed tier (Standard/Fast)";
126
+ readonly commandFastUnavailable: "The current model has no fast tier; /fast only works on Codex models whose catalog advertises one";
127
+ };
128
+ /** Every copy key. */
129
+ export type SubscriptionsKey = keyof typeof en;
130
+ /** The locale namespace this plugin registers. */
131
+ export declare const LOCALE_NS = "subscription-models";
132
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
133
+ interface LocaleNamespaceMap {
134
+ 'subscription-models': SubscriptionsKey;
135
+ }
136
+ }
137
+ export declare const zh: Record<SubscriptionsKey, string>;
138
+ /** Fill `{name}` placeholders. */
139
+ export declare function format(text: string, params?: Record<string, string | number>): string;
@@ -0,0 +1,267 @@
1
+ /** Copy for every Client surface of this plugin, in one locale namespace. */
2
+ export const en = {
3
+ // Provider card
4
+ signIn: 'Sign in',
5
+ signInAgain: 'Sign in',
6
+ noApiKey: 'No API key needed',
7
+ signInExpired: 'Sign-in expired',
8
+ signedIn: 'Signed in',
9
+ signInNeeded: 'Sign-in needed',
10
+ manage: 'Manage',
11
+ modelsCount: '{visible}/{total} models',
12
+ modelsCountTitle: 'Models shown in the picker',
13
+ refreshUsage: 'Refresh usage',
14
+ refreshUsageNamed: 'Refresh {name} usage',
15
+ refreshedWait: 'Refreshed. Again in {seconds}s',
16
+ defaultAccount: 'Default account',
17
+ servingAccount: 'Serving this session',
18
+ live: 'live',
19
+ liveTitle: 'Updates with every response',
20
+ agoShort: '{time} ago',
21
+ staleShort: '{time} old',
22
+ staleTitle: 'Refresh failed. Retrying {when}',
23
+ noUsageData: 'No usage data',
24
+ noUsageDataTitle: 'This provider does not publish usage',
25
+ usageUnavailable: 'Usage unavailable',
26
+ moreAccounts: '{count} more accounts',
27
+ // Sign-in flow
28
+ stepTabOpened: 'Tab opened',
29
+ stepApprove: 'Approve access',
30
+ stepLoadModels: 'Load models',
31
+ stepCodeIssued: 'Code issued',
32
+ stepWaitingGithub: 'Waiting for GitHub',
33
+ pasteRedirect: 'Paste redirect URL instead',
34
+ pastePlaceholder: 'Redirect URL or code',
35
+ continue: 'Continue',
36
+ cancel: 'Cancel',
37
+ copyCode: 'Copy code',
38
+ claudeImport: 'Import Claude Code',
39
+ claudeBrowser: 'Browser sign-in',
40
+ // Manage panel
41
+ tabAccounts: 'Accounts',
42
+ tabModels: 'Models',
43
+ tabTools: 'Tools',
44
+ pool: 'Pool',
45
+ poolInclude: 'Include {account} in the pool',
46
+ makeDefault: 'Make default',
47
+ signOut: 'Sign out',
48
+ addAccount: 'Add account',
49
+ searchModels: 'Search {count} models',
50
+ showInPicker: 'Show {model} in the picker',
51
+ pickerCount: '{visible} of {total} in the picker',
52
+ autoShowNew: 'Show new models automatically',
53
+ selectAll: 'Select all',
54
+ deselectAll: 'Deselect all',
55
+ effortFor: 'Default effort for {model}',
56
+ effortAuto: 'Auto',
57
+ toolWebSearch: 'Web search',
58
+ toolImage: 'Image generation',
59
+ toolVideo: 'Video generation',
60
+ toolXSearch: 'X search',
61
+ toolsNote: 'Applies to new sessions',
62
+ save: 'Save',
63
+ saving: 'Saving…',
64
+ saveFailed: 'Could not save: {message}',
65
+ loadFailed: 'Could not load: {message}',
66
+ // Window labels and times
67
+ window5h: '5h',
68
+ window7d: '7d',
69
+ windowOther: 'limit',
70
+ resetsIn: 'in {time}',
71
+ emptyAt: 'empty {time}',
72
+ backAt: 'back {time}',
73
+ tipUsedLeft: '{used}% used · {left}% left',
74
+ tipElapsed: '{percent}% of the window has passed',
75
+ tipPace: 'Pace: ~{percent}% by reset',
76
+ tipResets: 'Resets {time}',
77
+ tipCount: '{used} of {limit} used',
78
+ notReported: 'Not reported',
79
+ // Footer
80
+ subscriptions: 'Subscriptions',
81
+ addProvider: 'Add a provider',
82
+ apiKey: 'API key',
83
+ addKey: 'Add',
84
+ removeKey: 'Remove key',
85
+ keyHelp: 'Paste an API key. It is checked once, then stored on this machine.',
86
+ keyChecking: 'Checking key…',
87
+ usageEmpty: 'Sign in to a subscription in Models to see its usage here.',
88
+ composerUsage: 'Composer usage',
89
+ composerUsageNote: 'Current model plus pinned',
90
+ showQuotaAs: 'Show quota as',
91
+ displayLeft: 'Left',
92
+ displayUsed: 'Used',
93
+ paceWarnings: 'Pace warnings',
94
+ proxy: 'Proxy',
95
+ proxyOff: 'Off',
96
+ proxyOn: 'On',
97
+ configure: 'Configure',
98
+ proxyUrl: 'Proxy URL',
99
+ proxyBypass: 'Bypass hosts, comma separated',
100
+ proxyEnabled: 'Use this proxy',
101
+ proxyTest: 'Test',
102
+ proxyTestOk: 'HTTP {status} in {ms} ms',
103
+ // Gauge and popover
104
+ usage: 'Usage',
105
+ usageLabel: 'Subscription usage',
106
+ refreshNow: 'Refresh now',
107
+ usageSettings: 'Usage settings',
108
+ pin: 'Pin to composer',
109
+ unpin: 'Unpin from composer',
110
+ otherProviders: '{count} more',
111
+ // Notices
112
+ noticeEmpty: '{provider} {window} empty around {time}',
113
+ noticeOut: '{provider} {window} limit reached',
114
+ noticeSwitched: '{provider} limit reached. Switched to {account}',
115
+ dismiss: 'Dismiss',
116
+ // Retained upstream surfaces
117
+ generating: 'Generating image…',
118
+ generatingVideo: 'Generating video…',
119
+ image: 'image',
120
+ imageClose: 'Close',
121
+ imageLoadFailed: 'Retry',
122
+ imageLoading: 'Loading…',
123
+ imagePreview: 'Image preview',
124
+ speed: 'Speed',
125
+ speedStandard: 'Standard',
126
+ speedStandardDescription: 'Default speed',
127
+ speedFast: 'Fast',
128
+ speedFastDescription: '1.5x speed, more usage',
129
+ videoLoadFailed: 'Video failed to load: {message}',
130
+ videoLoading: 'Loading video…',
131
+ viewImage: 'View image',
132
+ viewImageNamed: 'View {name}',
133
+ commandFast: 'Switch the Codex speed tier (Standard/Fast)',
134
+ commandFastUnavailable: 'The current model has no fast tier; /fast only works on Codex models whose catalog advertises one',
135
+ };
136
+ /** The locale namespace this plugin registers. */
137
+ export const LOCALE_NS = 'subscription-models';
138
+ export const zh = {
139
+ signIn: '登录',
140
+ signInAgain: '重新登录',
141
+ noApiKey: '无需 API 密钥',
142
+ signInExpired: '登录已过期',
143
+ signedIn: '已登录',
144
+ signInNeeded: '需要登录',
145
+ manage: '管理',
146
+ modelsCount: '{visible}/{total} 个模型',
147
+ modelsCountTitle: '模型选择器中显示的模型',
148
+ refreshUsage: '刷新用量',
149
+ refreshUsageNamed: '刷新 {name} 用量',
150
+ refreshedWait: '已刷新,{seconds} 秒后可再次刷新',
151
+ defaultAccount: '默认账号',
152
+ servingAccount: '正在为本会话服务',
153
+ live: '实时',
154
+ liveTitle: '每次回复后更新',
155
+ agoShort: '{time}前',
156
+ staleShort: '已过 {time}',
157
+ staleTitle: '刷新失败,{when}重试',
158
+ noUsageData: '无用量数据',
159
+ noUsageDataTitle: '该服务商不提供用量数据',
160
+ usageUnavailable: '用量不可用',
161
+ moreAccounts: '另外 {count} 个账号',
162
+ stepTabOpened: '已打开标签页',
163
+ stepApprove: '批准访问',
164
+ stepLoadModels: '加载模型',
165
+ stepCodeIssued: '已生成代码',
166
+ stepWaitingGithub: '等待 GitHub',
167
+ pasteRedirect: '改为粘贴回调 URL',
168
+ pastePlaceholder: '回调 URL 或授权码',
169
+ continue: '继续',
170
+ cancel: '取消',
171
+ copyCode: '复制代码',
172
+ claudeImport: '导入 Claude Code',
173
+ claudeBrowser: '浏览器登录',
174
+ tabAccounts: '账号',
175
+ tabModels: '模型',
176
+ tabTools: '工具',
177
+ pool: '账号池',
178
+ poolInclude: '将 {account} 加入账号池',
179
+ makeDefault: '设为默认',
180
+ signOut: '退出登录',
181
+ addAccount: '添加账号',
182
+ searchModels: '搜索 {count} 个模型',
183
+ showInPicker: '在选择器中显示 {model}',
184
+ pickerCount: '选择器中显示 {visible}/{total}',
185
+ autoShowNew: '自动显示新模型',
186
+ selectAll: '全选',
187
+ deselectAll: '全不选',
188
+ effortFor: '{model} 的默认推理强度',
189
+ effortAuto: '自动',
190
+ toolWebSearch: '网页搜索',
191
+ toolImage: '图片生成',
192
+ toolVideo: '视频生成',
193
+ toolXSearch: 'X 搜索',
194
+ toolsNote: '对新会话生效',
195
+ save: '保存',
196
+ saving: '保存中…',
197
+ saveFailed: '保存失败:{message}',
198
+ loadFailed: '加载失败:{message}',
199
+ window5h: '5h',
200
+ window7d: '7d',
201
+ windowOther: '限额',
202
+ resetsIn: '{time}后',
203
+ emptyAt: '{time} 用尽',
204
+ backAt: '{time} 恢复',
205
+ tipUsedLeft: '已用 {used}% · 剩余 {left}%',
206
+ tipElapsed: '窗口已过 {percent}%',
207
+ tipPace: '按当前速度:重置前约用 {percent}%',
208
+ tipResets: '{time} 重置',
209
+ tipCount: '已用 {used} / {limit}',
210
+ notReported: '未提供',
211
+ subscriptions: '订阅',
212
+ addProvider: '添加提供商',
213
+ apiKey: 'API 密钥',
214
+ addKey: '添加',
215
+ removeKey: '移除密钥',
216
+ keyHelp: '粘贴 API 密钥。验证一次后保存在本机。',
217
+ keyChecking: '正在验证密钥…',
218
+ usageEmpty: '在“模型”中登录订阅后,可在此查看用量。',
219
+ composerUsage: '输入框用量',
220
+ composerUsageNote: '当前模型和已固定',
221
+ showQuotaAs: '额度显示为',
222
+ displayLeft: '剩余',
223
+ displayUsed: '已用',
224
+ paceWarnings: '速度预警',
225
+ proxy: '代理',
226
+ proxyOff: '关闭',
227
+ proxyOn: '开启',
228
+ configure: '配置',
229
+ proxyUrl: '代理 URL',
230
+ proxyBypass: '绕过的主机,逗号分隔',
231
+ proxyEnabled: '使用此代理',
232
+ proxyTest: '测试',
233
+ proxyTestOk: 'HTTP {status},耗时 {ms} ms',
234
+ usage: '用量',
235
+ usageLabel: '订阅用量',
236
+ refreshNow: '立即刷新',
237
+ usageSettings: '用量设置',
238
+ pin: '固定到输入框',
239
+ unpin: '从输入框取消固定',
240
+ otherProviders: '另外 {count} 个',
241
+ noticeEmpty: '{provider} {window} 预计 {time} 用尽',
242
+ noticeOut: '{provider} {window} 已达上限',
243
+ noticeSwitched: '{provider} 已达上限,已切换到 {account}',
244
+ dismiss: '关闭',
245
+ generating: '正在生成图片…',
246
+ generatingVideo: '正在生成视频…',
247
+ image: '图片',
248
+ imageClose: '关闭',
249
+ imageLoadFailed: '重试',
250
+ imageLoading: '加载中…',
251
+ imagePreview: '图片预览',
252
+ speed: '速度',
253
+ speedStandard: '标准',
254
+ speedStandardDescription: '默认速度',
255
+ speedFast: '快速',
256
+ speedFastDescription: '约 1.5 倍速度,消耗更多用量',
257
+ videoLoadFailed: '视频加载失败:{message}',
258
+ videoLoading: '视频加载中…',
259
+ viewImage: '查看图片',
260
+ viewImageNamed: '查看 {name}',
261
+ commandFast: '切换 Codex 速度档(标准/快速)',
262
+ commandFastUnavailable: '当前模型不支持快速档;/fast 仅对目录声明了 fast tier 的 Codex 模型可用',
263
+ };
264
+ /** Fill `{name}` placeholders. */
265
+ export function format(text, params = {}) {
266
+ return text.replace(/\{(\w+)\}/g, (match, key) => (key in params ? String(params[key]) : match));
267
+ }
@@ -0,0 +1,91 @@
1
+ import type { UsageWindow } from '../providers/common.js';
2
+ import type { Pace, QuotaDisplay } from '../usage/pace.js';
3
+ import type { SubscriptionsKey } from './locales.js';
4
+ export type T = (key: SubscriptionsKey) => string;
5
+ /** Translate with placeholders. */
6
+ export declare function tf(t: T, key: SubscriptionsKey, params: Record<string, string | number>): string;
7
+ declare const PATHS: {
8
+ readonly refresh: import("react").JSX.Element;
9
+ readonly alert: import("react").JSX.Element;
10
+ readonly check: import("react").JSX.Element;
11
+ readonly star: import("react").JSX.Element;
12
+ readonly bolt: import("react").JSX.Element;
13
+ readonly pin: import("react").JSX.Element;
14
+ readonly pinFilled: import("react").JSX.Element;
15
+ readonly gear: import("react").JSX.Element;
16
+ readonly ext: import("react").JSX.Element;
17
+ readonly copy: import("react").JSX.Element;
18
+ readonly x: import("react").JSX.Element;
19
+ readonly right: import("react").JSX.Element;
20
+ readonly down: import("react").JSX.Element;
21
+ readonly meter: import("react").JSX.Element;
22
+ readonly sparkle: import("react").JSX.Element;
23
+ };
24
+ export type IconName = keyof typeof PATHS;
25
+ /** One 16-unit stroke icon. */
26
+ export declare function Icon({ name, size, className }: {
27
+ name: IconName;
28
+ size?: number;
29
+ className?: string;
30
+ }): import("react").JSX.Element;
31
+ /** "3h 6m", "2d 12h", "42m". */
32
+ export declare function shortDuration(ms: number): string;
33
+ /**
34
+ * A short point in time in the browser's locale: "6:04 PM" today, "Wed" within
35
+ * the week, "12 Nov" beyond. The day alone keeps the time column narrow; the
36
+ * tooltip carries the exact reset time.
37
+ */
38
+ export declare function clockTime(at: number, now: number): string;
39
+ /** Weekday and time, for tooltips. */
40
+ export declare function fullTime(at: number): string;
41
+ /** The window's length as "5h", "7d" or "30d", rounded to a whole unit; undefined when unknown. */
42
+ export declare function lengthLabel(durationMs: number | undefined): string | undefined;
43
+ /** "5h", "7d", "30d": the window's own length, else its kind, else "limit". */
44
+ export declare function kindLabel(t: T, kind: UsageWindow['kind'], durationMs?: number): string;
45
+ /** The length label, with a model scope when the window has one. A per-model quota is named by its scope alone. */
46
+ export declare function windowLabel(t: T, window: UsageWindow): string;
47
+ /** A window as shown, with the models it stands for when several share one quota. */
48
+ export type ShownWindow = UsageWindow & {
49
+ models?: string[];
50
+ };
51
+ /**
52
+ * Per-model windows that report the same usage and reset share one quota pool
53
+ * (Antigravity reports one window per model), so they merge into one row named
54
+ * by model family. A per-model window at 0% with no reset carries no information
55
+ * and is hidden. Unscoped windows pass through unchanged.
56
+ */
57
+ export declare function shownWindows(windows: readonly UsageWindow[] | undefined): ShownWindow[];
58
+ /**
59
+ * What compact surfaces show: unscoped windows, session first. A provider that
60
+ * only reports per-model windows (Antigravity) shows its two most used instead.
61
+ */
62
+ export declare function primaryWindows(windows: readonly UsageWindow[] | undefined): ShownWindow[];
63
+ /** The pace bar: fill is quota, hatch is the forecast, color is the pace state. Drains in `left` mode. */
64
+ export declare function Bar({ window, p, display, height }: {
65
+ window: UsageWindow;
66
+ p: Pace;
67
+ display: QuotaDisplay;
68
+ height?: number;
69
+ }): import("react").JSX.Element;
70
+ /** One window on the shared grid: label | bar | value | time. */
71
+ export declare function WindowRow({ t, window, display, now }: {
72
+ t: T;
73
+ window: ShownWindow;
74
+ display: QuotaDisplay;
75
+ now: number;
76
+ }): import("react").JSX.Element;
77
+ /** Label, small bar and value, for summary rows and the gauge. */
78
+ export declare function Mini({ t, window, display, now }: {
79
+ t: T;
80
+ window: ShownWindow;
81
+ display: QuotaDisplay;
82
+ now: number;
83
+ }): import("react").JSX.Element;
84
+ /** The mini meters of an account's unscoped windows. */
85
+ export declare function Minis({ t, windows, display, now }: {
86
+ t: T;
87
+ windows: readonly UsageWindow[] | undefined;
88
+ display: QuotaDisplay;
89
+ now: number;
90
+ }): import("react").JSX.Element | null;
91
+ export {};