dsh-plugin-subscription-oauth 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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +413 -2
  3. package/cordis.patch.yml +13 -0
  4. package/lib/auth/device-flow.d.ts +112 -0
  5. package/lib/auth/device-flow.js +319 -0
  6. package/lib/auth/device-id.d.ts +31 -0
  7. package/lib/auth/device-id.js +58 -0
  8. package/lib/auth/flow.d.ts +33 -0
  9. package/lib/auth/flow.js +12 -0
  10. package/lib/auth/glm-flow.d.ts +99 -0
  11. package/lib/auth/glm-flow.js +194 -0
  12. package/lib/auth/headers.d.ts +61 -0
  13. package/lib/auth/headers.js +106 -0
  14. package/lib/auth/pkce-flow.d.ts +78 -0
  15. package/lib/auth/pkce-flow.js +205 -0
  16. package/lib/auth/provider-controller.d.ts +241 -0
  17. package/lib/auth/provider-controller.js +502 -0
  18. package/lib/auth/registry.d.ts +91 -0
  19. package/lib/auth/registry.js +149 -0
  20. package/lib/auth/rpc.d.ts +31 -0
  21. package/lib/auth/rpc.js +200 -0
  22. package/lib/auth/store.d.ts +99 -0
  23. package/lib/auth/store.js +213 -0
  24. package/lib/auth/tokens.d.ts +76 -0
  25. package/lib/auth/tokens.js +103 -0
  26. package/lib/client/SubscriptionsSection.d.ts +34 -0
  27. package/lib/client/SubscriptionsSection.js +742 -0
  28. package/lib/client/index.d.ts +36 -0
  29. package/lib/client/index.js +47 -0
  30. package/lib/client/locales.d.ts +187 -0
  31. package/lib/client/locales.js +185 -0
  32. package/lib/client/styles.d.ts +18 -0
  33. package/lib/client/styles.js +257 -0
  34. package/lib/client/subscriptions-rpc.d.ts +24 -0
  35. package/lib/client/subscriptions-rpc.js +44 -0
  36. package/lib/client.js +2078 -0
  37. package/lib/client.js.map +1 -0
  38. package/lib/constants.d.ts +79 -0
  39. package/lib/constants.js +91 -0
  40. package/lib/errors.d.ts +28 -0
  41. package/lib/errors.js +34 -0
  42. package/lib/http.d.ts +24 -0
  43. package/lib/http.js +98 -0
  44. package/lib/index.d.ts +57 -0
  45. package/lib/index.js +185 -0
  46. package/lib/protocol.d.ts +316 -0
  47. package/lib/protocol.js +29 -0
  48. package/lib/providers/antigravity-catalog.d.ts +53 -0
  49. package/lib/providers/antigravity-catalog.js +269 -0
  50. package/lib/providers/antigravity.d.ts +331 -0
  51. package/lib/providers/antigravity.js +821 -0
  52. package/lib/providers/auto.d.ts +151 -0
  53. package/lib/providers/auto.js +351 -0
  54. package/lib/providers/catalog.d.ts +69 -0
  55. package/lib/providers/catalog.js +78 -0
  56. package/lib/providers/common.d.ts +51 -0
  57. package/lib/providers/common.js +169 -0
  58. package/lib/providers/glm-provider.d.ts +41 -0
  59. package/lib/providers/glm-provider.js +165 -0
  60. package/lib/providers/glm.d.ts +159 -0
  61. package/lib/providers/glm.js +445 -0
  62. package/lib/providers/grok.d.ts +224 -0
  63. package/lib/providers/grok.js +700 -0
  64. package/lib/providers/kimi-provider.d.ts +45 -0
  65. package/lib/providers/kimi-provider.js +148 -0
  66. package/lib/providers/kimi.d.ts +151 -0
  67. package/lib/providers/kimi.js +400 -0
  68. package/lib/providers/responses-stream.d.ts +58 -0
  69. package/lib/providers/responses-stream.js +115 -0
  70. package/lib/providers/usage.d.ts +65 -0
  71. package/lib/providers/usage.js +309 -0
  72. package/lib/settings.d.ts +122 -0
  73. package/lib/settings.js +333 -0
  74. package/lib/translate/antigravity-schema.d.ts +24 -0
  75. package/lib/translate/antigravity-schema.js +174 -0
  76. package/lib/translate/antigravity.d.ts +184 -0
  77. package/lib/translate/antigravity.js +419 -0
  78. package/lib/translate/responses.d.ts +156 -0
  79. package/lib/translate/responses.js +395 -0
  80. package/lib/translate/sse.d.ts +27 -0
  81. package/lib/translate/sse.js +82 -0
  82. package/package.json +126 -4
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Subscriptions settings page, browser half.
3
+ *
4
+ * Registers one `settings.section` entry titled 订阅 / Subscriptions. Every
5
+ * connection fact arrives through the node half's `subscription-oauth` RPC
6
+ * endpoints, so this half holds no credential state of its own, and the copy
7
+ * rides the client locale service under the `settings.subscriptions` namespace.
8
+ *
9
+ * @module dsh-plugin-subscription-oauth/client
10
+ */
11
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
12
+ import type { SubscriptionsKey } from './locales.js';
13
+ export type { SubscriptionsSectionInjected, SubscriptionsSectionProps } from './SubscriptionsSection.js';
14
+ export type { SubscriptionsKey } from './locales.js';
15
+ export { createSubscriptionsCall, SubscriptionsRpcError } from './subscriptions-rpc.js';
16
+ export type { SubscriptionsCall } from './subscriptions-rpc.js';
17
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
18
+ interface LocaleNamespaceMap {
19
+ /** The Subscriptions settings page copy. */
20
+ 'settings.subscriptions': SubscriptionsKey;
21
+ }
22
+ }
23
+ /**
24
+ * Required services: `slots` carries the registration seat, `connection` the
25
+ * RPC caller, and `locale` the copy dictionaries.
26
+ */
27
+ export declare const inject: string[];
28
+ /**
29
+ * Register the Subscriptions settings section.
30
+ *
31
+ * Registration goes through `slots.inject`, so the shell's own apply order
32
+ * relative to this one is unconstrained.
33
+ *
34
+ * @param ctx - client root context.
35
+ */
36
+ export declare function apply(ctx: ClientContext): void;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Subscriptions settings page, browser half.
3
+ *
4
+ * Registers one `settings.section` entry titled 订阅 / Subscriptions. Every
5
+ * connection fact arrives through the node half's `subscription-oauth` RPC
6
+ * endpoints, so this half holds no credential state of its own, and the copy
7
+ * rides the client locale service under the `settings.subscriptions` namespace.
8
+ *
9
+ * @module dsh-plugin-subscription-oauth/client
10
+ */
11
+ import { SubscriptionsSection } from './SubscriptionsSection.js';
12
+ import { createSubscriptionsCall } from './subscriptions-rpc.js';
13
+ import { en, zh } from './locales.js';
14
+ export { createSubscriptionsCall, SubscriptionsRpcError } from './subscriptions-rpc.js';
15
+ /** Dictionary namespace owned by this plugin. */
16
+ const NS = 'settings.subscriptions';
17
+ /** Settings nav position: after the shipped sections, before plugin tooling. */
18
+ const SECTION_ORDER = 92;
19
+ /**
20
+ * Required services: `slots` carries the registration seat, `connection` the
21
+ * RPC caller, and `locale` the copy dictionaries.
22
+ */
23
+ export const inject = ['slots', 'connection', 'locale'];
24
+ /**
25
+ * Register the Subscriptions settings section.
26
+ *
27
+ * Registration goes through `slots.inject`, so the shell's own apply order
28
+ * relative to this one is unconstrained.
29
+ *
30
+ * @param ctx - client root context.
31
+ */
32
+ export function apply(ctx) {
33
+ ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-plugin-subscription-oauth: copy dictionaries');
34
+ // The shell's Context merge types `connection` as the host handle; in the
35
+ // browser the same key holds the full client ConnectionHandle.
36
+ const connection = ctx.get('connection');
37
+ const t = ctx.locale.bind(NS);
38
+ const call = createSubscriptionsCall(connection.rpc);
39
+ ctx.slots.inject('settings.section', () => ctx.slots.register({
40
+ name: 'settings.section',
41
+ id: 'subscriptions',
42
+ order: SECTION_ORDER,
43
+ // A thunk re-evaluated per read, so the nav label follows the active locale.
44
+ label: () => t('nav'),
45
+ inject: () => ({ call, t }),
46
+ }, SubscriptionsSection));
47
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Copy dictionaries for the Subscriptions settings page.
3
+ *
4
+ * English is the key-set source of truth; the Chinese dictionary is typed
5
+ * against it, so a key added to one and forgotten in the other is a compile
6
+ * error rather than a silent fallback.
7
+ */
8
+ /** English strings. */
9
+ export declare const en: {
10
+ readonly nav: "Subscriptions";
11
+ readonly intro: "Sign in with a subscription account — Kimi Code, Grok (X Premium) or Google Antigravity. DeepSeek Harness keeps the tokens on this machine and streams every request through the provider's own API.";
12
+ readonly loading: "Checking subscriptions…";
13
+ readonly unavailable: "The subscriptions page needs the web connection service, which this composition does not provide.";
14
+ readonly statusConnected: "Connected · {count} account(s)";
15
+ readonly statusSignedOut: "Not signed in";
16
+ readonly statusBusy: "Waiting for browser approval";
17
+ readonly statusSignIn: "Sign in to add this provider's models to the model picker.";
18
+ readonly statusAuto: "Follows {count} enabled model(s) from every provider";
19
+ readonly connect: "Connect";
20
+ readonly edit: "Edit";
21
+ readonly collapse: "Collapse";
22
+ readonly addAccount: "Add account";
23
+ readonly manage: "Manage";
24
+ readonly cancel: "Cancel";
25
+ readonly close: "Close";
26
+ readonly logout: "Sign out";
27
+ readonly makeDefault: "Use by default";
28
+ readonly defaultBadge: "Default";
29
+ readonly accountNeedsLogin: "Sign in again";
30
+ readonly accountNeedsLoginHint: "The provider refused this account's grant, so its token cannot be renewed";
31
+ readonly accountExpired: "token expired";
32
+ readonly accountExpires: "expires {time}";
33
+ readonly deviceTitle: "Approve this device";
34
+ readonly devicePrompt: "Open the verification page and confirm the code below. This page updates by itself once the provider approves.";
35
+ readonly deviceOpen: "Open verification page";
36
+ readonly deviceCopy: "Copy code";
37
+ readonly deviceCopied: "Copied";
38
+ readonly deviceExpires: "The code expires at {time}.";
39
+ readonly openLogin: "Open sign-in page";
40
+ readonly openLoginHint: "Finish signing in in the browser tab that opened. This page updates by itself once the provider redirects back.";
41
+ readonly modelsTitle: "Models";
42
+ readonly modelsCount: "{count} available";
43
+ readonly modelsLive: "live";
44
+ readonly modelsBuiltIn: "built-in";
45
+ readonly modelsShow: "Show in picker";
46
+ readonly modelsHiddenCount: "· {count} hidden";
47
+ readonly modelsHidden: "Hidden from the model picker";
48
+ readonly modelsEmpty: "No models reported yet.";
49
+ readonly modelsAdd: "Add model";
50
+ readonly modelsAddHint: "Publish a model id this build does not know yet";
51
+ readonly modelsAddPlaceholder: "model id, e.g. k3-next";
52
+ readonly modelsAddConfirm: "Add";
53
+ readonly modelsRemove: "Remove this hand-added model";
54
+ readonly modelsContext: "{tokens} context";
55
+ readonly modelsAuto: "Auto";
56
+ readonly modelsAutoHint: "Pinned first: moves to the next model when one is unavailable";
57
+ readonly modelsAutoOff: "Off — the picker offers the models directly instead";
58
+ readonly modelsAutoChain: "Auto tries these, in this order — drag to re-order";
59
+ readonly modelsDrag: "Drag to re-order (or press ↑ / ↓ here)";
60
+ readonly modelsAutoChainOff: "Take out of Auto";
61
+ readonly modelsAutoChainEmpty: "No model is enabled, so Auto has nothing to try.";
62
+ readonly modelsPinned: "pinned";
63
+ readonly usageTitle: "Plan and usage";
64
+ readonly usagePlan: "Plan: {plan}";
65
+ readonly usageRenews: "renews {time}";
66
+ readonly usageReset: "resets {time}";
67
+ readonly usageRefresh: "Refresh usage";
68
+ readonly usageFetched: "read {time}";
69
+ readonly usageNone: "This provider reports no plan quota.";
70
+ readonly usageError: "Could not read usage: {message}";
71
+ readonly usage_5h: "5-hour window";
72
+ readonly usage_weekly: "Weekly window";
73
+ readonly usage_credits: "Included credit";
74
+ readonly usage_gemini: "Gemini allowance (rolling)";
75
+ readonly usage_gemini_weekly: "Gemini allowance (weekly)";
76
+ readonly usage_claude: "Claude allowance (rolling)";
77
+ readonly usage_claude_weekly: "Claude allowance (weekly)";
78
+ readonly usage_other: "Allowance";
79
+ readonly refresh: "Refresh";
80
+ readonly refreshing: "Refreshing…";
81
+ readonly modelsRefreshed: "Model list refreshed.";
82
+ readonly refreshToken: "Refresh token";
83
+ readonly tokenRefreshed: "Token refreshed; valid until {time}.";
84
+ readonly hint: "Authorization follows the account the browser is signed in with. To add a different account, switch accounts there first, or use a private window.";
85
+ readonly manageTitle: "Manage {provider}";
86
+ readonly manageAccounts: "Accounts";
87
+ readonly reload: "Reload credentials";
88
+ readonly reloadHint: "Use this after signing in from another DeepSeek Harness window.";
89
+ readonly detail_oauthHost: "Authorization server";
90
+ readonly detail_apiBase: "API base";
91
+ readonly detail_credentialFile: "Credential file";
92
+ readonly detail_project: "Cloud project";
93
+ readonly lastError: "Last login attempt failed: {message}";
94
+ readonly loginFailed: "Could not start the sign-in: {message}";
95
+ readonly actionFailed: "Action failed: {message}";
96
+ };
97
+ /** The Subscriptions namespace key union. */
98
+ export type SubscriptionsKey = keyof typeof en;
99
+ /** Chinese strings. */
100
+ export declare const zh: {
101
+ nav: string;
102
+ intro: string;
103
+ loading: string;
104
+ unavailable: string;
105
+ statusConnected: string;
106
+ statusSignedOut: string;
107
+ statusBusy: string;
108
+ statusSignIn: string;
109
+ statusAuto: string;
110
+ connect: string;
111
+ edit: string;
112
+ collapse: string;
113
+ addAccount: string;
114
+ manage: string;
115
+ cancel: string;
116
+ close: string;
117
+ logout: string;
118
+ makeDefault: string;
119
+ defaultBadge: string;
120
+ accountNeedsLogin: string;
121
+ accountNeedsLoginHint: string;
122
+ accountExpired: string;
123
+ accountExpires: string;
124
+ deviceTitle: string;
125
+ devicePrompt: string;
126
+ deviceOpen: string;
127
+ deviceCopy: string;
128
+ deviceCopied: string;
129
+ deviceExpires: string;
130
+ openLogin: string;
131
+ openLoginHint: string;
132
+ modelsTitle: string;
133
+ modelsCount: string;
134
+ modelsLive: string;
135
+ modelsBuiltIn: string;
136
+ modelsShow: string;
137
+ modelsHiddenCount: string;
138
+ modelsHidden: string;
139
+ modelsEmpty: string;
140
+ modelsAdd: string;
141
+ modelsAddHint: string;
142
+ modelsAddPlaceholder: string;
143
+ modelsAddConfirm: string;
144
+ modelsRemove: string;
145
+ modelsContext: string;
146
+ modelsAuto: string;
147
+ modelsAutoHint: string;
148
+ modelsAutoOff: string;
149
+ modelsAutoChain: string;
150
+ modelsDrag: string;
151
+ modelsAutoChainOff: string;
152
+ modelsAutoChainEmpty: string;
153
+ modelsPinned: string;
154
+ usageTitle: string;
155
+ usagePlan: string;
156
+ usageRenews: string;
157
+ usageReset: string;
158
+ usageRefresh: string;
159
+ usageFetched: string;
160
+ usageNone: string;
161
+ usageError: string;
162
+ usage_5h: string;
163
+ usage_weekly: string;
164
+ usage_credits: string;
165
+ usage_gemini: string;
166
+ usage_gemini_weekly: string;
167
+ usage_claude: string;
168
+ usage_claude_weekly: string;
169
+ usage_other: string;
170
+ refresh: string;
171
+ refreshing: string;
172
+ modelsRefreshed: string;
173
+ refreshToken: string;
174
+ tokenRefreshed: string;
175
+ hint: string;
176
+ manageTitle: string;
177
+ manageAccounts: string;
178
+ reload: string;
179
+ reloadHint: string;
180
+ detail_oauthHost: string;
181
+ detail_apiBase: string;
182
+ detail_credentialFile: string;
183
+ detail_project: string;
184
+ lastError: string;
185
+ loginFailed: string;
186
+ actionFailed: string;
187
+ };
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Copy dictionaries for the Subscriptions settings page.
3
+ *
4
+ * English is the key-set source of truth; the Chinese dictionary is typed
5
+ * against it, so a key added to one and forgotten in the other is a compile
6
+ * error rather than a silent fallback.
7
+ */
8
+ /** English strings. */
9
+ export const en = {
10
+ nav: 'Subscriptions',
11
+ intro: 'Sign in with a subscription account — Kimi Code, Grok (X Premium) or Google Antigravity. DeepSeek Harness keeps the tokens on this machine and streams every request through the provider\'s own API.',
12
+ loading: 'Checking subscriptions…',
13
+ unavailable: 'The subscriptions page needs the web connection service, which this composition does not provide.',
14
+ statusConnected: 'Connected · {count} account(s)',
15
+ statusSignedOut: 'Not signed in',
16
+ statusBusy: 'Waiting for browser approval',
17
+ statusSignIn: 'Sign in to add this provider\'s models to the model picker.',
18
+ statusAuto: 'Follows {count} enabled model(s) from every provider',
19
+ connect: 'Connect',
20
+ edit: 'Edit',
21
+ collapse: 'Collapse',
22
+ addAccount: 'Add account',
23
+ manage: 'Manage',
24
+ cancel: 'Cancel',
25
+ close: 'Close',
26
+ logout: 'Sign out',
27
+ makeDefault: 'Use by default',
28
+ defaultBadge: 'Default',
29
+ accountNeedsLogin: 'Sign in again',
30
+ accountNeedsLoginHint: 'The provider refused this account\'s grant, so its token cannot be renewed',
31
+ accountExpired: 'token expired',
32
+ accountExpires: 'expires {time}',
33
+ deviceTitle: 'Approve this device',
34
+ devicePrompt: 'Open the verification page and confirm the code below. This page updates by itself once the provider approves.',
35
+ deviceOpen: 'Open verification page',
36
+ deviceCopy: 'Copy code',
37
+ deviceCopied: 'Copied',
38
+ deviceExpires: 'The code expires at {time}.',
39
+ openLogin: 'Open sign-in page',
40
+ openLoginHint: 'Finish signing in in the browser tab that opened. This page updates by itself once the provider redirects back.',
41
+ modelsTitle: 'Models',
42
+ modelsCount: '{count} available',
43
+ modelsLive: 'live',
44
+ modelsBuiltIn: 'built-in',
45
+ modelsShow: 'Show in picker',
46
+ modelsHiddenCount: '· {count} hidden',
47
+ modelsHidden: 'Hidden from the model picker',
48
+ modelsEmpty: 'No models reported yet.',
49
+ modelsAdd: 'Add model',
50
+ modelsAddHint: 'Publish a model id this build does not know yet',
51
+ modelsAddPlaceholder: 'model id, e.g. k3-next',
52
+ modelsAddConfirm: 'Add',
53
+ modelsRemove: 'Remove this hand-added model',
54
+ modelsContext: '{tokens} context',
55
+ modelsAuto: 'Auto',
56
+ modelsAutoHint: 'Pinned first: moves to the next model when one is unavailable',
57
+ modelsAutoOff: 'Off — the picker offers the models directly instead',
58
+ modelsAutoChain: 'Auto tries these, in this order — drag to re-order',
59
+ modelsDrag: 'Drag to re-order (or press ↑ / ↓ here)',
60
+ modelsAutoChainOff: 'Take out of Auto',
61
+ modelsAutoChainEmpty: 'No model is enabled, so Auto has nothing to try.',
62
+ modelsPinned: 'pinned',
63
+ usageTitle: 'Plan and usage',
64
+ usagePlan: 'Plan: {plan}',
65
+ usageRenews: 'renews {time}',
66
+ usageReset: 'resets {time}',
67
+ usageRefresh: 'Refresh usage',
68
+ usageFetched: 'read {time}',
69
+ usageNone: 'This provider reports no plan quota.',
70
+ usageError: 'Could not read usage: {message}',
71
+ usage_5h: '5-hour window',
72
+ usage_weekly: 'Weekly window',
73
+ usage_credits: 'Included credit',
74
+ usage_gemini: 'Gemini allowance (rolling)',
75
+ usage_gemini_weekly: 'Gemini allowance (weekly)',
76
+ usage_claude: 'Claude allowance (rolling)',
77
+ usage_claude_weekly: 'Claude allowance (weekly)',
78
+ usage_other: 'Allowance',
79
+ refresh: 'Refresh',
80
+ refreshing: 'Refreshing…',
81
+ modelsRefreshed: 'Model list refreshed.',
82
+ refreshToken: 'Refresh token',
83
+ tokenRefreshed: 'Token refreshed; valid until {time}.',
84
+ hint: 'Authorization follows the account the browser is signed in with. To add a different account, switch accounts there first, or use a private window.',
85
+ manageTitle: 'Manage {provider}',
86
+ manageAccounts: 'Accounts',
87
+ reload: 'Reload credentials',
88
+ reloadHint: 'Use this after signing in from another DeepSeek Harness window.',
89
+ detail_oauthHost: 'Authorization server',
90
+ detail_apiBase: 'API base',
91
+ detail_credentialFile: 'Credential file',
92
+ detail_project: 'Cloud project',
93
+ lastError: 'Last login attempt failed: {message}',
94
+ loginFailed: 'Could not start the sign-in: {message}',
95
+ actionFailed: 'Action failed: {message}',
96
+ };
97
+ /** Chinese strings. */
98
+ export const zh = {
99
+ nav: '订阅',
100
+ intro: '使用订阅账号登录 —— Kimi Code、Grok (X Premium) 或 Google Antigravity。DeepSeek Harness 将令牌保存在本机,并通过各服务自己的 API 发起请求。',
101
+ loading: '正在检查订阅…',
102
+ unavailable: '订阅页面需要 Web 连接服务,当前组合未提供该服务。',
103
+ statusConnected: '已连接 {count} 个账号',
104
+ statusSignedOut: '未登录',
105
+ statusBusy: '等待浏览器确认',
106
+ statusSignIn: '登录后即可在模型选择器中使用该服务的模型。',
107
+ statusAuto: '依次使用来自各服务的 {count} 个已启用模型',
108
+ connect: '连接',
109
+ edit: '编辑',
110
+ collapse: '收起',
111
+ addAccount: '添加账号',
112
+ manage: '管理',
113
+ cancel: '取消',
114
+ close: '关闭',
115
+ logout: '退出登录',
116
+ makeDefault: '设为默认',
117
+ defaultBadge: '默认',
118
+ accountNeedsLogin: '需重新登录',
119
+ accountNeedsLoginHint: '服务方已拒绝该账号的授权,令牌无法自动续期',
120
+ accountExpired: '令牌已过期',
121
+ accountExpires: '过期时间 {time}',
122
+ deviceTitle: '确认此设备',
123
+ devicePrompt: '打开验证页面并确认下方代码,服务确认后本页面会自动更新。',
124
+ deviceOpen: '打开验证页面',
125
+ deviceCopy: '复制代码',
126
+ deviceCopied: '已复制',
127
+ deviceExpires: '代码将于 {time} 过期。',
128
+ openLogin: '打开登录页面',
129
+ openLoginHint: '请在打开的浏览器标签页中完成登录;服务回调后本页面会自动更新。',
130
+ modelsTitle: '模型',
131
+ modelsCount: '共 {count} 个',
132
+ modelsLive: '实时',
133
+ modelsBuiltIn: '内置',
134
+ modelsShow: '在选择器中显示',
135
+ modelsHiddenCount: '· 已隐藏 {count} 个',
136
+ modelsHidden: '已从模型选择器隐藏',
137
+ modelsEmpty: '暂未获取到模型。',
138
+ modelsAdd: '添加模型',
139
+ modelsAddHint: '手动添加一个本版本还不认识的模型 ID',
140
+ modelsAddPlaceholder: '模型 ID,例如 k3-next',
141
+ modelsAddConfirm: '添加',
142
+ modelsRemove: '移除这个手动添加的模型',
143
+ modelsContext: '{tokens} 上下文',
144
+ modelsAuto: '自动',
145
+ modelsAutoHint: '固定在首位:某个模型不可用时自动改用下一个',
146
+ modelsAutoOff: '已关闭 —— 选择器将直接列出各个模型',
147
+ modelsAutoChain: '自动会按这个顺序依次尝试(拖动可调整)',
148
+ modelsDrag: '拖动调整顺序(也可在此按 ↑ / ↓)',
149
+ modelsAutoChainOff: '从自动中移除',
150
+ modelsAutoChainEmpty: '没有启用任何模型,自动没有可尝试的模型。',
151
+ modelsPinned: '固定',
152
+ usageTitle: '套餐与额度',
153
+ usagePlan: '套餐:{plan}',
154
+ usageRenews: '续费时间 {time}',
155
+ usageReset: '重置时间 {time}',
156
+ usageRefresh: '刷新额度',
157
+ usageFetched: '读取于 {time}',
158
+ usageNone: '该服务未提供套餐额度信息。',
159
+ usageError: '额度读取失败:{message}',
160
+ usage_5h: '5 小时窗口',
161
+ usage_weekly: '每周窗口',
162
+ usage_credits: '包含额度',
163
+ usage_gemini: 'Gemini 模型额度(滚动)',
164
+ usage_gemini_weekly: 'Gemini 模型额度(每周)',
165
+ usage_claude: 'Claude 模型额度(滚动)',
166
+ usage_claude_weekly: 'Claude 模型额度(每周)',
167
+ usage_other: '额度',
168
+ refresh: '刷新',
169
+ refreshing: '正在刷新…',
170
+ modelsRefreshed: '模型列表已刷新。',
171
+ refreshToken: '刷新令牌',
172
+ tokenRefreshed: '令牌已刷新,有效至 {time}。',
173
+ hint: '授权以浏览器当前登录的账号为准;要添加不同账号,请先在浏览器里切换账号,或使用无痕窗口。',
174
+ manageTitle: '管理 {provider}',
175
+ manageAccounts: '账号',
176
+ reload: '重新读取凭据',
177
+ reloadHint: '在另一个 DeepSeek Harness 窗口中登录后,请使用此操作。',
178
+ detail_oauthHost: '授权服务器',
179
+ detail_apiBase: 'API 地址',
180
+ detail_credentialFile: '凭据文件',
181
+ detail_project: '云项目',
182
+ lastError: '上次登录失败:{message}',
183
+ loginFailed: '无法开始登录:{message}',
184
+ actionFailed: '操作失败:{message}',
185
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Scoped stylesheet for the Subscriptions page and its manage dialog.
3
+ *
4
+ * The host loads plugin markup without its own control classes, and a bare
5
+ * `<button>` therefore renders with the browser's default raised chrome — which
6
+ * reads as a stray highlight in a dark theme. Rather than invent a look, this
7
+ * follows the control vocabulary of the sibling `dsh-plugin-subscriptions`
8
+ * plugin (same author-facing design as the shell's settings forms): a 6 px
9
+ * radius small control, a transparent fill, a hairline border from the theme's
10
+ * alias tokens, and the theme's hover/active/focus tokens for state.
11
+ *
12
+ * The tokens all carry fallbacks, so the page still renders correctly on a host
13
+ * build that does not define them.
14
+ *
15
+ * @module dsh-plugin-subscription-oauth/client/styles
16
+ */
17
+ /** The page's and dialog's stylesheet. */
18
+ export declare const subscriptionsCss = "\n.dsh-subscriptions-settings,\n.dsh-subscription-manager {\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n /* Native controls (checkbox, dialog) follow the host theme, not the OS. */\n color-scheme: light;\n}\nbody[data-ds-dark-theme] :is(.dsh-subscriptions-settings, .dsh-subscription-manager) {\n color-scheme: dark;\n}\n.dsh-subscription-manager {\n box-sizing: border-box;\n padding: 0;\n border: 0;\n border-radius: var(--dsw-radius-panel, 16px);\n background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));\n color: var(--dsw-alias-label-primary);\n box-shadow: var(--dsw-elevation-prominent, 0 20px 70px #0004);\n}\n.dsh-subscription-manager::backdrop {\n background: var(--dsw-alias-bg-mask-1, #0006);\n backdrop-filter: var(--dsw-mask-blur, none);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) h2 {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) strong,\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-label {\n font-size: 13px;\n line-height: 1.5;\n font-weight: 500;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) small,\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-hint,\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) [role=\"status\"] {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-error {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary, #b42318);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-success {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-success-primary, #067647);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) label:has(> input[type=\"checkbox\"]) {\n cursor: pointer;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"] {\n accent-color: var(--dsw-alias-brand-primary);\n}\n/*\n * A model's on/off control is a switch, not a checkbox: it takes effect\n * immediately and its state is what matters, not a tick. Drawn from the theme\n * tokens with appearance: none, so it follows the host palette in both themes\n * instead of the platform's checkbox chrome.\n */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"].dsh-subscription-switch {\n appearance: none;\n -webkit-appearance: none;\n position: relative;\n box-sizing: border-box;\n flex-shrink: 0;\n width: 34px;\n height: 20px;\n margin: 0;\n border: 0.5px solid var(--dsw-alias-border-l3, var(--dsw-alias-border-l2));\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-2));\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"].dsh-subscription-switch::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--dsw-alias-label-primary-foreground, #fff);\n box-shadow: 0 1px 2px #0003;\n transition: transform 120ms ease;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"].dsh-subscription-switch:checked {\n border-color: transparent;\n background: var(--dsw-alias-state-success-primary, var(--dsw-alias-brand-primary, #067647));\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"].dsh-subscription-switch:checked::after {\n transform: translateX(14px);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"].dsh-subscription-switch:disabled {\n opacity: 0.4;\n cursor: default;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n min-height: 28px;\n padding: 0 10px;\n border: 0.5px solid var(--dsw-alias-border-l3, var(--dsw-alias-border-l2));\n border-radius: var(--dsw-radius-sm, 6px);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-alias-bg-layer-3));\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button:active:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-active, var(--dsw-alias-bg-layer-3));\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button:disabled {\n opacity: 0.4;\n cursor: default;\n}\n/* A control that is present but should not read as a bordered button. */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button.dsh-subscription-quiet {\n min-height: 22px;\n padding: 0 4px;\n border-color: transparent;\n color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-primary));\n}\n/* The free-text field for a hand-added model id. */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input.dsh-subscription-input {\n box-sizing: border-box;\n flex: 1 1 auto;\n min-width: 0;\n min-height: 28px;\n padding: 0 10px;\n border: 0.5px solid var(--dsw-alias-border-l3, var(--dsw-alias-border-l2));\n border-radius: var(--dsw-radius-sm, 6px);\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input.dsh-subscription-input::placeholder {\n color: var(--dsw-alias-label-tertiary);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input.dsh-subscription-input:focus-visible {\n outline: var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n outline-offset: 2px;\n}\n/* A drag handle: no border or fill, so it reads as a grip rather than a button. */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button.dsh-subscription-handle {\n min-height: 18px;\n height: 18px;\n padding: 0 2px;\n border-color: transparent;\n border-radius: var(--dsw-radius-sm, 6px);\n background: transparent;\n color: var(--dsw-alias-label-tertiary, var(--dsw-alias-label-secondary));\n font-size: 12px;\n line-height: 18px;\n cursor: grab;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button.dsh-subscription-handle:hover:not(:disabled) {\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button.dsh-subscription-handle:active:not(:disabled) { cursor: grabbing; }\n/* Controls inside the manage dialog are one step larger, like a form footer. */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-dialog-actions button {\n min-height: 34px;\n padding: 0 14px;\n border-radius: var(--dsw-radius-md, 8px);\n font-size: 13px;\n line-height: 1.5;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button.dsh-subscription-primary {\n border-color: transparent;\n background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-label-primary));\n color: var(--dsw-alias-label-primary-foreground, var(--dsw-alias-bg-layer-1));\n font-weight: 500;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button.dsh-subscription-primary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover, var(--dsw-alias-label-secondary));\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) button:focus-visible,\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) input[type=\"checkbox\"]:focus-visible,\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-disclosure:focus-visible {\n outline: var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n outline-offset: 2px;\n}\n/* The catalog heading is a summary-style disclosure, not a bordered button. */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-disclosure {\n border-color: transparent;\n border-radius: var(--dsw-radius-sm, 6px);\n background: transparent;\n padding: 0 4px;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-primary));\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-disclosure:hover:not(:disabled) {\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n/* A usage meter: the track, with the fill sized by the caller. */\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-meter {\n height: 6px;\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-2));\n overflow: hidden;\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-meter > span {\n display: block;\n height: 100%;\n background: var(--dsw-alias-state-success-primary, #067647);\n}\n:is(.dsh-subscriptions-settings, .dsh-subscription-manager) .dsh-subscription-meter > span[data-exhausted=\"true\"] {\n background: var(--dsw-alias-state-error-primary, #b42318);\n}\n";