@eduwork/dsh-oidc 0.3.0-dev.1 → 0.3.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 (59) hide show
  1. package/CHANGELOG.en.md +12 -0
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +9 -1
  4. package/README_EN.md +9 -1
  5. package/THIRD_PARTY_NOTICES.en.md +5 -4
  6. package/THIRD_PARTY_NOTICES.md +5 -5
  7. package/docs/account-extensions.en.md +7 -1
  8. package/docs/account-extensions.md +7 -1
  9. package/docs/compatibility.en.md +3 -1
  10. package/docs/compatibility.md +3 -1
  11. package/docs/development.en.md +1 -1
  12. package/docs/development.md +1 -1
  13. package/docs/dsh-integration.en.md +3 -3
  14. package/docs/dsh-integration.md +3 -3
  15. package/docs/enterprise-profile.en.md +49 -2
  16. package/docs/enterprise-profile.md +49 -2
  17. package/docs/gateway-auth/README.md +7 -6
  18. package/docs/gateway-auth/README_EN.md +7 -6
  19. package/docs/gateway-auth/experimental-oidc-llm.en.md +10 -8
  20. package/docs/gateway-auth/experimental-oidc-llm.md +9 -7
  21. package/docs/gateway-auth/litellm-setup.en.md +10 -4
  22. package/docs/gateway-auth/litellm-setup.md +10 -4
  23. package/docs/gateway-auth/oidc-llm-draft.en.md +89 -63
  24. package/docs/gateway-auth/oidc-llm-draft.md +86 -60
  25. package/docs/getting-started.en.md +3 -1
  26. package/docs/getting-started.md +3 -1
  27. package/docs/key-binding-protocol.en.md +1 -1
  28. package/docs/key-binding-protocol.md +1 -1
  29. package/docs/oidc-interoperability.en.md +1 -1
  30. package/docs/oidc-interoperability.md +1 -1
  31. package/docs/open-integration.en.md +3 -1
  32. package/docs/open-integration.md +3 -1
  33. package/examples/ecnu.enterprise-profile.example.json +4 -1
  34. package/examples/enterprise-profile.example.json +4 -1
  35. package/examples/identity-only.example.json +7 -2
  36. package/examples/litellm.enterprise-profile.example.json +9 -0
  37. package/examples/oidc-llm.enterprise-profile.example.json +33 -0
  38. package/examples/resources-discovery.example.json +9 -2
  39. package/lib/callback-page.js +9 -4
  40. package/lib/client.js +460 -360
  41. package/lib/desktop-oidc.js +2 -2
  42. package/lib/gateway-backend.js +20 -5
  43. package/lib/index.js +8 -6
  44. package/lib/litellm-protocol.js +4 -3
  45. package/lib/model-types.js +7 -0
  46. package/lib/oidc-llm-protocol.js +8 -5
  47. package/lib/oidc.js +22 -28
  48. package/lib/profile.js +36 -47
  49. package/lib/provider/authorization-scope.js +4 -0
  50. package/lib/provider/core.js +8 -19
  51. package/lib/provider/index.js +18 -2
  52. package/lib/provider/transform-adapter.js +4 -0
  53. package/lib/resources.js +12 -4
  54. package/lib/token-lifetime.js +15 -0
  55. package/lib/transport.js +5 -0
  56. package/lib/typert-schemas.js +14 -12
  57. package/package.json +104 -97
  58. package/protocol/resources.openapi.yaml +11 -3
  59. package/schema/enterprise-profile.v1alpha1.schema.json +40 -5
package/lib/client.js CHANGED
@@ -29,8 +29,272 @@ window.__ModuleLoader__.load({
29
29
  let react = require("react");
30
30
  react = __toESM(react, 1);
31
31
  let react_dom = require("react-dom");
32
+ //#region src/client/locale.ts
33
+ const NS = "eduwork.oidc";
34
+ const dictionaries = {
35
+ "zh": {
36
+ "account.waiting": "请在浏览器中完成登录…",
37
+ "account.cancelLogin": "取消登录",
38
+ "account.identityDescription": "使用组织账号登录。模型服务可在设置中单独配置。",
39
+ "account.identityConnected": "组织身份已登录",
40
+ "account.unavailable": "企业模型服务暂时不可用",
41
+ "account.connected": "已连接",
42
+ "account.disconnected": "尚未连接",
43
+ "account.description": "使用组织统一身份认证连接企业模型。密码不会进入本应用;模型请求使用登录授权。",
44
+ "account.connecting": "正在连接…",
45
+ "account.login": "使用企业账号登录",
46
+ "account.checking": "正在检查…",
47
+ "account.check": "检查连接",
48
+ "account.logout": "退出登录",
49
+ "account.help": "帮助",
50
+ "account.dialog": "连接企业模型",
51
+ "account.shortDescription": "通过组织统一身份认证连接企业模型;密码不会进入本应用。",
52
+ "account.other": "使用其他模型",
53
+ "account.enabled": "完成后将启用",
54
+ "account.footerConnected": "企业模型已连接",
55
+ "account.footerSetup": "点击设置完成登录",
56
+ "account.useModels": "使用企业模型",
57
+ "managed.waiting": "请在浏览器中完成登录…",
58
+ "managed.cancelLogin": "取消登录",
59
+ "managed.title": "学校 / 企业服务",
60
+ "managed.description": "已验证机构和兼容协议服务使用统一入口管理;普通 API Key 提供方继续在模型设置中管理。",
61
+ "managed.loading": "正在读取学校 / 企业服务…",
62
+ "managed.add": "+ 添加学校 / 企业服务",
63
+ "managed.verified": "已验证机构",
64
+ "managed.custom": "自定义服务",
65
+ "managed.connected": "已连接",
66
+ "managed.enabled": "已启用",
67
+ "managed.disabled": "未启用",
68
+ "managed.configure": "配置",
69
+ "managed.enable": "启用并重载",
70
+ "managed.login": "登录",
71
+ "managed.refresh": "刷新状态",
72
+ "managed.processing": "处理中…",
73
+ "managed.profileManaged": "Enterprise Profile 管理",
74
+ "managed.addTitle": "添加学校 / 企业服务",
75
+ "managed.addDescription": "选择已验证机构,或填写一个兼容协议 Base URL。",
76
+ "managed.addVerified": "添加",
77
+ "managed.compatible": "连接兼容协议服务",
78
+ "managed.compatibleHint": "默认从服务端发现登录、模型和能力。若元数据不完整,添加后可手动补充模型目录。",
79
+ "managed.saveService": "保存服务",
80
+ "managed.saving": "保存中…",
81
+ "managed.providerID": "Provider ID",
82
+ "managed.modelCatalog": "模型目录",
83
+ "managed.defaultContext": "默认上下文",
84
+ "managed.defaultOutput": "默认最大输出",
85
+ "managed.unspecified": "未声明",
86
+ "managed.modelCapability": "模型能力",
87
+ "managed.readonlyModels": "该机构的模型参数由 Enterprise Profile 或发行目录管理,只读。",
88
+ "managed.customModels": "默认自动发现;仅在服务端元数据不完整时使用手动模式。",
89
+ "managed.automatic": "自动发现",
90
+ "managed.manual": "手动配置",
91
+ "managed.baseModel": "基础模型",
92
+ "managed.context": "上下文",
93
+ "managed.output": "最大输出",
94
+ "managed.input": "输入",
95
+ "managed.reasoning": "思考强度",
96
+ "managed.decidedByService": "由服务决定",
97
+ "managed.unsupported": "暂不支持",
98
+ "managed.noModels": "尚未同步模型目录。完成机构登录后会自动读取,也可使用手动配置补充。",
99
+ "managed.model": "模型",
100
+ "managed.remove": "删除",
101
+ "managed.modelID": "模型 ID *",
102
+ "managed.displayName": "显示名称",
103
+ "managed.baseModelID": "基础模型 ID",
104
+ "managed.contextWindow": "上下文窗口",
105
+ "managed.maxOutput": "最大输出",
106
+ "managed.modalities": "输入模态",
107
+ "managed.reasoningLevels": "思考强度",
108
+ "managed.defaultReasoning": "默认思考强度",
109
+ "managed.supportsReasoning": "支持思考",
110
+ "managed.addModel": "+ 添加模型",
111
+ "managed.cancel": "取消",
112
+ "managed.saveModels": "保存模型配置",
113
+ "managed.close": "关闭",
114
+ "managed.editAddress": "企业服务地址",
115
+ "managed.editAddressHint": "修改地址会清除与旧服务绑定的本地登录状态;当前已启用时还需要重载 Runtime。",
116
+ "managed.save": "保存修改",
117
+ "managed.removeService": "移除服务",
118
+ "managed.deleteService": "删除服务",
119
+ "managed.confirmRemove": "确认从当前配置中移除?以后仍可重新添加。",
120
+ "managed.confirmDelete": "确认永久删除这项本地配置?",
121
+ "managed.confirm": "确认删除",
122
+ "managed.disable": "停用并重载",
123
+ "managed.restartNotice": "机构配置已保存。重启后会加载对应的 Provider、品牌和本地能力组合。",
124
+ "managed.restart": "立即重启应用",
125
+ "managed.emptyTitle": "尚未配置学校 / 企业服务",
126
+ "managed.emptyHint": "添加只保存配置;需要使用时再显式启用。全局同时只会启用一个企业服务。",
127
+ "managed.profileNotice": "应用从受信 Enterprise Profile 读取机构与模型目录;如需修改,请更新 Profile 后重启应用。",
128
+ "managed.fileHint": "通过配置文件连接学校或企业服务。修改后退出应用,再重新启动。",
129
+ "managed.openConfig": "打开配置文件",
130
+ "managed.openExamples": "查看示例",
131
+ "managed.configOpened": "已请求系统打开配置文件,修改后请退出并重新启动应用。",
132
+ "managed.examplesOpened": "已请求系统打开示例目录。",
133
+ "managed.fileFallback": "请在运行应用的电脑上打开:",
134
+ "managed.examplesHint": "完整示例见同目录下的 examples 文件夹。",
135
+ "managed.sourcePreset": "内置审核目录",
136
+ "managed.sourceDiscovered": "服务端自动发现",
137
+ "managed.sourcePending": "等待服务端同步",
138
+ "managed.sourceManual": "本机手动配置",
139
+ "managed.sourceProvider": "提供方声明",
140
+ "managed.effortOff": "关闭",
141
+ "managed.effortMinimal": "极低",
142
+ "managed.effortLow": "低",
143
+ "managed.effortMedium": "中",
144
+ "managed.effortHigh": "高",
145
+ "managed.effortExtraHigh": "极高",
146
+ "managed.modalityText": "文本",
147
+ "managed.modalityImage": "图片",
148
+ "managed.modalityAudio": "音频",
149
+ "managed.modalityVideo": "视频",
150
+ "managed.fileModelsHint": "尚未同步模型目录。登录后将读取服务端模型;也可在配置文件中声明模型目录。",
151
+ "managed.identityOnly": "身份登录 · 模型可自行配置",
152
+ "managed.configurationFile": "配置文件",
153
+ "managed.viewDetails": "查看详情",
154
+ "managed.fileEmptyHint": "参考上方示例,在配置文件的 organizations 中填写企业信息,保存并退出后重新启动。也可以直接在模型设置中使用自己的 API Key。",
155
+ "managed.multimodal": "多模态",
156
+ "menu.menu": "账户菜单",
157
+ "menu.check": "刷新账户",
158
+ "menu.logout": "退出登录",
159
+ "menu.login": "登录账户",
160
+ "menu.waiting": "请在浏览器中完成登录…",
161
+ "menu.cancel": "取消登录",
162
+ "menu.processing": "正在处理…"
163
+ },
164
+ "en": {
165
+ "account.waiting": "Complete sign-in in your browser…",
166
+ "account.cancelLogin": "Cancel sign-in",
167
+ "account.identityDescription": "Sign in with your organization account. Configure model services separately in settings.",
168
+ "account.identityConnected": "Organization identity connected",
169
+ "account.unavailable": "Enterprise model service is temporarily unavailable",
170
+ "account.connected": "Connected",
171
+ "account.disconnected": "Not connected",
172
+ "account.description": "Connect with your organization account. Your password never enters the app; model requests use your sign-in authorization.",
173
+ "account.connecting": "Connecting…",
174
+ "account.login": "Sign in with organization",
175
+ "account.checking": "Checking…",
176
+ "account.check": "Check connection",
177
+ "account.logout": "Sign out",
178
+ "account.help": "Help",
179
+ "account.dialog": "Connect enterprise models",
180
+ "account.shortDescription": "Connect enterprise models through your organization identity provider. Your password never enters the app.",
181
+ "account.other": "Use another model",
182
+ "account.enabled": "This enables",
183
+ "account.footerConnected": "Enterprise models connected",
184
+ "account.footerSetup": "Open settings to connect",
185
+ "account.useModels": "Use organization model",
186
+ "managed.waiting": "Complete sign-in in your browser…",
187
+ "managed.cancelLogin": "Cancel sign-in",
188
+ "managed.title": "Organization services",
189
+ "managed.description": "Manage verified organizations and compatible enterprise services here; ordinary API-key providers remain in model settings.",
190
+ "managed.loading": "Loading organization services…",
191
+ "managed.add": "+ Add organization service",
192
+ "managed.verified": "Verified organization",
193
+ "managed.custom": "Custom service",
194
+ "managed.connected": "Connected",
195
+ "managed.enabled": "Enabled",
196
+ "managed.disabled": "Disabled",
197
+ "managed.configure": "Configure",
198
+ "managed.enable": "Enable and reload",
199
+ "managed.login": "Sign in",
200
+ "managed.refresh": "Refresh",
201
+ "managed.processing": "Working…",
202
+ "managed.profileManaged": "Enterprise Profile managed",
203
+ "managed.addTitle": "Add organization service",
204
+ "managed.addDescription": "Select a verified organization or enter a compatible protocol Base URL.",
205
+ "managed.addVerified": "Add",
206
+ "managed.compatible": "Connect a compatible service",
207
+ "managed.compatibleHint": "Login, models, and capabilities are discovered by default. A model catalog can be supplied manually when metadata is incomplete.",
208
+ "managed.saveService": "Save service",
209
+ "managed.saving": "Saving…",
210
+ "managed.providerID": "Provider ID",
211
+ "managed.modelCatalog": "Model catalog",
212
+ "managed.defaultContext": "Default context",
213
+ "managed.defaultOutput": "Default output",
214
+ "managed.unspecified": "Unspecified",
215
+ "managed.modelCapability": "Model capabilities",
216
+ "managed.readonlyModels": "This catalog is read-only and managed by the Enterprise Profile or distribution.",
217
+ "managed.customModels": "Automatic discovery is preferred; use manual mode only when server metadata is incomplete.",
218
+ "managed.automatic": "Automatic discovery",
219
+ "managed.manual": "Manual configuration",
220
+ "managed.baseModel": "Base model",
221
+ "managed.context": "Context",
222
+ "managed.output": "Max output",
223
+ "managed.input": "Input",
224
+ "managed.reasoning": "Reasoning effort",
225
+ "managed.decidedByService": "Service default",
226
+ "managed.unsupported": "Unsupported",
227
+ "managed.noModels": "No model catalog is available yet. Sign in to discover models or configure them manually.",
228
+ "managed.model": "Model",
229
+ "managed.remove": "Remove",
230
+ "managed.modelID": "Model ID *",
231
+ "managed.displayName": "Display name",
232
+ "managed.baseModelID": "Base model ID",
233
+ "managed.contextWindow": "Context window",
234
+ "managed.maxOutput": "Max output",
235
+ "managed.modalities": "Input modalities",
236
+ "managed.reasoningLevels": "Reasoning effort",
237
+ "managed.defaultReasoning": "Default reasoning effort",
238
+ "managed.supportsReasoning": "Supports reasoning",
239
+ "managed.addModel": "+ Add model",
240
+ "managed.cancel": "Cancel",
241
+ "managed.saveModels": "Save models",
242
+ "managed.close": "Close",
243
+ "managed.editAddress": "Service address",
244
+ "managed.editAddressHint": "Changing the address clears the old local login binding and requires a Runtime reload when active.",
245
+ "managed.save": "Save",
246
+ "managed.removeService": "Remove service",
247
+ "managed.deleteService": "Delete service",
248
+ "managed.confirmRemove": "Remove this service from the current configuration?",
249
+ "managed.confirmDelete": "Permanently delete this local configuration?",
250
+ "managed.confirm": "Confirm",
251
+ "managed.disable": "Disable and reload",
252
+ "managed.restartNotice": "Configuration was saved. Reload to apply the Provider, brand, and local capabilities.",
253
+ "managed.restart": "Restart now",
254
+ "managed.emptyTitle": "No organization service configured",
255
+ "managed.emptyHint": "Adding a service only saves its configuration. Enable one explicitly when needed; only one service is active at a time.",
256
+ "managed.profileNotice": "The app reads organizations and models from a trusted Enterprise Profile. Update the Profile and restart the app to change them.",
257
+ "managed.fileHint": "Connect an organization through the configuration file. Quit and relaunch after editing.",
258
+ "managed.openConfig": "Open configuration file",
259
+ "managed.openExamples": "View examples",
260
+ "managed.configOpened": "The file was sent to your system editor. Quit and relaunch after editing.",
261
+ "managed.examplesOpened": "The examples folder was sent to your system file manager.",
262
+ "managed.fileFallback": "Open this file on the computer running the app: ",
263
+ "managed.examplesHint": "Complete examples are in the examples folder beside it.",
264
+ "managed.sourcePreset": "Reviewed catalog",
265
+ "managed.sourceDiscovered": "Server discovery",
266
+ "managed.sourcePending": "Awaiting discovery",
267
+ "managed.sourceManual": "Local manual catalog",
268
+ "managed.sourceProvider": "Provider declaration",
269
+ "managed.effortOff": "Off",
270
+ "managed.effortMinimal": "Minimal",
271
+ "managed.effortLow": "Low",
272
+ "managed.effortMedium": "Medium",
273
+ "managed.effortHigh": "High",
274
+ "managed.effortExtraHigh": "Extra high",
275
+ "managed.modalityText": "Text",
276
+ "managed.modalityImage": "Image",
277
+ "managed.modalityAudio": "Audio",
278
+ "managed.modalityVideo": "Video",
279
+ "managed.fileModelsHint": "No model catalog has been synced. Sign in to discover models, or declare them in the configuration file.",
280
+ "managed.identityOnly": "Identity sign-in · configure your own models",
281
+ "managed.configurationFile": "Configuration file",
282
+ "managed.viewDetails": "View details",
283
+ "managed.fileEmptyHint": "Use the examples above to fill in organizations, save, quit and relaunch. You can also use your own API key in model settings.",
284
+ "managed.multimodal": "Multimodal",
285
+ "menu.menu": "Account menu",
286
+ "menu.check": "Refresh account",
287
+ "menu.logout": "Sign out",
288
+ "menu.login": "Sign in",
289
+ "menu.waiting": "Complete sign-in in your browser…",
290
+ "menu.cancel": "Cancel sign-in",
291
+ "menu.processing": "Working…"
292
+ }
293
+ };
294
+ //#endregion
32
295
  //#region node_modules/zod/v4/core/core.js
33
296
  var _a$1;
297
+ /* @__NO_SIDE_EFFECTS__ */
34
298
  function $constructor(name, initializer, params) {
35
299
  function init(inst, def) {
36
300
  if (!inst._zod) Object.defineProperty(inst, "_zod", {
@@ -419,8 +683,8 @@ window.__ModuleLoader__.load({
419
683
  enumerable: false
420
684
  });
421
685
  };
422
- const $ZodError = $constructor("$ZodError", initializer$1);
423
- const $ZodRealError = $constructor("$ZodError", initializer$1, { Parent: Error });
686
+ const $ZodError = /* @__PURE__ */ $constructor("$ZodError", initializer$1);
687
+ const $ZodRealError = /* @__PURE__ */ $constructor("$ZodError", initializer$1, { Parent: Error });
424
688
  function flattenError(error, mapper = (issue) => issue.message) {
425
689
  const fieldErrors = {};
426
690
  const formErrors = [];
@@ -4243,6 +4507,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4243
4507
  return /* @__PURE__ */ _superRefine(fn, params);
4244
4508
  }
4245
4509
  //#endregion
4510
+ //#region src/host/model-types.js
4511
+ const MODEL_TYPES = Object.freeze([
4512
+ "llm",
4513
+ "embedding",
4514
+ "rerank",
4515
+ "image",
4516
+ "tts",
4517
+ "unknown"
4518
+ ]);
4519
+ //#endregion
4246
4520
  //#region src/host/typert-schemas.js
4247
4521
  const pkg$1 = "@eduwork/dsh-oidc";
4248
4522
  const profileIdSchema = string().min(1).max(64);
@@ -4253,11 +4527,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4253
4527
  const configurationTargetSchema = _enum(["config", "examples"]);
4254
4528
  const openConfigurationResult = Object.freeze({
4255
4529
  mode: "strict",
4530
+ create() {
4531
+ return this.schema;
4532
+ },
4256
4533
  typeSymbol: `${pkg$1}#OpenConfigurationResult`,
4257
4534
  schema: object({ opened: literal(true) }).strict()
4258
4535
  });
4259
4536
  const enterpriseSelectionResult = Object.freeze({
4260
4537
  mode: "strict",
4538
+ create() {
4539
+ return this.schema;
4540
+ },
4261
4541
  typeSymbol: `${pkg$1}#EnterpriseSelectionResult`,
4262
4542
  schema: object({
4263
4543
  changed: boolean(),
@@ -4277,7 +4557,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4277
4557
  primaryColor: string().optional(),
4278
4558
  loginTitle: string().optional(),
4279
4559
  loginDescription: string().optional(),
4280
- supportURL: string().optional()
4560
+ loginButtonLabel: string().min(1).max(40).optional(),
4561
+ supportURL: string().optional(),
4562
+ language: _enum([
4563
+ "auto",
4564
+ "zh-CN",
4565
+ "en"
4566
+ ]).optional()
4281
4567
  }).strict();
4282
4568
  const publicProfileSchema = object({
4283
4569
  id: string(),
@@ -4308,7 +4594,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4308
4594
  credentialState: string().optional(),
4309
4595
  capabilities: array(string()).optional()
4310
4596
  }).strict();
4311
- const runtimeModelsSchema = array(object({
4597
+ const runtimeModelSchema = object({
4312
4598
  id: string().min(1).max(256),
4313
4599
  name: string().max(256).optional(),
4314
4600
  upstreamModelID: string().max(256).optional(),
@@ -4332,14 +4618,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4332
4618
  "max"
4333
4619
  ]).optional(),
4334
4620
  compat: record(string(), unknown()).optional()
4335
- }).strict()).max(128);
4621
+ }).strict();
4622
+ const runtimeModelsSchema = array(runtimeModelSchema).max(128);
4623
+ const resourceModelSchema = runtimeModelSchema.extend({ type: _enum(MODEL_TYPES) });
4336
4624
  const resourcesResult = Object.freeze({
4337
4625
  mode: "strict",
4626
+ create() {
4627
+ return this.schema;
4628
+ },
4338
4629
  typeSymbol: `${pkg$1}#Resources`,
4339
4630
  schema: object({
4340
4631
  profileID: string(),
4341
4632
  modelSource: string(),
4342
- models: runtimeModelsSchema,
4633
+ models: array(resourceModelSchema).max(128),
4343
4634
  issues: array(string())
4344
4635
  }).strict()
4345
4636
  });
@@ -4364,6 +4655,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4364
4655
  }).strict();
4365
4656
  const configurationResult = Object.freeze({
4366
4657
  mode: "strict",
4658
+ create() {
4659
+ return this.schema;
4660
+ },
4367
4661
  typeSymbol: `${pkg$1}#Configuration`,
4368
4662
  schema: object({
4369
4663
  schemaVersion: literal("dsh-oidc/v1alpha1"),
@@ -4383,6 +4677,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4383
4677
  });
4384
4678
  const managementResult = Object.freeze({
4385
4679
  mode: "strict",
4680
+ create() {
4681
+ return this.schema;
4682
+ },
4386
4683
  typeSymbol: `${pkg$1}#ManagementConfiguration`,
4387
4684
  schema: object({
4388
4685
  schemaVersion: literal("dsh-oidc/management/v1alpha1"),
@@ -4399,16 +4696,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4399
4696
  });
4400
4697
  const restartResult = Object.freeze({
4401
4698
  mode: "strict",
4699
+ create() {
4700
+ return this.schema;
4701
+ },
4402
4702
  typeSymbol: `${pkg$1}#RestartResult`,
4403
4703
  schema: object({ restarting: literal(true) }).strict()
4404
4704
  });
4405
4705
  const accountResult = Object.freeze({
4406
4706
  mode: "strict",
4707
+ create() {
4708
+ return this.schema;
4709
+ },
4407
4710
  typeSymbol: `${pkg$1}#AccountStatus`,
4408
4711
  schema: accountSchema
4409
4712
  });
4410
4713
  const beginResult = Object.freeze({
4411
4714
  mode: "strict",
4715
+ create() {
4716
+ return this.schema;
4717
+ },
4412
4718
  typeSymbol: `${pkg$1}#BeginResult`,
4413
4719
  schema: union([
4414
4720
  object({
@@ -4428,6 +4734,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4428
4734
  });
4429
4735
  const loginResult = Object.freeze({
4430
4736
  mode: "strict",
4737
+ create() {
4738
+ return this.schema;
4739
+ },
4431
4740
  typeSymbol: `${pkg$1}#LoginResult`,
4432
4741
  schema: object({
4433
4742
  loginID: loginIdSchema,
@@ -4451,6 +4760,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4451
4760
  source: "json",
4452
4761
  codec: Object.freeze({
4453
4762
  mode: "strict",
4763
+ create() {
4764
+ return this.schema;
4765
+ },
4454
4766
  typeSymbol,
4455
4767
  schema
4456
4768
  })
@@ -4649,7 +4961,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4649
4961
  }
4650
4962
  if (next.state === "cancelled") return service.status(profileID);
4651
4963
  if (next.state === "failed") {
4652
- const message = ["gateway_callback_issuer_missing", "gateway_callback_issuer_invalid"].includes(next.errorCode) ? "The authentication response does not match the sign-in configuration. Contact your administrator before trying again." : "Organization sign-in did not complete. Please try again.";
4964
+ const message = ["gateway_callback_issuer_missing", "gateway_callback_issuer_invalid"].includes(next.errorCode) ? "The authentication response does not match the sign-in configuration. Contact your administrator before trying again." : next.errorCode === "oidc_id_token_time_invalid" ? "The sign-in token failed its time check. Enable automatic date and time in system settings, synchronize your clock, and sign in again. If this continues, contact your administrator." : "Organization sign-in did not complete. Please try again.";
4653
4965
  throw Object.assign(new Error(message), { code: next.errorCode });
4654
4966
  }
4655
4967
  if (next.state === "expired") break;
@@ -4696,166 +5008,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4696
5008
  const textSecondary = "var(--dsw-alias-label-secondary, #75635c)";
4697
5009
  const textTertiary = "var(--dsw-alias-label-tertiary, #8a766f)";
4698
5010
  const background = "var(--dsw-alias-bg-layer-1, #fffdfb)";
4699
- const isChinese$1 = typeof navigator !== "undefined" && navigator.language.toLowerCase().startsWith("zh");
4700
- const copy = isChinese$1 ? {
4701
- waiting: "请在浏览器中完成登录…",
4702
- cancelLogin: "取消登录",
4703
- title: "学校 / 企业服务",
4704
- description: "已验证机构和兼容协议服务使用统一入口管理;普通 API Key 提供方继续由 DSH 原生设置管理。",
4705
- loading: "正在读取学校 / 企业服务…",
4706
- add: "+ 添加学校 / 企业服务",
4707
- verified: "已验证机构",
4708
- custom: "自定义服务",
4709
- connected: "已连接",
4710
- enabled: "已启用",
4711
- disabled: "未启用",
4712
- configure: "配置",
4713
- enable: "启用并重载",
4714
- login: "登录",
4715
- refresh: "刷新状态",
4716
- processing: "处理中…",
4717
- profileManaged: "Enterprise Profile 管理",
4718
- addTitle: "添加学校 / 企业服务",
4719
- addDescription: "选择已验证机构,或填写一个兼容协议 Base URL。",
4720
- addVerified: "添加",
4721
- compatible: "连接兼容协议服务",
4722
- compatibleHint: "默认从服务端发现登录、模型和能力。若元数据不完整,添加后可手动补充模型目录。",
4723
- saveService: "保存服务",
4724
- saving: "保存中…",
4725
- providerID: "Provider ID",
4726
- modelCatalog: "模型目录",
4727
- defaultContext: "默认上下文",
4728
- defaultOutput: "默认最大输出",
4729
- unspecified: "未声明",
4730
- modelCapability: "模型能力",
4731
- readonlyModels: "该机构的模型参数由 Enterprise Profile 或发行目录管理,只读。",
4732
- customModels: "默认自动发现;仅在服务端元数据不完整时使用手动模式。",
4733
- automatic: "自动发现",
4734
- manual: "手动配置",
4735
- baseModel: "基础模型",
4736
- context: "上下文",
4737
- output: "最大输出",
4738
- input: "输入",
4739
- reasoning: "思考强度",
4740
- decidedByService: "由服务决定",
4741
- unsupported: "暂不支持",
4742
- noModels: "尚未同步模型目录。完成机构登录后会自动读取,也可使用手动配置补充。",
4743
- model: "模型",
4744
- remove: "删除",
4745
- modelID: "模型 ID *",
4746
- displayName: "显示名称",
4747
- baseModelID: "基础模型 ID",
4748
- contextWindow: "上下文窗口",
4749
- maxOutput: "最大输出",
4750
- modalities: "输入模态",
4751
- reasoningLevels: "思考强度",
4752
- defaultReasoning: "默认思考强度",
4753
- supportsReasoning: "支持思考",
4754
- addModel: "+ 添加模型",
4755
- cancel: "取消",
4756
- saveModels: "保存模型配置",
4757
- close: "关闭",
4758
- editAddress: "企业服务地址",
4759
- editAddressHint: "修改地址会清除与旧服务绑定的本地登录状态;当前已启用时还需要重载 Runtime。",
4760
- save: "保存修改",
4761
- removeService: "移除服务",
4762
- deleteService: "删除服务",
4763
- confirmRemove: "确认从当前配置中移除?以后仍可重新添加。",
4764
- confirmDelete: "确认永久删除这项本地配置?",
4765
- confirm: "确认删除",
4766
- disable: "停用并重载",
4767
- restartNotice: "机构配置已保存。重启后会加载对应的 Provider、品牌和本地能力组合。",
4768
- restart: "立即重启应用",
4769
- emptyTitle: "尚未配置学校 / 企业服务",
4770
- emptyHint: "添加只保存配置;需要使用时再显式启用。全局同时只会启用一个企业服务。",
4771
- profileNotice: "应用从受信 Enterprise Profile 读取机构与模型目录;如需修改,请更新 Profile 后重启 DSH。",
4772
- fileHint: "通过配置文件连接学校或企业服务。修改后退出应用,再重新启动。",
4773
- openConfig: "打开配置文件",
4774
- openExamples: "查看示例",
4775
- configOpened: "已请求系统打开配置文件,修改后请退出并重新启动应用。",
4776
- examplesOpened: "已请求系统打开示例目录。",
4777
- fileFallback: "请在运行应用的电脑上打开:",
4778
- examplesHint: "完整示例见同目录下的 examples 文件夹。"
4779
- } : {
4780
- waiting: "Complete sign-in in your browser…",
4781
- cancelLogin: "Cancel sign-in",
4782
- title: "Organization services",
4783
- description: "Manage verified organizations and compatible enterprise services here; ordinary API-key providers remain in DSH model settings.",
4784
- loading: "Loading organization services…",
4785
- add: "+ Add organization service",
4786
- verified: "Verified organization",
4787
- custom: "Custom service",
4788
- connected: "Connected",
4789
- enabled: "Enabled",
4790
- disabled: "Disabled",
4791
- configure: "Configure",
4792
- enable: "Enable and reload",
4793
- login: "Sign in",
4794
- refresh: "Refresh",
4795
- processing: "Working…",
4796
- profileManaged: "Enterprise Profile managed",
4797
- addTitle: "Add organization service",
4798
- addDescription: "Select a verified organization or enter a compatible protocol Base URL.",
4799
- addVerified: "Add",
4800
- compatible: "Connect a compatible service",
4801
- compatibleHint: "Login, models, and capabilities are discovered by default. A model catalog can be supplied manually when metadata is incomplete.",
4802
- saveService: "Save service",
4803
- saving: "Saving…",
4804
- providerID: "Provider ID",
4805
- modelCatalog: "Model catalog",
4806
- defaultContext: "Default context",
4807
- defaultOutput: "Default output",
4808
- unspecified: "Unspecified",
4809
- modelCapability: "Model capabilities",
4810
- readonlyModels: "This catalog is read-only and managed by the Enterprise Profile or distribution.",
4811
- customModels: "Automatic discovery is preferred; use manual mode only when server metadata is incomplete.",
4812
- automatic: "Automatic discovery",
4813
- manual: "Manual configuration",
4814
- baseModel: "Base model",
4815
- context: "Context",
4816
- output: "Max output",
4817
- input: "Input",
4818
- reasoning: "Reasoning effort",
4819
- decidedByService: "Service default",
4820
- unsupported: "Unsupported",
4821
- noModels: "No model catalog is available yet. Sign in to discover models or configure them manually.",
4822
- model: "Model",
4823
- remove: "Remove",
4824
- modelID: "Model ID *",
4825
- displayName: "Display name",
4826
- baseModelID: "Base model ID",
4827
- contextWindow: "Context window",
4828
- maxOutput: "Max output",
4829
- modalities: "Input modalities",
4830
- reasoningLevels: "Reasoning effort",
4831
- defaultReasoning: "Default reasoning effort",
4832
- supportsReasoning: "Supports reasoning",
4833
- addModel: "+ Add model",
4834
- cancel: "Cancel",
4835
- saveModels: "Save models",
4836
- close: "Close",
4837
- editAddress: "Service address",
4838
- editAddressHint: "Changing the address clears the old local login binding and requires a Runtime reload when active.",
4839
- save: "Save",
4840
- removeService: "Remove service",
4841
- deleteService: "Delete service",
4842
- confirmRemove: "Remove this service from the current configuration?",
4843
- confirmDelete: "Permanently delete this local configuration?",
4844
- confirm: "Confirm",
4845
- disable: "Disable and reload",
4846
- restartNotice: "Configuration was saved. Reload to apply the Provider, brand, and local capabilities.",
4847
- restart: "Restart now",
4848
- emptyTitle: "No organization service configured",
4849
- emptyHint: "Adding a service only saves its configuration. Enable one explicitly when needed; only one service is active at a time.",
4850
- profileNotice: "The app reads organizations and models from a trusted Enterprise Profile. Update the Profile and restart DSH to change them.",
4851
- fileHint: "Connect an organization through the configuration file. Quit and relaunch after editing.",
4852
- openConfig: "Open configuration file",
4853
- openExamples: "View examples",
4854
- configOpened: "The file was sent to your system editor. Quit and relaunch after editing.",
4855
- examplesOpened: "The examples folder was sent to your system file manager.",
4856
- fileFallback: "Open this file on the computer running the app: ",
4857
- examplesHint: "Complete examples are in the examples folder beside it."
4858
- };
4859
5011
  const buttonStyle = Object.freeze({
4860
5012
  border: `1px solid ${border$1}`,
4861
5013
  borderRadius: 9,
@@ -4889,29 +5041,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4889
5041
  fontFamily: "system-ui, sans-serif",
4890
5042
  boxSizing: "border-box"
4891
5043
  });
4892
- const sourceLabel = (value) => ({
4893
- preset: isChinese$1 ? "内置审核目录" : "Reviewed catalog",
4894
- discovered: isChinese$1 ? "服务端自动发现" : "Server discovery",
4895
- discovery: isChinese$1 ? "等待服务端同步" : "Awaiting discovery",
4896
- manual: isChinese$1 ? "本机手动配置" : "Local manual catalog",
4897
- profile: copy.profileManaged
4898
- })[value] || (isChinese$1 ? "提供方声明" : "Provider declaration");
4899
- const capabilityLabel = (value) => ({
4900
- off: isChinese$1 ? "关闭" : "Off",
4901
- minimal: isChinese$1 ? "极低" : "Minimal",
4902
- low: isChinese$1 ? "低" : "Low",
4903
- medium: isChinese$1 ? "中" : "Medium",
4904
- high: isChinese$1 ? "高" : "High",
4905
- xhigh: isChinese$1 ? "极高" : "Extra high",
4906
- max: "Max"
4907
- })[value] || value;
4908
- const modalityLabel = (value) => ({
4909
- text: isChinese$1 ? "文本" : "Text",
4910
- image: isChinese$1 ? "图片" : "Image",
4911
- audio: isChinese$1 ? "音频" : "Audio",
4912
- video: isChinese$1 ? "视频" : "Video"
4913
- })[value] || value;
4914
- function ManagedProviderCard({ service, configuration }) {
5044
+ function ManagedProviderCard({ t, service, configuration }) {
5045
+ const sourceLabel = (value) => ({
5046
+ preset: t("managed.sourcePreset"),
5047
+ discovered: t("managed.sourceDiscovered"),
5048
+ discovery: t("managed.sourcePending"),
5049
+ manual: t("managed.sourceManual"),
5050
+ profile: t("managed.profileManaged")
5051
+ })[value] || t("managed.sourceProvider");
5052
+ const capabilityLabel = (value) => ({
5053
+ off: t("managed.effortOff"),
5054
+ minimal: t("managed.effortMinimal"),
5055
+ low: t("managed.effortLow"),
5056
+ medium: t("managed.effortMedium"),
5057
+ high: t("managed.effortHigh"),
5058
+ xhigh: t("managed.effortExtraHigh"),
5059
+ max: "Max"
5060
+ })[value] || value;
5061
+ const modalityLabel = (value) => ({
5062
+ text: t("managed.modalityText"),
5063
+ image: t("managed.modalityImage"),
5064
+ audio: t("managed.modalityAudio"),
5065
+ video: t("managed.modalityVideo")
5066
+ })[value] || value;
4915
5067
  const [management, setManagement] = (0, react.useState)(null);
4916
5068
  const [statuses, setStatuses] = (0, react.useState)({});
4917
5069
  const [busy, setBusy] = (0, react.useState)(false);
@@ -5011,10 +5163,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5011
5163
  margin: "18px 0",
5012
5164
  color: textSecondary,
5013
5165
  fontSize: 12
5014
- } }, copy.loading);
5166
+ } }, t("managed.loading"));
5015
5167
  const canManageProfiles = !configuration.configFile && management.capabilities.manageProfiles === true;
5016
5168
  const canManageModels = !configuration.configFile && management.capabilities.manageModels === true;
5017
- const noModelsNotice = configuration.configFile ? isChinese$1 ? "尚未同步模型目录。登录后将读取服务端模型;也可在配置文件中声明模型目录。" : "No model catalog has been synced. Sign in to discover models, or declare them in the configuration file." : copy.noModels;
5169
+ const noModelsNotice = configuration.configFile ? t("managed.fileModelsHint") : t("managed.noModels");
5018
5170
  const canRestart = management.capabilities.restart === true;
5019
5171
  const detail = management.profiles.find((profile) => profile.id === detailID) ?? null;
5020
5172
  const configured = management.profiles.filter((profile) => profile.configured);
@@ -5088,7 +5240,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5088
5240
  color: textSecondary,
5089
5241
  fontSize: 11
5090
5242
  }
5091
- }, isChinese$1 ? "身份登录 · 模型可自行配置" : "Identity sign-in · configure your own models")] : profile.runtime.models.length > 0 ? profile.runtime.models.map((model) => h$2("code", {
5243
+ }, t("managed.identityOnly"))] : profile.runtime.models.length > 0 ? profile.runtime.models.map((model) => h$2("code", {
5092
5244
  key: model.id,
5093
5245
  style: {
5094
5246
  borderRadius: 6,
@@ -5125,16 +5277,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5125
5277
  } }, h$2("strong", { style: { fontSize: 15 } }, profile.displayName), h$2("span", { style: {
5126
5278
  borderRadius: 999,
5127
5279
  padding: "2px 7px",
5128
- background: profile.builtIn ? "#f5e9e8" : "#eef1f6",
5129
- color: profile.builtIn ? accent : "#536174",
5280
+ background: "var(--dsw-alias-bg-layer-2, #eef1f6)",
5281
+ color: textSecondary,
5130
5282
  fontSize: 11
5131
- } }, configuration.configFile ? isChinese$1 ? "配置文件" : "Configuration file" : profile.builtIn ? copy.verified : copy.custom), h$2("span", { style: {
5283
+ } }, configuration.configFile ? t("managed.configurationFile") : profile.builtIn ? t("managed.verified") : t("managed.custom")), h$2("span", { style: {
5132
5284
  borderRadius: 999,
5133
5285
  padding: "2px 7px",
5134
- border: `1px solid ${connected ? "#b9d9c8" : border$1}`,
5135
- color: connected ? "#357a55" : profile.enabled ? accent : textTertiary,
5286
+ border: `1px solid ${connected ? "var(--dsw-alias-state-success-primary, #357a55)" : border$1}`,
5287
+ color: connected ? "var(--dsw-alias-state-success-primary, #357a55)" : profile.enabled ? accent : textTertiary,
5136
5288
  fontSize: 11
5137
- } }, connected ? copy.connected : profile.enabled ? copy.enabled : copy.disabled)), h$2("div", { style: {
5289
+ } }, connected ? t("managed.connected") : profile.enabled ? t("managed.enabled") : t("managed.disabled"))), h$2("div", { style: {
5138
5290
  marginTop: 6,
5139
5291
  color: textSecondary,
5140
5292
  fontSize: 11,
@@ -5155,22 +5307,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5155
5307
  disabled: busy,
5156
5308
  style: buttonStyle,
5157
5309
  onClick: () => openDetail(profile)
5158
- }, canManageProfiles || canManageModels ? copy.configure : isChinese$1 ? "查看详情" : "View details"), canManageProfiles && !profile.enabled && h$2("button", {
5310
+ }, canManageProfiles || canManageModels ? t("managed.configure") : t("managed.viewDetails")), canManageProfiles && !profile.enabled && h$2("button", {
5159
5311
  type: "button",
5160
5312
  disabled: busy,
5161
5313
  style: primaryStyle,
5162
5314
  onClick: () => enable(profile.id)
5163
- }, copy.enable), profile.enabled && !restartRequired && !connected && h$2("button", {
5315
+ }, t("managed.enable")), profile.enabled && !restartRequired && !connected && h$2("button", {
5164
5316
  type: "button",
5165
5317
  disabled: busy,
5166
5318
  style: primaryStyle,
5167
5319
  onClick: () => connect(profile.id)
5168
- }, busy ? copy.processing : copy.login), profile.enabled && !restartRequired && connected && h$2("button", {
5320
+ }, busy ? t("managed.processing") : t("managed.login")), profile.enabled && !restartRequired && connected && h$2("button", {
5169
5321
  type: "button",
5170
5322
  disabled: busy,
5171
5323
  style: buttonStyle,
5172
5324
  onClick: () => run(() => service.reconcile(profile.id, {}))
5173
- }, copy.refresh))));
5325
+ }, t("managed.refresh")))));
5174
5326
  })) : h$2("div", { style: {
5175
5327
  padding: 18,
5176
5328
  border: `1px dashed ${border$1}`,
@@ -5179,12 +5331,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5179
5331
  } }, h$2("strong", { style: {
5180
5332
  display: "block",
5181
5333
  fontSize: 14
5182
- } }, copy.emptyTitle), h$2("p", { style: {
5334
+ } }, t("managed.emptyTitle")), h$2("p", { style: {
5183
5335
  margin: "6px 0 0",
5184
5336
  color: textSecondary,
5185
5337
  fontSize: 12,
5186
5338
  lineHeight: 1.55
5187
- } }, configuration.configFile ? isChinese$1 ? "参考上方示例,在配置文件的 organizations 中填写企业信息,保存并退出后重新启动。也可以直接在模型设置中使用自己的 API Key。" : "Use the examples above to fill in organizations, save, quit and relaunch. You can also use your own API key in model settings." : copy.emptyHint));
5339
+ } }, configuration.configFile ? t("managed.fileEmptyHint") : t("managed.emptyHint")));
5188
5340
  const addDialog = addOpen && h$2("div", {
5189
5341
  style: panelStyle,
5190
5342
  onMouseDown: (event) => {
@@ -5193,7 +5345,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5193
5345
  }, h$2("div", {
5194
5346
  role: "dialog",
5195
5347
  "aria-modal": "true",
5196
- "aria-label": copy.addTitle,
5348
+ "aria-label": t("managed.addTitle"),
5197
5349
  style: {
5198
5350
  ...cardStyle,
5199
5351
  width: "min(660px, calc(100vw - 40px))"
@@ -5205,14 +5357,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5205
5357
  } }, h$2("div", null, h$2("h2", { style: {
5206
5358
  margin: "0 0 4px",
5207
5359
  fontSize: 22
5208
- } }, copy.addTitle), h$2("p", { style: {
5360
+ } }, t("managed.addTitle")), h$2("p", { style: {
5209
5361
  margin: 0,
5210
5362
  color: textSecondary,
5211
5363
  fontSize: 12
5212
- } }, copy.addDescription)), h$2("button", {
5364
+ } }, t("managed.addDescription"))), h$2("button", {
5213
5365
  type: "button",
5214
5366
  disabled: busy,
5215
- "aria-label": copy.close,
5367
+ "aria-label": t("managed.close"),
5216
5368
  onClick: () => setAddOpen(false),
5217
5369
  style: buttonStyle
5218
5370
  }, "×")), available.length > 0 && h$2("div", { style: {
@@ -5238,7 +5390,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5238
5390
  disabled: busy,
5239
5391
  style: primaryStyle,
5240
5392
  onClick: () => run(() => service.configure(profile.id)).then(() => setAddOpen(false))
5241
- }, copy.addVerified)))), h$2("form", {
5393
+ }, t("managed.addVerified"))))), h$2("form", {
5242
5394
  onSubmit: addCustom,
5243
5395
  style: {
5244
5396
  marginTop: 20,
@@ -5248,11 +5400,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5248
5400
  }, h$2("strong", { style: {
5249
5401
  display: "block",
5250
5402
  fontSize: 13
5251
- } }, copy.compatible), h$2("p", { style: {
5403
+ } }, t("managed.compatible")), h$2("p", { style: {
5252
5404
  margin: "5px 0 10px",
5253
5405
  color: textSecondary,
5254
5406
  fontSize: 12
5255
- } }, copy.compatibleHint), h$2("div", { style: {
5407
+ } }, t("managed.compatibleHint")), h$2("div", { style: {
5256
5408
  display: "flex",
5257
5409
  gap: 8
5258
5410
  } }, h$2("input", {
@@ -5266,7 +5418,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5266
5418
  type: "submit",
5267
5419
  disabled: busy,
5268
5420
  style: primaryStyle
5269
- }, busy ? copy.saving : copy.saveService)))));
5421
+ }, busy ? t("managed.saving") : t("managed.saveService"))))));
5270
5422
  const modelEditors = modelDrafts.map((draft, index) => h$2("article", {
5271
5423
  key: index,
5272
5424
  style: {
@@ -5278,20 +5430,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5278
5430
  display: "flex",
5279
5431
  justifyContent: "space-between",
5280
5432
  marginBottom: 10
5281
- } }, h$2("strong", null, `${copy.model} ${index + 1}`), modelDrafts.length > 1 && h$2("button", {
5433
+ } }, h$2("strong", null, `${t("managed.model")} ${index + 1}`), modelDrafts.length > 1 && h$2("button", {
5282
5434
  type: "button",
5283
5435
  style: buttonStyle,
5284
5436
  onClick: () => setModelDrafts((current) => current.filter((_, candidate) => candidate !== index))
5285
- }, copy.remove)), h$2("div", { style: {
5437
+ }, t("managed.remove"))), h$2("div", { style: {
5286
5438
  display: "grid",
5287
5439
  gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
5288
5440
  gap: 9
5289
5441
  } }, ...[
5290
- [copy.modelID, "id"],
5291
- [copy.displayName, "name"],
5292
- [copy.baseModelID, "upstreamModelID"],
5293
- [copy.contextWindow, "contextWindow"],
5294
- [copy.maxOutput, "maxTokens"]
5442
+ [t("managed.modelID"), "id"],
5443
+ [t("managed.displayName"), "name"],
5444
+ [t("managed.baseModelID"), "upstreamModelID"],
5445
+ [t("managed.contextWindow"), "contextWindow"],
5446
+ [t("managed.maxOutput"), "maxTokens"]
5295
5447
  ].map(([label, field]) => h$2("label", {
5296
5448
  key: field,
5297
5449
  style: { fontSize: 11 }
@@ -5309,7 +5461,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5309
5461
  } }, h$2("span", { style: {
5310
5462
  marginRight: 10,
5311
5463
  color: textSecondary
5312
- } }, copy.modalities), ...[
5464
+ } }, t("managed.modalities")), ...[
5313
5465
  "text",
5314
5466
  "image",
5315
5467
  "audio",
@@ -5327,14 +5479,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5327
5479
  } }, h$2("span", { style: {
5328
5480
  marginRight: 10,
5329
5481
  color: textSecondary
5330
- } }, copy.reasoningLevels), h$2("label", { style: { marginRight: 12 } }, h$2("input", {
5482
+ } }, t("managed.reasoningLevels")), h$2("label", { style: { marginRight: 12 } }, h$2("input", {
5331
5483
  type: "checkbox",
5332
5484
  checked: draft.reasoningSupported,
5333
5485
  onChange: (event) => updateDraft(index, {
5334
5486
  reasoningSupported: event.currentTarget.checked,
5335
5487
  reasoning: event.currentTarget.checked ? draft.reasoning : []
5336
5488
  })
5337
- }), ` ${copy.supportsReasoning}`), ...draft.reasoningSupported ? reasoningEffortOrder.map((value) => h$2("label", {
5489
+ }), ` ${t("managed.supportsReasoning")}`), ...draft.reasoningSupported ? reasoningEffortOrder.map((value) => h$2("label", {
5338
5490
  key: value,
5339
5491
  style: { marginRight: 11 }
5340
5492
  }, h$2("input", {
@@ -5345,14 +5497,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5345
5497
  display: "block",
5346
5498
  marginTop: 9,
5347
5499
  fontSize: 11
5348
- } }, copy.defaultReasoning, h$2("select", {
5500
+ } }, t("managed.defaultReasoning"), h$2("select", {
5349
5501
  value: draft.reasoning.includes(draft.defaultReasoningEffort) ? draft.defaultReasoningEffort : "",
5350
5502
  onChange: (event) => updateDraft(index, { defaultReasoningEffort: event.currentTarget.value }),
5351
5503
  style: {
5352
5504
  ...inputStyle,
5353
5505
  marginTop: 5
5354
5506
  }
5355
- }, h$2("option", { value: "" }, copy.decidedByService), ...draft.reasoning.slice().sort((left, right) => reasoningEffortOrder.indexOf(left) - reasoningEffortOrder.indexOf(right)).map((value) => h$2("option", {
5507
+ }, h$2("option", { value: "" }, t("managed.decidedByService")), ...draft.reasoning.slice().sort((left, right) => reasoningEffortOrder.indexOf(left) - reasoningEffortOrder.indexOf(right)).map((value) => h$2("option", {
5356
5508
  key: value,
5357
5509
  value
5358
5510
  }, capabilityLabel(value)))))));
@@ -5364,7 +5516,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5364
5516
  }, h$2("div", {
5365
5517
  role: "dialog",
5366
5518
  "aria-modal": "true",
5367
- "aria-label": `${detail.displayName} ${copy.configure}`,
5519
+ "aria-label": `${detail.displayName} ${t("managed.configure")}`,
5368
5520
  style: cardStyle
5369
5521
  }, h$2("div", { style: {
5370
5522
  display: "flex",
@@ -5381,7 +5533,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5381
5533
  } }, `${detail.organization} · ${detail.baseURL}`)), h$2("button", {
5382
5534
  type: "button",
5383
5535
  disabled: busy,
5384
- "aria-label": copy.close,
5536
+ "aria-label": t("managed.close"),
5385
5537
  onClick: () => setDetailID(""),
5386
5538
  style: buttonStyle
5387
5539
  }, "×")), h$2("div", { style: {
@@ -5390,10 +5542,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5390
5542
  gap: 8,
5391
5543
  marginTop: 17
5392
5544
  } }, ...[
5393
- [copy.providerID, detail.providerID],
5394
- [copy.modelCatalog, sourceLabel(detail.runtime.modelSource)],
5395
- [copy.defaultContext, modelCapabilitySummary({}, detail.runtime).contextWindow],
5396
- [copy.defaultOutput, modelCapabilitySummary({}, detail.runtime).maxTokens]
5545
+ [t("managed.providerID"), detail.providerID],
5546
+ [t("managed.modelCatalog"), sourceLabel(detail.runtime.modelSource)],
5547
+ [t("managed.defaultContext"), modelCapabilitySummary({}, detail.runtime).contextWindow],
5548
+ [t("managed.defaultOutput"), modelCapabilitySummary({}, detail.runtime).maxTokens]
5397
5549
  ].map(([label, value]) => h$2("div", {
5398
5550
  key: label,
5399
5551
  style: {
@@ -5409,7 +5561,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5409
5561
  display: "block",
5410
5562
  marginTop: 4,
5411
5563
  fontSize: 12
5412
- } }, value || copy.unspecified)))), canManageProfiles && !detail.builtIn && h$2("form", {
5564
+ } }, value || t("managed.unspecified"))))), canManageProfiles && !detail.builtIn && h$2("form", {
5413
5565
  onSubmit: updateCustom,
5414
5566
  style: {
5415
5567
  marginTop: 16,
@@ -5417,11 +5569,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5417
5569
  border: `1px solid ${border$1}`,
5418
5570
  borderRadius: 10
5419
5571
  }
5420
- }, h$2("strong", { style: { fontSize: 12 } }, copy.editAddress), h$2("p", { style: {
5572
+ }, h$2("strong", { style: { fontSize: 12 } }, t("managed.editAddress")), h$2("p", { style: {
5421
5573
  margin: "4px 0 9px",
5422
5574
  color: textTertiary,
5423
5575
  fontSize: 11
5424
- } }, copy.editAddressHint), h$2("div", { style: {
5576
+ } }, t("managed.editAddressHint")), h$2("div", { style: {
5425
5577
  display: "flex",
5426
5578
  gap: 8
5427
5579
  } }, h$2("input", {
@@ -5434,16 +5586,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5434
5586
  type: "submit",
5435
5587
  disabled: busy || editBaseURL === detail.baseURL,
5436
5588
  style: buttonStyle
5437
- }, copy.save))), h$2("div", { style: {
5589
+ }, t("managed.save")))), h$2("div", { style: {
5438
5590
  marginTop: 20,
5439
5591
  display: "flex",
5440
5592
  justifyContent: "space-between",
5441
5593
  gap: 12
5442
- } }, h$2("div", null, h$2("strong", { style: { fontSize: 14 } }, copy.modelCapability), h$2("p", { style: {
5594
+ } }, h$2("div", null, h$2("strong", { style: { fontSize: 14 } }, t("managed.modelCapability")), h$2("p", { style: {
5443
5595
  margin: "4px 0 0",
5444
5596
  color: textTertiary,
5445
5597
  fontSize: 11
5446
- } }, canManageModels && !detail.builtIn ? copy.customModels : copy.readonlyModels)), canManageModels && !detail.builtIn && h$2("div", { style: {
5598
+ } }, canManageModels && !detail.builtIn ? t("managed.customModels") : t("managed.readonlyModels"))), canManageModels && !detail.builtIn && h$2("div", { style: {
5447
5599
  display: "flex",
5448
5600
  gap: 7
5449
5601
  } }, h$2("button", {
@@ -5451,7 +5603,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5451
5603
  disabled: busy,
5452
5604
  style: buttonStyle,
5453
5605
  onClick: useDiscovery
5454
- }, copy.automatic), h$2("button", {
5606
+ }, t("managed.automatic")), h$2("button", {
5455
5607
  type: "button",
5456
5608
  disabled: busy,
5457
5609
  style: editingModels ? primaryStyle : buttonStyle,
@@ -5459,7 +5611,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5459
5611
  setModelDrafts(detail.runtime.models.map(runtimeModelDraft).concat(detail.runtime.models.length ? [] : [runtimeModelDraft()]));
5460
5612
  setEditingModels(true);
5461
5613
  }
5462
- }, copy.manual))), !editingModels && h$2("div", { style: {
5614
+ }, t("managed.manual")))), !editingModels && h$2("div", { style: {
5463
5615
  display: "grid",
5464
5616
  gap: 9,
5465
5617
  marginTop: 11
@@ -5480,16 +5632,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5480
5632
  color: textTertiary,
5481
5633
  fontSize: 11
5482
5634
  } }, summary.id), summary.multimodal && h$2("span", { style: {
5483
- color: "#355c91",
5635
+ color: "var(--dsw-alias-state-business-primary, #355c91)",
5484
5636
  fontSize: 10
5485
- } }, isChinese$1 ? "多模态" : "Multimodal")), h$2("div", { style: {
5637
+ } }, t("managed.multimodal"))), h$2("div", { style: {
5486
5638
  display: "grid",
5487
5639
  gridTemplateColumns: "repeat(auto-fit, minmax(125px, 1fr))",
5488
5640
  gap: 8,
5489
5641
  marginTop: 10,
5490
5642
  color: textSecondary,
5491
5643
  fontSize: 11
5492
- } }, summary.upstreamModelID && h$2("span", null, `${copy.baseModel}:${summary.upstreamModelID}`), h$2("span", null, `${copy.context}:${summary.contextWindow || copy.unspecified}`), h$2("span", null, `${copy.output}:${summary.maxTokens || copy.unspecified}`), h$2("span", null, `${copy.input}:${summary.input.map(modalityLabel).join("、")}`), h$2("span", null, `${copy.reasoning}:${!summary.reasoningSupported ? copy.unsupported : summary.reasoningEfforts.length ? summary.reasoningEfforts.map(capabilityLabel).join("、") : copy.decidedByService}`)));
5644
+ } }, summary.upstreamModelID && h$2("span", null, `${t("managed.baseModel")}:${summary.upstreamModelID}`), h$2("span", null, `${t("managed.context")}:${summary.contextWindow || t("managed.unspecified")}`), h$2("span", null, `${t("managed.output")}:${summary.maxTokens || t("managed.unspecified")}`), h$2("span", null, `${t("managed.input")}:${summary.input.map(modalityLabel).join("、")}`), h$2("span", null, `${t("managed.reasoning")}:${!summary.reasoningSupported ? t("managed.unsupported") : summary.reasoningEfforts.length ? summary.reasoningEfforts.map(capabilityLabel).join("、") : t("managed.decidedByService")}`)));
5493
5645
  }) : [h$2("div", {
5494
5646
  key: "empty",
5495
5647
  style: {
@@ -5513,18 +5665,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5513
5665
  type: "button",
5514
5666
  style: buttonStyle,
5515
5667
  onClick: () => setModelDrafts((current) => [...current, runtimeModelDraft()])
5516
- }, copy.addModel), h$2("div", { style: {
5668
+ }, t("managed.addModel")), h$2("div", { style: {
5517
5669
  display: "flex",
5518
5670
  gap: 8
5519
5671
  } }, h$2("button", {
5520
5672
  type: "button",
5521
5673
  style: buttonStyle,
5522
5674
  onClick: () => setEditingModels(false)
5523
- }, copy.cancel), h$2("button", {
5675
+ }, t("managed.cancel")), h$2("button", {
5524
5676
  type: "submit",
5525
5677
  disabled: busy,
5526
5678
  style: primaryStyle
5527
- }, copy.saveModels)))), canManageProfiles && h$2("div", { style: {
5679
+ }, t("managed.saveModels"))))), canManageProfiles && h$2("div", { style: {
5528
5680
  display: "flex",
5529
5681
  justifyContent: "space-between",
5530
5682
  gap: 10,
@@ -5532,38 +5684,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5532
5684
  paddingTop: 14,
5533
5685
  borderTop: `1px solid ${border$1}`
5534
5686
  } }, h$2("div", null, removeConfirmID === detail.id ? h$2("span", { style: {
5535
- color: "#a82332",
5687
+ color: "var(--dsw-alias-state-error-primary, #a82332)",
5536
5688
  fontSize: 11
5537
- } }, detail.builtIn ? copy.confirmRemove : copy.confirmDelete) : h$2("button", {
5689
+ } }, detail.builtIn ? t("managed.confirmRemove") : t("managed.confirmDelete")) : h$2("button", {
5538
5690
  type: "button",
5539
5691
  disabled: busy,
5540
5692
  style: {
5541
5693
  ...buttonStyle,
5542
- color: "#a82332"
5694
+ color: "var(--dsw-alias-state-error-primary, #a82332)"
5543
5695
  },
5544
5696
  onClick: () => setRemoveConfirmID(detail.id)
5545
- }, detail.builtIn ? copy.removeService : copy.deleteService), removeConfirmID === detail.id && h$2("span", { style: { marginLeft: 8 } }, h$2("button", {
5697
+ }, detail.builtIn ? t("managed.removeService") : t("managed.deleteService")), removeConfirmID === detail.id && h$2("span", { style: { marginLeft: 8 } }, h$2("button", {
5546
5698
  type: "button",
5547
5699
  style: buttonStyle,
5548
5700
  onClick: () => setRemoveConfirmID("")
5549
- }, copy.cancel), h$2("button", {
5701
+ }, t("managed.cancel")), h$2("button", {
5550
5702
  type: "button",
5551
5703
  style: {
5552
5704
  ...primaryStyle,
5553
5705
  marginLeft: 6
5554
5706
  },
5555
5707
  onClick: () => removeProfile(detail)
5556
- }, copy.confirm))), detail.enabled ? h$2("button", {
5708
+ }, t("managed.confirm")))), detail.enabled ? h$2("button", {
5557
5709
  type: "button",
5558
5710
  disabled: busy,
5559
5711
  style: buttonStyle,
5560
5712
  onClick: disable
5561
- }, copy.disable) : h$2("button", {
5713
+ }, t("managed.disable")) : h$2("button", {
5562
5714
  type: "button",
5563
5715
  disabled: busy,
5564
5716
  style: primaryStyle,
5565
5717
  onClick: () => enable(detail.id)
5566
- }, copy.enable))));
5718
+ }, t("managed.enable")))));
5567
5719
  return h$2("section", {
5568
5720
  "data-dsh-oidc-managed-provider": "true",
5569
5721
  style: { margin: "18px 0" }
@@ -5572,12 +5724,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5572
5724
  justifyContent: "space-between",
5573
5725
  gap: 16,
5574
5726
  marginBottom: 11
5575
- } }, h$2("div", null, h$2("strong", { style: { fontSize: 14 } }, copy.title), h$2("p", { style: {
5727
+ } }, h$2("div", null, h$2("strong", { style: { fontSize: 14 } }, t("managed.title")), h$2("p", { style: {
5576
5728
  margin: "4px 0 0",
5577
5729
  color: textSecondary,
5578
5730
  fontSize: 12,
5579
5731
  lineHeight: 1.55
5580
- } }, copy.description)), canManageProfiles && h$2("button", {
5732
+ } }, t("managed.description"))), canManageProfiles && h$2("button", {
5581
5733
  type: "button",
5582
5734
  disabled: busy,
5583
5735
  style: primaryStyle,
@@ -5586,7 +5738,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5586
5738
  setNotice("");
5587
5739
  setAddOpen(true);
5588
5740
  }
5589
- }, copy.add)), configuration.configFile ? h$2("div", {
5741
+ }, t("managed.add"))), configuration.configFile ? h$2("div", {
5590
5742
  "data-eduwork-config-file": true,
5591
5743
  style: {
5592
5744
  margin: "10px 0",
@@ -5595,7 +5747,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5595
5747
  lineHeight: 1.7,
5596
5748
  overflowWrap: "anywhere"
5597
5749
  }
5598
- }, h$2("p", { style: { margin: 0 } }, copy.fileHint), configuration.configFile.canOpen ? h$2("div", { style: {
5750
+ }, h$2("p", { style: { margin: 0 } }, t("managed.fileHint")), configuration.configFile.canOpen ? h$2("div", { style: {
5599
5751
  display: "flex",
5600
5752
  flexWrap: "wrap",
5601
5753
  gap: 8,
@@ -5604,30 +5756,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5604
5756
  type: "button",
5605
5757
  style: primaryStyle,
5606
5758
  disabled: busy,
5607
- onClick: () => run(() => service.openConfiguration("config"), copy.configOpened)
5608
- }, copy.openConfig), h$2("button", {
5759
+ onClick: () => run(() => service.openConfiguration("config"), t("managed.configOpened"))
5760
+ }, t("managed.openConfig")), h$2("button", {
5609
5761
  type: "button",
5610
5762
  style: buttonStyle,
5611
5763
  disabled: busy,
5612
- onClick: () => run(() => service.openConfiguration("examples"), copy.examplesOpened)
5613
- }, copy.openExamples)) : h$2("div", { style: { marginTop: 6 } }, h$2("div", null, copy.fileFallback, h$2("code", null, configuration.configFile.path)), h$2("div", null, copy.examplesHint))) : management.mode === "profile" && h$2("p", { style: {
5764
+ onClick: () => run(() => service.openConfiguration("examples"), t("managed.examplesOpened"))
5765
+ }, t("managed.openExamples"))) : h$2("div", { style: { marginTop: 6 } }, h$2("div", null, t("managed.fileFallback"), h$2("code", null, configuration.configFile.path)), h$2("div", null, t("managed.examplesHint")))) : management.mode === "profile" && h$2("p", { style: {
5614
5766
  margin: "8px 0",
5615
5767
  color: textTertiary,
5616
5768
  fontSize: 11
5617
- } }, copy.profileNotice), login.pending && h$2("p", { role: "status" }, copy.waiting, " ", h$2("button", {
5769
+ } }, t("managed.profileNotice")), login.pending && h$2("p", { role: "status" }, t("managed.waiting"), " ", h$2("button", {
5618
5770
  type: "button",
5619
5771
  style: buttonStyle,
5620
5772
  onClick: login.cancel
5621
- }, copy.cancelLogin)), error && h$2("p", {
5773
+ }, t("managed.cancelLogin"))), error && h$2("p", {
5622
5774
  role: "alert",
5623
5775
  style: {
5624
- color: "#a82332",
5776
+ color: "var(--dsw-alias-state-error-primary, #a82332)",
5625
5777
  fontSize: 12
5626
5778
  }
5627
5779
  }, error), notice && h$2("p", {
5628
5780
  role: "status",
5629
5781
  style: {
5630
- color: "#357a55",
5782
+ color: "var(--dsw-alias-state-success-primary, #357a55)",
5631
5783
  fontSize: 12
5632
5784
  }
5633
5785
  }, notice), restartRequired && canRestart && h$2("div", { style: {
@@ -5641,12 +5793,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5641
5793
  } }, h$2("span", { style: {
5642
5794
  color: textSecondary,
5643
5795
  fontSize: 12
5644
- } }, copy.restartNotice), h$2("button", {
5796
+ } }, t("managed.restartNotice")), h$2("button", {
5645
5797
  type: "button",
5646
5798
  disabled: busy,
5647
5799
  style: primaryStyle,
5648
5800
  onClick: () => run(service.restart)
5649
- }, copy.restart)), providerCards, addDialog, detailDialog);
5801
+ }, t("managed.restart"))), providerCards, addDialog, detailDialog);
5650
5802
  }
5651
5803
  //#endregion
5652
5804
  //#region src/client/use-account-status.ts
@@ -5785,23 +5937,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5785
5937
  //#endregion
5786
5938
  //#region src/client/account-menu.ts
5787
5939
  const h$1 = react.default.createElement;
5788
- const words = typeof navigator !== "undefined" && navigator.language.toLowerCase().startsWith("zh") ? {
5789
- menu: "账户菜单",
5790
- check: "刷新账户",
5791
- logout: "退出登录",
5792
- login: "登录账户",
5793
- waiting: "请在浏览器中完成登录…",
5794
- cancel: "取消登录",
5795
- processing: "正在处理…"
5796
- } : {
5797
- menu: "Account menu",
5798
- check: "Refresh account",
5799
- logout: "Sign out",
5800
- login: "Sign in",
5801
- waiting: "Complete sign-in in your browser…",
5802
- cancel: "Cancel sign-in",
5803
- processing: "Working…"
5804
- };
5805
5940
  const action = {
5806
5941
  width: "100%",
5807
5942
  textAlign: "left",
@@ -5814,7 +5949,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5814
5949
  color: "inherit"
5815
5950
  };
5816
5951
  const secondary = "var(--dsw-alias-label-secondary, #69717f)";
5817
- function AccountMenu({ service, profile, children, renderSlot, wide = true }) {
5952
+ function AccountMenu({ t, service, profile, children, renderSlot, wide = true }) {
5818
5953
  const status = useAccountStatus(service, profile.id);
5819
5954
  const [open, setOpen] = (0, react.useState)(false);
5820
5955
  const [position, setPosition] = (0, react.useState)({
@@ -5899,13 +6034,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5899
6034
  onClick
5900
6035
  }, label);
5901
6036
  const refreshAccount = () => service.reconcile(profile.id, {});
5902
- const defaultContent = signedIn && button(busy ? words.processing : words.check, () => void run(refreshAccount));
6037
+ const defaultContent = signedIn && button(busy ? t("menu.processing") : t("menu.check"), () => void run(refreshAccount));
5903
6038
  const content = open && h$1("div", {
5904
6039
  ref: panel,
5905
6040
  id,
5906
6041
  role: "menu",
5907
6042
  tabIndex: -1,
5908
- "aria-label": words.menu,
6043
+ "aria-label": t("menu.menu"),
5909
6044
  onKeyDown: keydown,
5910
6045
  style: {
5911
6046
  position: "fixed",
@@ -5939,12 +6074,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5939
6074
  }, { fallback: defaultContent }) : defaultContent, h$1("div", { style: {
5940
6075
  display: "grid",
5941
6076
  gap: 6
5942
- } }, !signedIn && button(busy ? words.processing : words.login, () => void run(() => login.begin(profile.id))), signedIn && button(words.logout, () => void run(() => service.logout(profile.id), true))), login.pending && h$1("p", { role: "status" }, words.waiting, " ", h$1("button", {
6077
+ } }, !signedIn && button(busy ? t("menu.processing") : profile.brand?.loginButtonLabel || t("menu.login"), () => void run(() => login.begin(profile.id))), signedIn && button(t("menu.logout"), () => void run(() => service.logout(profile.id), true))), login.pending && h$1("p", { role: "status" }, t("menu.waiting"), " ", h$1("button", {
5943
6078
  type: "button",
5944
6079
  role: "menuitem",
5945
6080
  style: action,
5946
6081
  onClick: login.cancel
5947
- }, words.cancel)), error && h$1("p", {
6082
+ }, t("menu.cancel"))), error && h$1("p", {
5948
6083
  role: "alert",
5949
6084
  style: {
5950
6085
  color: "var(--dsw-alias-state-error-primary, #a14d3b)",
@@ -5954,11 +6089,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5954
6089
  return h$1(react.default.Fragment, null, h$1("button", {
5955
6090
  ref: trigger,
5956
6091
  type: "button",
5957
- "aria-label": `${accountUserName(status) || accountOrganization(profile)} · ${words.menu}`,
6092
+ "aria-label": `${accountUserName(status) || accountOrganization(profile)} · ${t("menu.menu")}`,
5958
6093
  "aria-haspopup": "menu",
5959
6094
  "aria-expanded": open,
5960
6095
  "aria-controls": open ? id : void 0,
5961
- title: words.menu,
6096
+ title: t("menu.menu"),
5962
6097
  onClick: () => setOpen((value) => !value),
5963
6098
  onKeyDown: (event) => {
5964
6099
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
@@ -5984,6 +6119,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5984
6119
  //#region src/client/index.ts
5985
6120
  const inject = [
5986
6121
  "slots",
6122
+ "locale",
5987
6123
  "remote",
5988
6124
  "theme"
5989
6125
  ];
@@ -5998,54 +6134,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5998
6134
  background: "var(--dsw-alias-bg-layer-1, #fff)",
5999
6135
  color: "var(--dsw-alias-label-primary, #241a18)"
6000
6136
  });
6001
- const isChinese = typeof navigator !== "undefined" && navigator.language.toLowerCase().startsWith("zh");
6002
- const messages = isChinese ? {
6003
- waiting: "请在浏览器中完成登录…",
6004
- cancelLogin: "取消登录",
6005
- identityDescription: "使用组织账号登录。模型服务可在设置中单独配置。",
6006
- identityConnected: "组织身份已登录",
6007
- unavailable: "企业模型服务暂时不可用",
6008
- connected: "已连接",
6009
- disconnected: "尚未连接",
6010
- description: "使用组织统一身份认证连接企业模型。密码不会进入 DSH;模型请求使用登录授权。",
6011
- connecting: "正在连接…",
6012
- login: "使用企业账号登录",
6013
- checking: "正在检查…",
6014
- check: "检查连接",
6015
- logout: "退出登录",
6016
- help: "帮助",
6017
- dialog: "连接企业模型",
6018
- shortDescription: "通过组织统一身份认证连接企业模型;密码不会进入 DSH。",
6019
- other: "使用其他模型",
6020
- enabled: "完成后将启用",
6021
- footerConnected: "企业模型已连接",
6022
- footerSetup: "点击设置完成登录"
6023
- } : {
6024
- waiting: "Complete sign-in in your browser…",
6025
- cancelLogin: "Cancel sign-in",
6026
- identityDescription: "Sign in with your organization account. Configure model services separately in settings.",
6027
- identityConnected: "Organization identity connected",
6028
- unavailable: "Enterprise model service is temporarily unavailable",
6029
- connected: "Connected",
6030
- disconnected: "Not connected",
6031
- description: "Connect with your organization account. Your password never enters DSH; model requests use your sign-in authorization.",
6032
- connecting: "Connecting…",
6033
- login: "Sign in with organization",
6034
- checking: "Checking…",
6035
- check: "Check connection",
6036
- logout: "Sign out",
6037
- help: "Help",
6038
- dialog: "Connect enterprise models",
6039
- shortDescription: "Connect enterprise models through your organization identity provider. Your password never enters DSH.",
6040
- other: "Use another model",
6041
- enabled: "This enables",
6042
- footerConnected: "Enterprise models connected",
6043
- footerSetup: "Open settings to connect"
6044
- };
6045
- async function unwrap(operation) {
6137
+ async function unwrapResult(operation, t) {
6046
6138
  const result = await operation;
6047
6139
  if (result?.ok === true) return result.value;
6048
- throw new Error(result?.error?.message || result?.error?.code || messages.unavailable);
6140
+ throw new Error(result?.error?.message || result?.error?.code || t("account.unavailable"));
6049
6141
  }
6050
6142
  function ProductMark({ profile, size = 24 }) {
6051
6143
  const brand = profile.brand ?? {};
@@ -6157,19 +6249,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6157
6249
  run
6158
6250
  };
6159
6251
  }
6160
- function EnterpriseAccountCard({ service, configuration }) {
6252
+ function EnterpriseAccountCard({ t, service, configuration }) {
6161
6253
  const [profileID, setProfileID] = (0, react.useState)(configuration.profiles[0]?.id || "");
6162
6254
  const profile = configuration.profiles.find((candidate) => candidate.id === profileID) || configuration.profiles[0];
6163
6255
  const account = useAccount(service, profile.id);
6164
6256
  const primary = {
6165
6257
  ...button,
6166
- background: profile.brand?.primaryColor || "var(--dsw-alias-brand-primary, #5157af)",
6258
+ background: profile.brand?.primaryColor || "var(--dsw-alias-state-business-primary, #5157af)",
6167
6259
  color: "white",
6168
6260
  borderColor: "transparent"
6169
6261
  };
6170
6262
  const login = useSignIn(service);
6171
6263
  const begin = () => account.run("login", () => login.begin(profile.id));
6172
- const stateLabel = account.status?.state === "connected" ? messages.connected : messages.disconnected;
6264
+ const stateLabel = account.status?.state === "connected" ? t("account.connected") : t("account.disconnected");
6173
6265
  const userName = accountUserName(account.status);
6174
6266
  return h("section", { style: {
6175
6267
  padding: "16px 0",
@@ -6204,7 +6296,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6204
6296
  color: "var(--dsw-alias-label-secondary)",
6205
6297
  fontSize: 12,
6206
6298
  lineHeight: 1.6
6207
- } }, profile.brand?.loginDescription || (profile.provider ? messages.description : messages.identityDescription)), h("div", { style: {
6299
+ } }, profile.brand?.loginDescription || (profile.provider ? t("account.description") : t("account.identityDescription"))), h("div", { style: {
6208
6300
  marginTop: 12,
6209
6301
  display: "flex",
6210
6302
  gap: 8,
@@ -6214,17 +6306,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6214
6306
  disabled: Boolean(account.busy),
6215
6307
  style: primary,
6216
6308
  onClick: begin
6217
- }, account.busy ? messages.connecting : messages.login), account.status?.state === "connected" && h("button", {
6309
+ }, account.busy ? t("account.connecting") : profile.brand?.loginButtonLabel || t("account.login")), account.status?.state === "connected" && h("button", {
6218
6310
  type: "button",
6219
6311
  disabled: Boolean(account.busy),
6220
6312
  style: button,
6221
6313
  onClick: () => account.run("reconcile", () => service.reconcile(profile.id, {}))
6222
- }, account.busy ? messages.checking : messages.check), account.status?.state !== "signed_out" && h("button", {
6314
+ }, account.busy ? t("account.checking") : t("account.check")), account.status?.state !== "signed_out" && h("button", {
6223
6315
  type: "button",
6224
6316
  disabled: Boolean(account.busy),
6225
6317
  style: button,
6226
6318
  onClick: () => account.run("logout", () => service.logout(profile.id))
6227
- }, messages.logout), profile.brand?.supportURL && h("a", {
6319
+ }, t("account.logout")), profile.brand?.supportURL && h("a", {
6228
6320
  href: profile.brand.supportURL,
6229
6321
  target: "_blank",
6230
6322
  rel: "noopener noreferrer",
@@ -6232,24 +6324,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6232
6324
  ...button,
6233
6325
  textDecoration: "none"
6234
6326
  }
6235
- }, messages.help)), login.pending && h("p", { role: "status" }, messages.waiting, " ", h("button", {
6327
+ }, t("account.help"))), login.pending && h("p", { role: "status" }, t("account.waiting"), " ", h("button", {
6236
6328
  type: "button",
6237
6329
  style: button,
6238
6330
  onClick: login.cancel
6239
- }, messages.cancelLogin)), account.error && h("p", {
6331
+ }, t("account.cancelLogin"))), account.error && h("p", {
6240
6332
  role: "alert",
6241
6333
  style: {
6242
6334
  margin: "10px 0 0",
6243
- color: "#a82332",
6335
+ color: "var(--dsw-alias-state-error-primary, #a82332)",
6244
6336
  fontSize: 12
6245
6337
  }
6246
6338
  }, account.error), h("p", { style: {
6247
6339
  margin: "10px 0 0",
6248
6340
  color: "var(--dsw-alias-label-tertiary)",
6249
6341
  fontSize: 11
6250
- } }, profile.provider ? `${profile.provider.displayName} · ${profile.provider.models.map((model) => model.name).join("、")}` : messages.other));
6342
+ } }, profile.provider ? `${profile.provider.displayName} · ${profile.provider.models.map((model) => model.name).join("、")}` : t("account.other")));
6251
6343
  }
6252
- function EnterpriseOnboarding({ service, configuration, complete }) {
6344
+ function EnterpriseOnboarding({ t, service, configuration, complete }) {
6253
6345
  const profile = configuration.profiles[0];
6254
6346
  const account = useAccount(service, profile.id);
6255
6347
  (0, react.useEffect)(() => {
@@ -6264,7 +6356,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6264
6356
  if (account.status === null || account.status?.state === "connected" && !account.busy && !account.error) return null;
6265
6357
  const primary = {
6266
6358
  ...button,
6267
- background: profile.brand?.primaryColor || "var(--dsw-alias-brand-primary, #5157af)",
6359
+ background: profile.brand?.primaryColor || "var(--dsw-alias-state-business-primary, #5157af)",
6268
6360
  color: "white",
6269
6361
  borderColor: "transparent"
6270
6362
  };
@@ -6282,7 +6374,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6282
6374
  } }, h("section", {
6283
6375
  role: "dialog",
6284
6376
  "aria-modal": "true",
6285
- "aria-label": profile.brand?.loginTitle || messages.dialog,
6377
+ "aria-label": profile.brand?.loginTitle || t("account.dialog"),
6286
6378
  style: {
6287
6379
  boxSizing: "border-box",
6288
6380
  width: "min(540px, 100%)",
@@ -6306,7 +6398,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6306
6398
  margin: 0,
6307
6399
  fontSize: 20,
6308
6400
  fontWeight: 650
6309
- } }, profile.brand?.loginTitle || messages.dialog), h("div", { style: {
6401
+ } }, profile.brand?.loginTitle || t("account.dialog")), h("div", { style: {
6310
6402
  marginTop: 3,
6311
6403
  color: "var(--dsw-alias-label-secondary)",
6312
6404
  fontSize: 12
@@ -6315,7 +6407,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6315
6407
  color: "var(--dsw-alias-label-secondary)",
6316
6408
  fontSize: 13,
6317
6409
  lineHeight: 1.7
6318
- } }, profile.brand?.loginDescription || (profile.provider ? messages.shortDescription : messages.identityDescription)), h("div", { style: {
6410
+ } }, profile.brand?.loginDescription || (profile.provider ? t("account.shortDescription") : t("account.identityDescription"))), h("div", { style: {
6319
6411
  marginTop: 20,
6320
6412
  display: "flex",
6321
6413
  gap: 9,
@@ -6325,20 +6417,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6325
6417
  disabled: Boolean(account.busy),
6326
6418
  style: primary,
6327
6419
  onClick: account.status?.state === "connected" ? () => account.run("select", () => service.useModels(profile.id)) : begin
6328
- }, account.busy ? messages.connecting : account.status?.state === "connected" ? isChinese ? "使用企业模型" : "Use organization model" : messages.login), h("button", {
6420
+ }, account.busy ? t("account.connecting") : account.status?.state === "connected" ? t("account.useModels") : profile.brand?.loginButtonLabel || t("account.login")), h("button", {
6329
6421
  type: "button",
6330
6422
  disabled: Boolean(account.busy),
6331
6423
  style: button,
6332
6424
  onClick: complete
6333
- }, messages.other)), login.pending && h("p", { role: "status" }, messages.waiting, " ", h("button", {
6425
+ }, t("account.other"))), login.pending && h("p", { role: "status" }, t("account.waiting"), " ", h("button", {
6334
6426
  type: "button",
6335
6427
  style: button,
6336
6428
  onClick: login.cancel
6337
- }, messages.cancelLogin)), account.error && h("p", {
6429
+ }, t("account.cancelLogin"))), account.error && h("p", {
6338
6430
  role: "alert",
6339
6431
  style: {
6340
6432
  margin: "12px 0 0",
6341
- color: "#a82332",
6433
+ color: "var(--dsw-alias-state-error-primary, #a82332)",
6342
6434
  fontSize: 12
6343
6435
  }
6344
6436
  }, account.error), h("p", { style: {
@@ -6346,14 +6438,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6346
6438
  color: "var(--dsw-alias-label-tertiary)",
6347
6439
  fontSize: 11,
6348
6440
  lineHeight: 1.55
6349
- } }, profile.provider ? `${messages.enabled} ${profile.provider.displayName}: ${profile.provider.models.map((model) => model.name).join("、")}` : messages.other)));
6441
+ } }, profile.provider ? `${t("account.enabled")} ${profile.provider.displayName}: ${profile.provider.models.map((model) => model.name).join("、")}` : t("account.other"))));
6350
6442
  }
6351
- function FooterAccount({ service, configuration, renderSlot, wide = true }) {
6443
+ function FooterAccount({ t, service, configuration, renderSlot, wide = true }) {
6352
6444
  const profile = configuration.profiles[0];
6353
6445
  const status = useAccountStatus(service, profile.id);
6354
6446
  const userName = accountUserName(status);
6355
- const statusLabel = status?.state === "connected" ? profile.provider ? messages.footerConnected : messages.identityConnected : messages.footerSetup;
6447
+ const statusLabel = status?.state === "connected" ? profile.provider ? t("account.footerConnected") : t("account.identityConnected") : t("account.footerSetup");
6356
6448
  return h(AccountMenu, {
6449
+ t,
6357
6450
  service,
6358
6451
  profile,
6359
6452
  renderSlot,
@@ -6378,6 +6471,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6378
6471
  } }, accountStatusLine(profile, statusLabel, userName)))));
6379
6472
  }
6380
6473
  async function apply(ctx) {
6474
+ ctx.effect(() => ctx.locale.register(NS, dictionaries), "oidc: dictionaries");
6475
+ const t = ctx.locale.bind(NS);
6476
+ const unwrap = (operation) => unwrapResult(operation, t);
6381
6477
  const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE);
6382
6478
  ctx.inject(["remote.oidcAccounts"], (surfaceCtx) => {
6383
6479
  let cancelled = false;
@@ -6419,6 +6515,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6419
6515
  disposers.push(surfaceCtx.slots.inject("settings.models.footer", () => surfaceCtx.slots.register({
6420
6516
  name: "settings.models.footer",
6421
6517
  id: "dsh-oidc-enterprise",
6518
+ locale: NS,
6422
6519
  order: -100,
6423
6520
  inject: () => ({
6424
6521
  service,
@@ -6430,6 +6527,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6430
6527
  disposers.push(surfaceCtx.slots.inject("settings.onboarding", () => surfaceCtx.slots.register({
6431
6528
  name: "settings.onboarding",
6432
6529
  id: "dsh-oidc-enterprise",
6530
+ locale: NS,
6433
6531
  order: -10,
6434
6532
  inject: () => ({
6435
6533
  service,
@@ -6439,6 +6537,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6439
6537
  disposers.push(surfaceCtx.slots.inject("sidebar.footer.action", () => surfaceCtx.slots.register({
6440
6538
  name: "sidebar.footer.action",
6441
6539
  id: "dsh-oidc-account",
6540
+ locale: NS,
6442
6541
  order: -90,
6443
6542
  children: { "oidc.account.menu.details": {
6444
6543
  kind: "single",
@@ -6452,6 +6551,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6452
6551
  disposers.push(surfaceCtx.slots.inject("settings.general.item", () => surfaceCtx.slots.register({
6453
6552
  name: "settings.general.item",
6454
6553
  id: "dsh-oidc-account",
6554
+ locale: NS,
6455
6555
  order: 10,
6456
6556
  inject: () => ({
6457
6557
  service,