@khorsheed/dsh-local-agent-kimi 0.2.0-rc.1 → 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.
- package/CHANGELOG.md +26 -0
- package/README.en.md +24 -112
- package/README.i18n.yaml +2 -2
- package/README.md +24 -112
- package/lib/client.js +816 -324
- package/lib/index.js +2121 -1311
- package/lib/types/client/SettingsCard.d.ts +75 -24
- package/lib/types/client/SettingsCard.js +110 -137
- package/lib/types/client/icons.d.ts +1 -1
- package/lib/types/client/index.d.ts +6 -25
- package/lib/types/client/index.js +134 -51
- package/lib/types/client/locales.d.ts +34 -24
- package/lib/types/client/locales.js +38 -28
- package/lib/types/endpoint-auth.d.ts +202 -0
- package/lib/types/endpoint-auth.js +287 -0
- package/lib/types/index.d.ts +19 -2
- package/lib/types/index.js +146 -19
- package/lib/types/kimi-cli-provider.d.ts +31 -4
- package/lib/types/kimi-cli-provider.js +110 -60
- package/lib/types/live-driver.d.ts +17 -5
- package/lib/types/live-driver.js +345 -129
- package/lib/types/live-switch.d.ts +16 -1
- package/lib/types/live-switch.js +11 -1
- package/lib/types/model-broker.d.ts +12 -2
- package/lib/types/model-broker.js +51 -6
- package/lib/types/model-catalog.d.ts +44 -1
- package/lib/types/model-catalog.js +110 -17
- package/lib/types/model-configuration.d.ts +26 -0
- package/lib/types/model-configuration.js +43 -0
- package/lib/types/provision.d.ts +102 -31
- package/lib/types/provision.js +257 -45
- package/lib/types/records.d.ts +0 -20
- package/lib/types/records.js +1 -40
- package/lib/types/session-mirror.d.ts +115 -52
- package/lib/types/session-mirror.js +286 -210
- package/lib/types/session-view.d.ts +23 -2
- package/lib/types/session-view.js +37 -7
- package/locale/en.json +2 -2
- package/locale/zh.json +2 -2
- package/package.json +21 -22
- package/lib/invariant.js +0 -31
- package/lib/types/credential-guard.d.ts +0 -29
- package/lib/types/credential-guard.js +0 -107
- package/lib/types/invariant.d.ts +0 -16
- package/lib/types/invariant.js +0 -33
package/lib/client.js
CHANGED
|
@@ -100,23 +100,28 @@ window.__ModuleLoader__.load({
|
|
|
100
100
|
const NS = "local-agent-kimi";
|
|
101
101
|
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
102
102
|
const zh = {
|
|
103
|
-
"card.title": "
|
|
104
|
-
"card.description": "Kimi Code
|
|
103
|
+
"card.title": "本机 Kimi 委派",
|
|
104
|
+
"card.description": "Kimi Code 委派:端点凭据与常驻模式(live)",
|
|
105
105
|
"card.expand": "展开",
|
|
106
106
|
"card.collapse": "收起",
|
|
107
107
|
"auth.title": "认证",
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
108
|
+
"endpoint.info.aria": "端点凭据说明",
|
|
109
|
+
"endpoint.info": "这里保存的就是默认 scope 的 endpoint-auth.json(0600,只存本机),它优先于 profile 的 YAML 配置行;宿主 shell 的环境变量从不被读取。kimi 的 managed provider 经 `api_key_env` 从子进程环境读 key——密钥不落 config.toml(它要进评测条件指纹)、绝不写进 profile 文件。端点地址留空 = kimi 官方服务。没有网页登录:容器轮与宿主轮用同一套凭据,容器里不需要再授权一次。保存对下一轮委派生效,进行中的轮次不受影响。",
|
|
110
|
+
"endpoint.baseUrl": "端点地址(baseUrl)",
|
|
111
|
+
"endpoint.baseUrl.placeholder": "留空 = kimi 官方服务",
|
|
112
|
+
"endpoint.apiKey": "API Key",
|
|
113
|
+
"endpoint.secret.configured": "已配置 · 输入新值更换,留空保存 = 清除",
|
|
114
|
+
"endpoint.secret.placeholder": "未配置",
|
|
115
|
+
"endpoint.configured": "已配置",
|
|
116
|
+
"endpoint.save": "保存凭据",
|
|
117
|
+
"endpoint.applied": "已保存,下一轮委派生效;进行中的轮次不受影响",
|
|
118
|
+
"endpoint.error": "保存失败,请重试",
|
|
119
|
+
"endpoint.check": "验证端点并获取模型",
|
|
120
|
+
"endpoint.checking": "验证中…",
|
|
121
|
+
"endpoint.checkDirtyHint": "有未保存的修改,先保存凭据再验证",
|
|
122
|
+
"endpoint.checkUnavailable": "当前核心不支持端点验证(请升级 local-agent 核心包)",
|
|
123
|
+
"endpoint.unavailable": "当前核心不支持凭据配置(请升级 local-agent 核心包)",
|
|
124
|
+
"endpoint.checkFailed": "验证失败,请重试",
|
|
120
125
|
"live.title": "常驻模式(live)",
|
|
121
126
|
"live.info.aria": "常驻模式说明",
|
|
122
127
|
"live.info": "常驻模式 = 成员进程常驻:输出实时流入成员会话、取消不杀进程、崩溃后自动续上原会话;关闭则每轮独立进程,跑完一次性出结果。设置为全局偏好,对所有后续委派生效。",
|
|
@@ -126,23 +131,28 @@ window.__ModuleLoader__.load({
|
|
|
126
131
|
};
|
|
127
132
|
/** English dictionary, checked complete against the zh key set. */
|
|
128
133
|
const en = {
|
|
129
|
-
"card.title": "Local
|
|
130
|
-
"card.description": "Kimi Code delegation:
|
|
134
|
+
"card.title": "Local Kimi Delegation",
|
|
135
|
+
"card.description": "Kimi Code delegation: endpoint credential and resident (live) mode",
|
|
131
136
|
"card.expand": "Expand",
|
|
132
137
|
"card.collapse": "Collapse",
|
|
133
138
|
"auth.title": "Authentication",
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
139
|
+
"endpoint.info.aria": "About the endpoint credential",
|
|
140
|
+
"endpoint.info": "What you save here is the default scope's endpoint-auth.json (mode 0600, local only), which outranks the profile's YAML row; the host shell's environment is never read. Kimi's managed provider reads the key through its `api_key_env` indirection from the child process's environment — the key never lands in config.toml (an evaluation-condition input) nor in the profile document. A blank endpoint means kimi's own service. There is no web login: container rounds share the host's credential and nothing is authorized inside a container. Saving applies to the next delegation round; rounds in flight are unaffected.",
|
|
141
|
+
"endpoint.baseUrl": "Endpoint (baseUrl)",
|
|
142
|
+
"endpoint.baseUrl.placeholder": "Blank = kimi's own service",
|
|
143
|
+
"endpoint.apiKey": "API Key",
|
|
144
|
+
"endpoint.secret.configured": "Configured · type to replace, save blank to clear",
|
|
145
|
+
"endpoint.secret.placeholder": "Not configured",
|
|
146
|
+
"endpoint.configured": "Configured",
|
|
147
|
+
"endpoint.save": "Save credential",
|
|
148
|
+
"endpoint.applied": "Saved — takes effect on the next delegation round; rounds in flight are unaffected",
|
|
149
|
+
"endpoint.error": "Save failed, please retry",
|
|
150
|
+
"endpoint.check": "Verify endpoint & list models",
|
|
151
|
+
"endpoint.checking": "Verifying…",
|
|
152
|
+
"endpoint.checkDirtyHint": "Unsaved changes — save the credential before verifying",
|
|
153
|
+
"endpoint.checkUnavailable": "This core cannot verify endpoints (upgrade the local-agent core package)",
|
|
154
|
+
"endpoint.unavailable": "This core cannot configure credentials (upgrade the local-agent core package)",
|
|
155
|
+
"endpoint.checkFailed": "Verification failed, please retry",
|
|
146
156
|
"live.title": "Resident mode (live)",
|
|
147
157
|
"live.info.aria": "About resident mode",
|
|
148
158
|
"live.info": "Resident mode keeps the member process alive: output streams into the member session in real time, cancelling does not kill the process, and a crash resumes the same session. Off means every round runs as an independent one-shot process. The setting is global and applies to every later delegation.",
|
|
@@ -207,6 +217,14 @@ window.__ModuleLoader__.load({
|
|
|
207
217
|
};
|
|
208
218
|
}
|
|
209
219
|
/**
|
|
220
|
+
* Subscribe one harness's published status (no probe of its own): a sibling
|
|
221
|
+
* surface that WRITES the credential (the endpoint form's save) publishes
|
|
222
|
+
* through the same bus, and every block showing the status flips at once.
|
|
223
|
+
*/
|
|
224
|
+
function usePublishedAuthStatus(harnessId) {
|
|
225
|
+
return (0, react.useSyncExternalStore)(subscribe, () => statuses.get(harnessId));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
210
228
|
* Read one harness's latest known auth status. Every mount probes once and
|
|
211
229
|
* publishes — a published value only snapshots the past (a credential expiring
|
|
212
230
|
* mid-session must flip the dot at the next view, not stay green forever);
|
|
@@ -233,40 +251,40 @@ window.__ModuleLoader__.load({
|
|
|
233
251
|
}
|
|
234
252
|
//#endregion
|
|
235
253
|
//#region \0dsh-css:../local-agent/src/client/ProviderAuthBlock.module.css.mjs
|
|
236
|
-
const css$
|
|
237
|
-
const tagId$
|
|
238
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
254
|
+
const css$3 = ".On5p7W_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:4px;display:flex}.On5p7W_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.On5p7W_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.On5p7W_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.On5p7W_rowCard{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:10px;padding:12px 14px;display:flex}.On5p7W_rowPending{opacity:.6}.On5p7W_rowHead{align-items:center;gap:10px;display:flex}.On5p7W_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.On5p7W_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.On5p7W_rowTag{border:1px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.On5p7W_credentialDot{box-sizing:border-box;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.On5p7W_dotOn{background:var(--dsw-alias-state-success-primary)}.On5p7W_dotOff{background:var(--dsw-alias-state-error-primary)}.On5p7W_dotPending{background:var(--dsw-alias-fill-l3)}.On5p7W_status{color:var(--dsw-alias-label-tertiary);flex:none;margin-left:auto;font-size:12px;line-height:18px}.On5p7W_rowActions{align-items:center;gap:4px;display:inline-flex}.On5p7W_loginButton{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:14px;justify-content:center;align-items:center;padding:0 12px;font-size:12px;line-height:18px;display:inline-flex}.On5p7W_loginButton:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3)}.On5p7W_loginButton:disabled{color:var(--dsw-alias-label-tertiary);border-color:var(--dsw-alias-border-l2);cursor:not-allowed}.On5p7W_logoutButton{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);height:28px;color:var(--dsw-alias-state-error-primary);cursor:pointer;background:0 0;border-radius:14px;justify-content:center;align-items:center;padding:0 12px;font-size:12px;line-height:18px;display:inline-flex}.On5p7W_logoutButton:hover{border-color:var(--dsw-alias-state-error-primary)}.On5p7W_rosterError{color:var(--dsw-alias-state-error-primary);align-items:center;gap:10px;margin:8px 0 0;font-size:12px;line-height:18px;display:flex}.On5p7W_retryButton{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);height:24px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:12px;justify-content:center;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.On5p7W_retryButton:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3)}.On5p7W_loginPrompt{align-items:flex-start;gap:10px;display:flex}.On5p7W_promptText{min-width:0;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;flex:1;font-size:12px;line-height:18px}.On5p7W_codeInput{border:1px solid var(--dsw-alias-line-normal,currentColor);min-width:0;color:inherit;background:0 0;border-radius:6px;flex:1;padding:4px 8px;font-size:12px;line-height:18px}.On5p7W_openPage{color:var(--dsw-alias-accent-link);flex:none;font-size:12px;line-height:18px;text-decoration:none}.On5p7W_openPage:hover{text-decoration:underline}";
|
|
255
|
+
const tagId$3 = "@khorsheed/dsh-local-agent-kimi/ProviderAuthBlock.module.css";
|
|
256
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
239
257
|
const tag = document.createElement("style");
|
|
240
258
|
tag.dataset.plugin = "@khorsheed/dsh-local-agent-kimi";
|
|
241
|
-
tag.dataset.pluginCss = tagId$
|
|
242
|
-
tag.textContent = css$
|
|
259
|
+
tag.dataset.pluginCss = tagId$3;
|
|
260
|
+
tag.textContent = css$3;
|
|
243
261
|
document.head.appendChild(tag);
|
|
244
262
|
}
|
|
245
263
|
var ProviderAuthBlock_module_css_default = {
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
"
|
|
249
|
-
"
|
|
264
|
+
"title": "On5p7W_title",
|
|
265
|
+
"rowName": "On5p7W_rowName",
|
|
266
|
+
"rowCard": "On5p7W_rowCard",
|
|
267
|
+
"rowActions": "On5p7W_rowActions",
|
|
268
|
+
"retryButton": "On5p7W_retryButton",
|
|
269
|
+
"credentialDot": "On5p7W_credentialDot",
|
|
270
|
+
"rowTag": "On5p7W_rowTag",
|
|
271
|
+
"dotPending": "On5p7W_dotPending",
|
|
272
|
+
"codeInput": "On5p7W_codeInput",
|
|
250
273
|
"rows": "On5p7W_rows",
|
|
251
|
-
"intro": "On5p7W_intro",
|
|
252
274
|
"promptText": "On5p7W_promptText",
|
|
275
|
+
"rowHead": "On5p7W_rowHead",
|
|
253
276
|
"section": "On5p7W_section",
|
|
277
|
+
"status": "On5p7W_status",
|
|
254
278
|
"rosterError": "On5p7W_rosterError",
|
|
279
|
+
"intro": "On5p7W_intro",
|
|
280
|
+
"rowIdentity": "On5p7W_rowIdentity",
|
|
281
|
+
"dotOn": "On5p7W_dotOn",
|
|
282
|
+
"loginButton": "On5p7W_loginButton",
|
|
283
|
+
"logoutButton": "On5p7W_logoutButton",
|
|
255
284
|
"loginPrompt": "On5p7W_loginPrompt",
|
|
256
|
-
"dotOff": "On5p7W_dotOff",
|
|
257
|
-
"rowCard": "On5p7W_rowCard",
|
|
258
|
-
"credentialDot": "On5p7W_credentialDot",
|
|
259
|
-
"status": "On5p7W_status",
|
|
260
|
-
"rowHead": "On5p7W_rowHead",
|
|
261
|
-
"dotPending": "On5p7W_dotPending",
|
|
262
|
-
"codeInput": "On5p7W_codeInput",
|
|
263
|
-
"rowTag": "On5p7W_rowTag",
|
|
264
285
|
"openPage": "On5p7W_openPage",
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
-
"retryButton": "On5p7W_retryButton",
|
|
268
|
-
"title": "On5p7W_title",
|
|
269
|
-
"rowActions": "On5p7W_rowActions"
|
|
286
|
+
"dotOff": "On5p7W_dotOff",
|
|
287
|
+
"rowPending": "On5p7W_rowPending"
|
|
270
288
|
};
|
|
271
289
|
//#endregion
|
|
272
290
|
//#region ../local-agent/src/client/ProviderAuthBlock.tsx
|
|
@@ -300,12 +318,13 @@ window.__ModuleLoader__.load({
|
|
|
300
318
|
* for the retainedBy.mainView count on each summary (the label is ui-session's
|
|
301
319
|
* declaration merge, read here as a plain duck-typed count so this package
|
|
302
320
|
* needs no ui-session edge), with the legacy field as the older-host fallback.
|
|
321
|
+
* Exported for sibling cards that run slash commands from their own rows.
|
|
303
322
|
*/
|
|
304
323
|
const mainSessionId = (list) => Object.values(list.byId ?? {}).find((session) => (session.retainedBy?.mainView ?? 0) > 0)?.id ?? list.current;
|
|
305
324
|
/**
|
|
306
325
|
* One harness's auth interactions, shared between the per-provider settings
|
|
307
|
-
* cards (
|
|
308
|
-
*
|
|
326
|
+
* cards (each a `plugins.item` entry on the Plugins page, registered while
|
|
327
|
+
* the Host serves the provider's namespace): auth status through
|
|
309
328
|
* the read-only Remote channel and a web-login action that runs
|
|
310
329
|
* `/<harness> login`, surfaces the device-code prompt, and offers a link to
|
|
311
330
|
* the authorization page. The login command returns at prompt time while the
|
|
@@ -338,7 +357,8 @@ window.__ModuleLoader__.load({
|
|
|
338
357
|
const capabilities = probe === void 0 ? {} : {
|
|
339
358
|
loginable: probe.loginable ?? true,
|
|
340
359
|
logoutable: probe.logoutable ?? true,
|
|
341
|
-
...probe.loginAwaitingCode === true ? { loginAwaitingCode: true } : {}
|
|
360
|
+
...probe.loginAwaitingCode === true ? { loginAwaitingCode: true } : {},
|
|
361
|
+
...probe.effectiveSettings?.cliVersion === void 0 ? {} : { cliVersion: probe.effectiveSettings.cliVersion }
|
|
342
362
|
};
|
|
343
363
|
setView((prev) => statusKind === "authenticated" ? {
|
|
344
364
|
status: statusKind,
|
|
@@ -414,7 +434,7 @@ window.__ModuleLoader__.load({
|
|
|
414
434
|
setView({ status: "unavailable" });
|
|
415
435
|
});
|
|
416
436
|
};
|
|
417
|
-
const statusKind = view.status;
|
|
437
|
+
const statusKind = usePublishedAuthStatus(harness.id) ?? view.status;
|
|
418
438
|
const authenticated = statusKind === "authenticated";
|
|
419
439
|
const loginPending = pendingSince !== void 0;
|
|
420
440
|
const loginable = view.loginable ?? true;
|
|
@@ -438,6 +458,10 @@ window.__ModuleLoader__.load({
|
|
|
438
458
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
439
459
|
className: ProviderAuthBlock_module_css_default.rowTag,
|
|
440
460
|
children: harness.id
|
|
461
|
+
}),
|
|
462
|
+
view.cliVersion !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
463
|
+
className: ProviderAuthBlock_module_css_default.rowTag,
|
|
464
|
+
children: view.cliVersion
|
|
441
465
|
})
|
|
442
466
|
]
|
|
443
467
|
}),
|
|
@@ -529,20 +553,20 @@ window.__ModuleLoader__.load({
|
|
|
529
553
|
}
|
|
530
554
|
//#endregion
|
|
531
555
|
//#region \0dsh-css:../local-agent/src/client/AuthStatusDot.module.css.mjs
|
|
532
|
-
const css$
|
|
533
|
-
const tagId$
|
|
534
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
556
|
+
const css$2 = ".OFjNUG_credentialDot{box-sizing:border-box;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.OFjNUG_dotOn{background:var(--dsw-alias-state-success-primary)}.OFjNUG_dotOff{background:var(--dsw-alias-state-error-primary)}.OFjNUG_dotPending{background:var(--dsw-alias-fill-l3)}";
|
|
557
|
+
const tagId$2 = "@khorsheed/dsh-local-agent-kimi/AuthStatusDot.module.css";
|
|
558
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
535
559
|
const tag = document.createElement("style");
|
|
536
560
|
tag.dataset.plugin = "@khorsheed/dsh-local-agent-kimi";
|
|
537
|
-
tag.dataset.pluginCss = tagId$
|
|
538
|
-
tag.textContent = css$
|
|
561
|
+
tag.dataset.pluginCss = tagId$2;
|
|
562
|
+
tag.textContent = css$2;
|
|
539
563
|
document.head.appendChild(tag);
|
|
540
564
|
}
|
|
541
565
|
var AuthStatusDot_module_css_default = {
|
|
542
|
-
"
|
|
566
|
+
"dotPending": "OFjNUG_dotPending",
|
|
543
567
|
"credentialDot": "OFjNUG_credentialDot",
|
|
544
|
-
"
|
|
545
|
-
"
|
|
568
|
+
"dotOff": "OFjNUG_dotOff",
|
|
569
|
+
"dotOn": "OFjNUG_dotOn"
|
|
546
570
|
};
|
|
547
571
|
//#endregion
|
|
548
572
|
//#region ../local-agent/src/client/AuthStatusDot.tsx
|
|
@@ -557,8 +581,412 @@ window.__ModuleLoader__.load({
|
|
|
557
581
|
});
|
|
558
582
|
}
|
|
559
583
|
//#endregion
|
|
584
|
+
//#region \0dsh-css:../local-agent/src/client/ModelListSection.module.css.mjs
|
|
585
|
+
const css$1 = "._4eeJ7W_block{flex-direction:column;gap:10px;display:flex}._4eeJ7W_blockTitle{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;margin:0;font-size:13px;font-weight:500;line-height:1.4;display:flex}._4eeJ7W_info{appearance:none;color:var(--dsw-alias-label-tertiary);cursor:help;background:0 0;border:0;border-radius:50%;padding:0 2px;font-size:12px;line-height:1}._4eeJ7W_row{align-items:center;gap:12px;display:flex}._4eeJ7W_saved{color:var(--dsw-alias-state-success-primary);font-size:12px}._4eeJ7W_errorText{color:var(--dsw-alias-state-error-primary);font-size:12px}._4eeJ7W_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}._4eeJ7W_modelInput{min-width:0;font:inherit;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:5px 8px;font-size:13px;line-height:1.4}._4eeJ7W_modelSave{appearance:none;font:inherit;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:8px;flex:none;padding:5px 10px;font-size:13px;line-height:1.4}._4eeJ7W_modelList{flex-direction:column;gap:8px;display:flex}._4eeJ7W_modelRow{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:grab;border-radius:8px;align-items:center;gap:8px;padding:6px 8px;display:flex}._4eeJ7W_modelRowDragging{opacity:.6;cursor:grabbing}._4eeJ7W_modelDrag{color:var(--dsw-alias-label-tertiary);cursor:grab;user-select:none}._4eeJ7W_modelRowValue{font-size:13px;font-family:var(--dsw-alias-font-mono,monospace);color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}._4eeJ7W_modelRowLabel{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;max-width:40%;font-size:12px;overflow:hidden}._4eeJ7W_modelDefaultChip{color:var(--dsw-alias-success,#1a9e54);background:color-mix(in srgb, var(--dsw-alias-success,#1a9e54) 12%, transparent);border-radius:999px;padding:1px 8px;font-size:11px;line-height:1.4}._4eeJ7W_modelDelete{appearance:none;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;padding:2px 4px;font-size:12px}._4eeJ7W_modelAdd{appearance:none;border:1px dashed var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:5px 12px;font-size:13px}._4eeJ7W_dialogBackdrop{z-index:100;background:#00000052;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}._4eeJ7W_dialog{background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;flex-direction:column;gap:10px;width:min(520px,100vw - 48px);max-height:min(560px,100vh - 96px);padding:16px;display:flex;box-shadow:0 12px 40px #00000059}._4eeJ7W_dialogHead{justify-content:space-between;align-items:center;display:flex}._4eeJ7W_dialogTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;font-weight:600}._4eeJ7W_dialogClose{appearance:none;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:4px;padding:2px 4px;font-size:13px}._4eeJ7W_dialogHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px}._4eeJ7W_dialogToolbar{align-items:center;gap:8px;display:flex}._4eeJ7W_dialogToolbar ._4eeJ7W_modelInput{flex:1}._4eeJ7W_dialogSelectAll{appearance:none;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;padding:4px 6px;font-size:13px}._4eeJ7W_dialogList{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;flex-direction:column;flex:1;gap:2px;min-height:120px;max-height:320px;padding:6px;display:flex;overflow-y:auto}._4eeJ7W_dialogItem{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}._4eeJ7W_dialogItemAdded{opacity:.55;cursor:default}._4eeJ7W_dialogItemValue{font-family:var(--dsw-alias-font-mono,monospace)}._4eeJ7W_dialogItemLabel{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}._4eeJ7W_dialogActions{justify-content:flex-end;gap:8px;display:flex}._4eeJ7W_dialogConfirm{appearance:none;color:var(--dsw-alias-text-on-brand,#fff);background:var(--dsw-alias-brand-primary);cursor:pointer;border:0;border-radius:8px;padding:6px 14px;font-size:13px}";
|
|
586
|
+
const tagId$1 = "@khorsheed/dsh-local-agent-kimi/ModelListSection.module.css";
|
|
587
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
588
|
+
const tag = document.createElement("style");
|
|
589
|
+
tag.dataset.plugin = "@khorsheed/dsh-local-agent-kimi";
|
|
590
|
+
tag.dataset.pluginCss = tagId$1;
|
|
591
|
+
tag.textContent = css$1;
|
|
592
|
+
document.head.appendChild(tag);
|
|
593
|
+
}
|
|
594
|
+
var ModelListSection_module_css_default = {
|
|
595
|
+
"dialogConfirm": "_4eeJ7W_dialogConfirm",
|
|
596
|
+
"modelDelete": "_4eeJ7W_modelDelete",
|
|
597
|
+
"dialogItemLabel": "_4eeJ7W_dialogItemLabel",
|
|
598
|
+
"modelDrag": "_4eeJ7W_modelDrag",
|
|
599
|
+
"modelRowValue": "_4eeJ7W_modelRowValue",
|
|
600
|
+
"modelRow": "_4eeJ7W_modelRow",
|
|
601
|
+
"dialogItemAdded": "_4eeJ7W_dialogItemAdded",
|
|
602
|
+
"modelSave": "_4eeJ7W_modelSave",
|
|
603
|
+
"modelInput": "_4eeJ7W_modelInput",
|
|
604
|
+
"blockTitle": "_4eeJ7W_blockTitle",
|
|
605
|
+
"row": "_4eeJ7W_row",
|
|
606
|
+
"block": "_4eeJ7W_block",
|
|
607
|
+
"saved": "_4eeJ7W_saved",
|
|
608
|
+
"dialog": "_4eeJ7W_dialog",
|
|
609
|
+
"hint": "_4eeJ7W_hint",
|
|
610
|
+
"dialogItem": "_4eeJ7W_dialogItem",
|
|
611
|
+
"info": "_4eeJ7W_info",
|
|
612
|
+
"dialogBackdrop": "_4eeJ7W_dialogBackdrop",
|
|
613
|
+
"dialogItemValue": "_4eeJ7W_dialogItemValue",
|
|
614
|
+
"dialogHint": "_4eeJ7W_dialogHint",
|
|
615
|
+
"dialogHead": "_4eeJ7W_dialogHead",
|
|
616
|
+
"dialogList": "_4eeJ7W_dialogList",
|
|
617
|
+
"dialogToolbar": "_4eeJ7W_dialogToolbar",
|
|
618
|
+
"errorText": "_4eeJ7W_errorText",
|
|
619
|
+
"modelDefaultChip": "_4eeJ7W_modelDefaultChip",
|
|
620
|
+
"modelRowDragging": "_4eeJ7W_modelRowDragging",
|
|
621
|
+
"modelList": "_4eeJ7W_modelList",
|
|
622
|
+
"modelRowLabel": "_4eeJ7W_modelRowLabel",
|
|
623
|
+
"modelAdd": "_4eeJ7W_modelAdd",
|
|
624
|
+
"dialogTitle": "_4eeJ7W_dialogTitle",
|
|
625
|
+
"dialogActions": "_4eeJ7W_dialogActions",
|
|
626
|
+
"dialogSelectAll": "_4eeJ7W_dialogSelectAll",
|
|
627
|
+
"dialogClose": "_4eeJ7W_dialogClose"
|
|
628
|
+
};
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region ../local-agent/src/client/ModelListSection.tsx
|
|
631
|
+
/**
|
|
632
|
+
* The family's shared「可用模型」section: an ORDERED shortlist of
|
|
633
|
+
* endpoint-served models — the first entry is the default model every
|
|
634
|
+
* delegation round starts with. Rows drag to reorder and delete per row;
|
|
635
|
+
* "add model" opens a dialog over the endpoint's served catalog (search +
|
|
636
|
+
* checkboxes), so the list can only ever contain what the endpoint actually
|
|
637
|
+
* serves. An empty list falls back to the pre-list chain (the settings
|
|
638
|
+
* model key, the scoped config file, then the CLI's own default). Every
|
|
639
|
+
* edit persists immediately through the harness's model-list face (the
|
|
640
|
+
* gateway's `modelList`/`configureModelList` Remotes).
|
|
641
|
+
*
|
|
642
|
+
* One implementation serves every companion card (claude-code, codex,
|
|
643
|
+
* kimi): the section owns its state (list read on activate, immediate
|
|
644
|
+
* writes, the catalog read behind the add dialog) so each card's
|
|
645
|
+
* integration is the two faces plus copy — the interaction cannot drift
|
|
646
|
+
* between harnesses. Copy lives in the family core's own dictionary.
|
|
647
|
+
* @module @khorsheed/dsh-local-agent/client — model list section
|
|
648
|
+
*/
|
|
649
|
+
/** The section's staged state: the list and the catalog behind the add dialog. */
|
|
650
|
+
function useModelListState(active, modelList, modelDirectory, directoryRefresh) {
|
|
651
|
+
const unavailable = modelList === void 0;
|
|
652
|
+
const [models, setModels] = (0, react.useState)([]);
|
|
653
|
+
const [saved, setSaved] = (0, react.useState)(false);
|
|
654
|
+
const [error, setError] = (0, react.useState)(false);
|
|
655
|
+
(0, react.useEffect)(() => {
|
|
656
|
+
if (!active || modelList === void 0) return;
|
|
657
|
+
let stale = false;
|
|
658
|
+
modelList.read().then((list) => {
|
|
659
|
+
if (!stale) setModels(list ?? []);
|
|
660
|
+
}, () => {
|
|
661
|
+
if (!stale) setModels([]);
|
|
662
|
+
});
|
|
663
|
+
return () => {
|
|
664
|
+
stale = true;
|
|
665
|
+
};
|
|
666
|
+
}, [active, modelList]);
|
|
667
|
+
const [directory, setDirectory] = (0, react.useState)(null);
|
|
668
|
+
(0, react.useEffect)(() => {
|
|
669
|
+
if (!active || modelDirectory === void 0) return;
|
|
670
|
+
let stale = false;
|
|
671
|
+
modelDirectory(true).then((result) => {
|
|
672
|
+
if (!stale) setDirectory(result ?? null);
|
|
673
|
+
}, () => {
|
|
674
|
+
if (!stale) setDirectory(null);
|
|
675
|
+
});
|
|
676
|
+
return () => {
|
|
677
|
+
stale = true;
|
|
678
|
+
};
|
|
679
|
+
}, [
|
|
680
|
+
active,
|
|
681
|
+
modelDirectory,
|
|
682
|
+
directoryRefresh
|
|
683
|
+
]);
|
|
684
|
+
const saveModels = (next) => {
|
|
685
|
+
if (modelList === void 0) return;
|
|
686
|
+
setSaved(false);
|
|
687
|
+
setError(false);
|
|
688
|
+
modelList.write(next).then((written) => {
|
|
689
|
+
setModels(written ?? next);
|
|
690
|
+
setSaved(true);
|
|
691
|
+
}, () => {
|
|
692
|
+
setError(true);
|
|
693
|
+
});
|
|
694
|
+
};
|
|
695
|
+
return {
|
|
696
|
+
models,
|
|
697
|
+
unavailable,
|
|
698
|
+
saved,
|
|
699
|
+
error,
|
|
700
|
+
directory,
|
|
701
|
+
saveModels
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
/** The add dialog: search + checkboxes over the endpoint's served catalog. */
|
|
705
|
+
function AddModelsDialog({ models, directory, onAdd, onClose, t }) {
|
|
706
|
+
const [query, setQuery] = (0, react.useState)("");
|
|
707
|
+
const [checked, setChecked] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
708
|
+
const candidates = (0, react.useMemo)(() => {
|
|
709
|
+
const entries = directory?.entries ?? [];
|
|
710
|
+
const needle = query.trim().toLowerCase();
|
|
711
|
+
return entries.filter((entry) => needle === "" || entry.value.toLowerCase().includes(needle) || entry.label.toLowerCase().includes(needle)).map((entry) => ({
|
|
712
|
+
...entry,
|
|
713
|
+
added: models.includes(entry.value)
|
|
714
|
+
}));
|
|
715
|
+
}, [
|
|
716
|
+
directory,
|
|
717
|
+
query,
|
|
718
|
+
models
|
|
719
|
+
]);
|
|
720
|
+
const selectable = candidates.filter((entry) => !entry.added);
|
|
721
|
+
const allChecked = selectable.length > 0 && selectable.every((entry) => checked.has(entry.value));
|
|
722
|
+
const toggleAll = () => {
|
|
723
|
+
setChecked(allChecked ? /* @__PURE__ */ new Set() : new Set(selectable.map((entry) => entry.value)));
|
|
724
|
+
};
|
|
725
|
+
const toggle = (value) => {
|
|
726
|
+
setChecked((prev) => {
|
|
727
|
+
const next = new Set(prev);
|
|
728
|
+
if (next.has(value)) next.delete(value);
|
|
729
|
+
else next.add(value);
|
|
730
|
+
return next;
|
|
731
|
+
});
|
|
732
|
+
};
|
|
733
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
734
|
+
className: ModelListSection_module_css_default.dialogBackdrop,
|
|
735
|
+
role: "presentation",
|
|
736
|
+
onClick: () => {
|
|
737
|
+
onClose();
|
|
738
|
+
},
|
|
739
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
740
|
+
className: ModelListSection_module_css_default.dialog,
|
|
741
|
+
role: "dialog",
|
|
742
|
+
"aria-label": t("models.dialog.title"),
|
|
743
|
+
onClick: (event) => {
|
|
744
|
+
event.stopPropagation();
|
|
745
|
+
},
|
|
746
|
+
children: [
|
|
747
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
748
|
+
className: ModelListSection_module_css_default.dialogHead,
|
|
749
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
750
|
+
className: ModelListSection_module_css_default.dialogTitle,
|
|
751
|
+
children: t("models.dialog.title")
|
|
752
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
753
|
+
type: "button",
|
|
754
|
+
className: ModelListSection_module_css_default.dialogClose,
|
|
755
|
+
"aria-label": t("models.dialog.cancel"),
|
|
756
|
+
onClick: () => {
|
|
757
|
+
onClose();
|
|
758
|
+
},
|
|
759
|
+
children: "✕"
|
|
760
|
+
})]
|
|
761
|
+
}),
|
|
762
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
763
|
+
className: ModelListSection_module_css_default.dialogHint,
|
|
764
|
+
children: t("models.dialog.hint")
|
|
765
|
+
}),
|
|
766
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
767
|
+
className: ModelListSection_module_css_default.dialogToolbar,
|
|
768
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
769
|
+
type: "text",
|
|
770
|
+
className: ModelListSection_module_css_default.modelInput,
|
|
771
|
+
value: query,
|
|
772
|
+
placeholder: t("models.dialog.search"),
|
|
773
|
+
"aria-label": t("models.dialog.search"),
|
|
774
|
+
onChange: (event) => {
|
|
775
|
+
setQuery(event.currentTarget.value);
|
|
776
|
+
}
|
|
777
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
778
|
+
type: "button",
|
|
779
|
+
className: ModelListSection_module_css_default.dialogSelectAll,
|
|
780
|
+
disabled: selectable.length === 0,
|
|
781
|
+
onClick: () => {
|
|
782
|
+
toggleAll();
|
|
783
|
+
},
|
|
784
|
+
children: t("models.dialog.selectAll")
|
|
785
|
+
})]
|
|
786
|
+
}),
|
|
787
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
788
|
+
className: ModelListSection_module_css_default.dialogList,
|
|
789
|
+
children: [
|
|
790
|
+
directory === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
791
|
+
className: ModelListSection_module_css_default.hint,
|
|
792
|
+
children: t("models.dialog.loading")
|
|
793
|
+
}),
|
|
794
|
+
directory !== null && directory.entries.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
795
|
+
className: ModelListSection_module_css_default.hint,
|
|
796
|
+
children: directory.reason ?? t("models.dialog.empty")
|
|
797
|
+
}),
|
|
798
|
+
candidates.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
799
|
+
className: entry.added ? `${ModelListSection_module_css_default.dialogItem} ${ModelListSection_module_css_default.dialogItemAdded}` : ModelListSection_module_css_default.dialogItem,
|
|
800
|
+
children: [
|
|
801
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
802
|
+
type: "checkbox",
|
|
803
|
+
checked: entry.added || checked.has(entry.value),
|
|
804
|
+
disabled: entry.added,
|
|
805
|
+
onChange: () => {
|
|
806
|
+
toggle(entry.value);
|
|
807
|
+
}
|
|
808
|
+
}),
|
|
809
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
810
|
+
className: ModelListSection_module_css_default.dialogItemValue,
|
|
811
|
+
children: entry.value
|
|
812
|
+
}),
|
|
813
|
+
entry.label !== entry.value && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
814
|
+
className: ModelListSection_module_css_default.dialogItemLabel,
|
|
815
|
+
children: entry.label
|
|
816
|
+
})
|
|
817
|
+
]
|
|
818
|
+
}, entry.value))
|
|
819
|
+
]
|
|
820
|
+
}),
|
|
821
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
822
|
+
className: ModelListSection_module_css_default.dialogActions,
|
|
823
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
824
|
+
type: "button",
|
|
825
|
+
className: ModelListSection_module_css_default.modelSave,
|
|
826
|
+
onClick: () => {
|
|
827
|
+
onClose();
|
|
828
|
+
},
|
|
829
|
+
children: t("models.dialog.cancel")
|
|
830
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
831
|
+
type: "button",
|
|
832
|
+
className: ModelListSection_module_css_default.dialogConfirm,
|
|
833
|
+
disabled: checked.size === 0,
|
|
834
|
+
onClick: () => {
|
|
835
|
+
onAdd([...checked]);
|
|
836
|
+
},
|
|
837
|
+
children: t("models.dialog.confirm")
|
|
838
|
+
})]
|
|
839
|
+
})
|
|
840
|
+
]
|
|
841
|
+
})
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* The editor body: the ordered rows, the per-row delete, and the add button.
|
|
846
|
+
* Reorders persist on drop — every gesture writes immediately.
|
|
847
|
+
*/
|
|
848
|
+
function ModelListEditor({ models, directory, onChange, t }) {
|
|
849
|
+
const [dialogOpen, setDialogOpen] = (0, react.useState)(false);
|
|
850
|
+
const [dragIndex, setDragIndex] = (0, react.useState)(null);
|
|
851
|
+
const move = (from, to) => {
|
|
852
|
+
if (from === to) return;
|
|
853
|
+
const item = models[from];
|
|
854
|
+
if (item === void 0) return;
|
|
855
|
+
const next = [...models];
|
|
856
|
+
next.splice(from, 1);
|
|
857
|
+
next.splice(to, 0, item);
|
|
858
|
+
onChange(next);
|
|
859
|
+
};
|
|
860
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
861
|
+
className: ModelListSection_module_css_default.modelList,
|
|
862
|
+
children: [
|
|
863
|
+
models.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
864
|
+
className: ModelListSection_module_css_default.hint,
|
|
865
|
+
children: t("models.empty")
|
|
866
|
+
}),
|
|
867
|
+
models.map((model, index) => {
|
|
868
|
+
const entry = directory?.entries.find((candidate) => candidate.value === model);
|
|
869
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
870
|
+
className: dragIndex === index ? `${ModelListSection_module_css_default.modelRow} ${ModelListSection_module_css_default.modelRowDragging}` : ModelListSection_module_css_default.modelRow,
|
|
871
|
+
draggable: true,
|
|
872
|
+
onDragStart: () => {
|
|
873
|
+
setDragIndex(index);
|
|
874
|
+
},
|
|
875
|
+
onDragOver: (event) => {
|
|
876
|
+
event.preventDefault();
|
|
877
|
+
},
|
|
878
|
+
onDrop: () => {
|
|
879
|
+
if (dragIndex !== null) move(dragIndex, index);
|
|
880
|
+
setDragIndex(null);
|
|
881
|
+
},
|
|
882
|
+
onDragEnd: () => {
|
|
883
|
+
setDragIndex(null);
|
|
884
|
+
},
|
|
885
|
+
children: [
|
|
886
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
887
|
+
className: ModelListSection_module_css_default.modelDrag,
|
|
888
|
+
"aria-hidden": true,
|
|
889
|
+
children: "⠿"
|
|
890
|
+
}),
|
|
891
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
892
|
+
className: ModelListSection_module_css_default.modelRowValue,
|
|
893
|
+
children: model
|
|
894
|
+
}),
|
|
895
|
+
entry !== void 0 && entry.label !== model && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
896
|
+
className: ModelListSection_module_css_default.modelRowLabel,
|
|
897
|
+
children: entry.label
|
|
898
|
+
}),
|
|
899
|
+
index === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
900
|
+
className: ModelListSection_module_css_default.modelDefaultChip,
|
|
901
|
+
children: t("models.defaultChip")
|
|
902
|
+
}),
|
|
903
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
904
|
+
type: "button",
|
|
905
|
+
className: ModelListSection_module_css_default.modelDelete,
|
|
906
|
+
"aria-label": `${t("models.delete")}: ${model}`,
|
|
907
|
+
onClick: () => {
|
|
908
|
+
onChange(models.filter((_, other) => other !== index));
|
|
909
|
+
},
|
|
910
|
+
children: "✕"
|
|
911
|
+
})
|
|
912
|
+
]
|
|
913
|
+
}, model);
|
|
914
|
+
}),
|
|
915
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
916
|
+
className: ModelListSection_module_css_default.row,
|
|
917
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
918
|
+
type: "button",
|
|
919
|
+
className: ModelListSection_module_css_default.modelAdd,
|
|
920
|
+
onClick: () => {
|
|
921
|
+
setDialogOpen(true);
|
|
922
|
+
},
|
|
923
|
+
children: t("models.add")
|
|
924
|
+
}), models.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
925
|
+
className: ModelListSection_module_css_default.hint,
|
|
926
|
+
children: t("models.orderHint")
|
|
927
|
+
})]
|
|
928
|
+
}),
|
|
929
|
+
dialogOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddModelsDialog, {
|
|
930
|
+
models,
|
|
931
|
+
directory,
|
|
932
|
+
onAdd: (added) => {
|
|
933
|
+
onChange([...models, ...added]);
|
|
934
|
+
setDialogOpen(false);
|
|
935
|
+
},
|
|
936
|
+
onClose: () => {
|
|
937
|
+
setDialogOpen(false);
|
|
938
|
+
},
|
|
939
|
+
t
|
|
940
|
+
})
|
|
941
|
+
]
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* The「可用模型」section every companion's settings card renders: the block
|
|
946
|
+
* chrome (title + ⓘ bubble), the editor, and the save verdict. Reads fire
|
|
947
|
+
* only while `active`; a missing list face renders the header without the
|
|
948
|
+
* editor (declare-and-degrade).
|
|
949
|
+
* @param props - the faces, the activity gate, and copy.
|
|
950
|
+
* @returns the section.
|
|
951
|
+
*/
|
|
952
|
+
function ModelListSection({ active, modelList, modelDirectory, directoryRefresh, t }) {
|
|
953
|
+
const { models, unavailable, saved, error, directory, saveModels } = useModelListState(active, modelList, modelDirectory, directoryRefresh);
|
|
954
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
955
|
+
className: ModelListSection_module_css_default.block,
|
|
956
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
|
|
957
|
+
className: ModelListSection_module_css_default.blockTitle,
|
|
958
|
+
children: [t("models.title"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
959
|
+
label: t("models.info"),
|
|
960
|
+
side: "bottom",
|
|
961
|
+
maxWidth: 360,
|
|
962
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
963
|
+
type: "button",
|
|
964
|
+
className: ModelListSection_module_css_default.info,
|
|
965
|
+
"aria-label": t("models.info.aria"),
|
|
966
|
+
children: "ⓘ"
|
|
967
|
+
})
|
|
968
|
+
})]
|
|
969
|
+
}), !unavailable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
970
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelListEditor, {
|
|
971
|
+
models,
|
|
972
|
+
directory,
|
|
973
|
+
onChange: saveModels,
|
|
974
|
+
t
|
|
975
|
+
}),
|
|
976
|
+
saved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
977
|
+
className: ModelListSection_module_css_default.saved,
|
|
978
|
+
children: t("models.applied")
|
|
979
|
+
}),
|
|
980
|
+
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
981
|
+
className: ModelListSection_module_css_default.errorText,
|
|
982
|
+
children: t("models.error")
|
|
983
|
+
})
|
|
984
|
+
] })]
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
//#endregion
|
|
560
988
|
//#region \0dsh-css:src/client/SettingsCard.module.css.mjs
|
|
561
|
-
const css = ".apHkUa_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.apHkUa_card:hover{border-color:var(--dsw-alias-label-dimmed)}.apHkUa_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.apHkUa_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.apHkUa_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.apHkUa_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.apHkUa_nameRow{align-items:center;gap:6px;display:flex}.apHkUa_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.apHkUa_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.apHkUa_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.apHkUa_chevronOpen{transform:rotate(180deg)}.apHkUa_body{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:14px;margin:0 16px;padding:12px 0 8px;display:flex}.apHkUa_block{flex-direction:column;gap:10px;display:flex}.apHkUa_blockTitle{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;margin:0;font-size:13px;font-weight:500;line-height:1.4;display:flex}.apHkUa_info{appearance:none;color:var(--dsw-alias-label-tertiary);cursor:help;background:0 0;border:0;border-radius:50%;padding:0 2px;font-size:12px;line-height:1}.apHkUa_info:hover,.apHkUa_info:focus-visible{color:var(--dsw-alias-label-primary)}.apHkUa_row{align-items:center;gap:12px;display:flex}.apHkUa_rowLabel{color:var(--dsw-alias-label-primary);align-items:center;gap:4px;font-size:13px;line-height:1.4;display:inline-flex}.apHkUa_switch{border:1px solid color-mix(in srgb, currentColor 30%, transparent);background:color-mix(in srgb, currentColor 12%, transparent);cursor:pointer;width:2.25rem;height:1.25rem;color:var(--dsw-alias-label-primary);border-radius:999px;flex:none;align-self:center;padding:.125rem;transition:background .12s}.apHkUa_switch:disabled{opacity:.5;cursor:default}.apHkUa_switchOn{background:color-mix(in srgb, var(--dsh-accent,#4f8cff) 70%, transparent)}.apHkUa_knob{background:var(--dsh-surface,#fff);border-radius:999px;width:.9375rem;height:.9375rem;transition:transform .12s;display:block}.apHkUa_switchOn .apHkUa_knob{transform:translate(.9375rem)}.apHkUa_saved{color:var(--dsw-alias-state-success-primary);font-size:12px}.apHkUa_errorText{color:var(--dsw-alias-state-error-primary);font-size:12px}.apHkUa_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.apHkUa_modelInput{min-width:0;font:inherit;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:5px 8px;font-size:13px;line-height:1.4}.apHkUa_modelInput::placeholder{color:var(--dsw-alias-label-caption);opacity:1}.apHkUa_modelInput:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.apHkUa_modelInput:disabled{opacity:.5}.
|
|
989
|
+
const css = ".apHkUa_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.apHkUa_card:hover{border-color:var(--dsw-alias-label-dimmed)}.apHkUa_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.apHkUa_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.apHkUa_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.apHkUa_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.apHkUa_nameRow{align-items:center;gap:6px;display:flex}.apHkUa_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.apHkUa_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.apHkUa_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.apHkUa_chevronOpen{transform:rotate(180deg)}.apHkUa_body{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:14px;margin:0 16px;padding:12px 0 8px;display:flex}.apHkUa_block{flex-direction:column;gap:10px;display:flex}.apHkUa_blockTitle{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;margin:0;font-size:13px;font-weight:500;line-height:1.4;display:flex}.apHkUa_info{appearance:none;color:var(--dsw-alias-label-tertiary);cursor:help;background:0 0;border:0;border-radius:50%;padding:0 2px;font-size:12px;line-height:1}.apHkUa_info:hover,.apHkUa_info:focus-visible{color:var(--dsw-alias-label-primary)}.apHkUa_row{align-items:center;gap:12px;display:flex}.apHkUa_endpointFields{flex-direction:column;gap:8px;margin-top:4px;display:flex}.apHkUa_endpointField{flex-direction:column;gap:4px;display:flex}.apHkUa_endpointLabel{color:var(--dsw-alias-label-tertiary);align-items:center;gap:6px;font-size:12px;line-height:1.3;display:inline-flex}.apHkUa_configuredChip{color:var(--dsw-alias-success,#1a9e54);background:color-mix(in srgb, var(--dsw-alias-success,#1a9e54) 12%, transparent);border-radius:999px;padding:1px 8px;font-size:11px;line-height:1.4}.apHkUa_rowLabel{color:var(--dsw-alias-label-primary);align-items:center;gap:4px;font-size:13px;line-height:1.4;display:inline-flex}.apHkUa_switch{border:1px solid color-mix(in srgb, currentColor 30%, transparent);background:color-mix(in srgb, currentColor 12%, transparent);cursor:pointer;width:2.25rem;height:1.25rem;color:var(--dsw-alias-label-primary);border-radius:999px;flex:none;align-self:center;padding:.125rem;transition:background .12s}.apHkUa_switch:disabled{opacity:.5;cursor:default}.apHkUa_switchOn{background:color-mix(in srgb, var(--dsh-accent,#4f8cff) 70%, transparent)}.apHkUa_knob{background:var(--dsh-surface,#fff);border-radius:999px;width:.9375rem;height:.9375rem;transition:transform .12s;display:block}.apHkUa_switchOn .apHkUa_knob{transform:translate(.9375rem)}.apHkUa_saved{color:var(--dsw-alias-state-success-primary);font-size:12px}.apHkUa_errorText{color:var(--dsw-alias-state-error-primary);font-size:12px}.apHkUa_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.apHkUa_modelInput{min-width:0;font:inherit;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:5px 8px;font-size:13px;line-height:1.4}.apHkUa_modelInput::placeholder{color:var(--dsw-alias-label-caption);opacity:1}.apHkUa_modelInput:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.apHkUa_modelInput:disabled{opacity:.5}.apHkUa_modelSave{appearance:none;font:inherit;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:8px;flex:none;padding:5px 10px;font-size:13px;line-height:1.4}.apHkUa_modelSave:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed)}.apHkUa_modelSave:disabled{opacity:.5;cursor:default}";
|
|
562
990
|
const tagId = "@khorsheed/dsh-local-agent-kimi/SettingsCard.module.css";
|
|
563
991
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
564
992
|
const tag = document.createElement("style");
|
|
@@ -568,100 +996,97 @@ window.__ModuleLoader__.load({
|
|
|
568
996
|
document.head.appendChild(tag);
|
|
569
997
|
}
|
|
570
998
|
var SettingsCard_module_css_default = {
|
|
571
|
-
"
|
|
572
|
-
"info": "apHkUa_info",
|
|
573
|
-
"saved": "apHkUa_saved",
|
|
574
|
-
"modelMenuChevronOpen": "apHkUa_modelMenuChevronOpen",
|
|
575
|
-
"modelMenu": "apHkUa_modelMenu",
|
|
999
|
+
"blockTitle": "apHkUa_blockTitle",
|
|
576
1000
|
"chevronOpen": "apHkUa_chevronOpen",
|
|
577
|
-
"
|
|
578
|
-
"
|
|
579
|
-
"header": "apHkUa_header",
|
|
580
|
-
"name": "apHkUa_name",
|
|
581
|
-
"modelMenuUp": "apHkUa_modelMenuUp",
|
|
1001
|
+
"rowLabel": "apHkUa_rowLabel",
|
|
1002
|
+
"switch": "apHkUa_switch",
|
|
582
1003
|
"knob": "apHkUa_knob",
|
|
583
|
-
"
|
|
584
|
-
"
|
|
1004
|
+
"saved": "apHkUa_saved",
|
|
1005
|
+
"info": "apHkUa_info",
|
|
1006
|
+
"modelSave": "apHkUa_modelSave",
|
|
1007
|
+
"switchOn": "apHkUa_switchOn",
|
|
1008
|
+
"errorText": "apHkUa_errorText",
|
|
1009
|
+
"body": "apHkUa_body",
|
|
1010
|
+
"configuredChip": "apHkUa_configuredChip",
|
|
1011
|
+
"modelInput": "apHkUa_modelInput",
|
|
1012
|
+
"chevron": "apHkUa_chevron",
|
|
585
1013
|
"block": "apHkUa_block",
|
|
586
|
-
"
|
|
587
|
-
"
|
|
1014
|
+
"hint": "apHkUa_hint",
|
|
1015
|
+
"endpointLabel": "apHkUa_endpointLabel",
|
|
1016
|
+
"nameRow": "apHkUa_nameRow",
|
|
1017
|
+
"headText": "apHkUa_headText",
|
|
588
1018
|
"card": "apHkUa_card",
|
|
1019
|
+
"endpointField": "apHkUa_endpointField",
|
|
1020
|
+
"row": "apHkUa_row",
|
|
1021
|
+
"endpointFields": "apHkUa_endpointFields",
|
|
589
1022
|
"description": "apHkUa_description",
|
|
590
|
-
"hint": "apHkUa_hint",
|
|
591
|
-
"switchOn": "apHkUa_switchOn",
|
|
592
|
-
"modelItem": "apHkUa_modelItem",
|
|
593
|
-
"modelMenuButton": "apHkUa_modelMenuButton",
|
|
594
|
-
"switch": "apHkUa_switch",
|
|
595
|
-
"modelItemLabel": "apHkUa_modelItemLabel",
|
|
596
|
-
"modelMenuChevron": "apHkUa_modelMenuChevron",
|
|
597
|
-
"modelSave": "apHkUa_modelSave",
|
|
598
|
-
"modelField": "apHkUa_modelField",
|
|
599
1023
|
"cardOpen": "apHkUa_cardOpen",
|
|
600
|
-
"
|
|
601
|
-
"
|
|
602
|
-
"rowLabel": "apHkUa_rowLabel",
|
|
603
|
-
"errorText": "apHkUa_errorText",
|
|
604
|
-
"body": "apHkUa_body"
|
|
1024
|
+
"name": "apHkUa_name",
|
|
1025
|
+
"header": "apHkUa_header"
|
|
605
1026
|
};
|
|
606
1027
|
//#endregion
|
|
607
1028
|
//#region src/client/SettingsCard.tsx
|
|
608
|
-
/** How many previously-saved model identifiers the input suggests. */
|
|
609
|
-
const RECENT_MODEL_LIMIT = 5;
|
|
610
1029
|
/**
|
|
611
|
-
* The staged card state both settings surfaces share: the resident-mode
|
|
612
|
-
*
|
|
1030
|
+
* The staged card state both settings surfaces share: the resident-mode
|
|
1031
|
+
* switch writes through the bound settingsScope immediately
|
|
613
1032
|
* (revision-fenced), so a flip takes effect on the next delegation round
|
|
614
|
-
* without a reload; the
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
* @param active - whether the surface
|
|
1033
|
+
* without a reload; the endpoint credential form talks to the harness's own
|
|
1034
|
+
* store through the endpointAuth face. The「可用模型」section is the family
|
|
1035
|
+
* core's shared ModelListSection, which owns its own state.
|
|
1036
|
+
* @param active - whether the surface currently shows the body (gates the credential-form fetch).
|
|
618
1037
|
* @param useSettings - the bound settings hook from the inject hooks compartment.
|
|
619
1038
|
* @param scope - the bound settings scope the writes go through.
|
|
620
|
-
* @param
|
|
621
|
-
* @param t - copy.
|
|
1039
|
+
* @param endpointAuth - the harness's endpoint credential face; absent hides the credential form.
|
|
622
1040
|
*/
|
|
623
|
-
function useCardState(active, useSettings, scope,
|
|
1041
|
+
function useCardState(active, useSettings, scope, endpointAuth) {
|
|
624
1042
|
const snapshot = useSettings((value) => value);
|
|
625
1043
|
const [saved, setSaved] = (0, react.useState)(false);
|
|
626
1044
|
const [error, setError] = (0, react.useState)(false);
|
|
627
1045
|
const ready = snapshot.status === "ready" && snapshot.writable;
|
|
628
1046
|
const live = snapshot.value?.live ?? false;
|
|
629
|
-
const
|
|
630
|
-
const
|
|
631
|
-
const [
|
|
632
|
-
const [
|
|
633
|
-
const [
|
|
634
|
-
const
|
|
635
|
-
const
|
|
1047
|
+
const [endpointState, setEndpointState] = (0, react.useState)(null);
|
|
1048
|
+
const [baseUrlDraft, setBaseUrlDraft] = (0, react.useState)(null);
|
|
1049
|
+
const [apiKeyDraft, setApiKeyDraft] = (0, react.useState)(null);
|
|
1050
|
+
const [endpointSaved, setEndpointSaved] = (0, react.useState)(false);
|
|
1051
|
+
const [endpointError, setEndpointError] = (0, react.useState)(false);
|
|
1052
|
+
const endpointDirty = baseUrlDraft !== null || apiKeyDraft !== null;
|
|
1053
|
+
const endpointUnavailable = endpointAuth === void 0 || endpointState === "unavailable";
|
|
1054
|
+
const endpointLoading = !endpointUnavailable && endpointState === null;
|
|
1055
|
+
const apiKeyConfigured = endpointState !== null && endpointState !== "unavailable" && endpointState.apiKeySet;
|
|
636
1056
|
(0, react.useEffect)(() => {
|
|
637
|
-
if (!active) return;
|
|
1057
|
+
if (!active || endpointAuth === void 0) return;
|
|
638
1058
|
let stale = false;
|
|
639
|
-
|
|
640
|
-
if (!stale)
|
|
1059
|
+
endpointAuth.read().then((state) => {
|
|
1060
|
+
if (!stale) setEndpointState(state ?? "unavailable");
|
|
1061
|
+
}, () => {
|
|
1062
|
+
if (!stale) setEndpointState("unavailable");
|
|
641
1063
|
});
|
|
642
1064
|
return () => {
|
|
643
1065
|
stale = true;
|
|
644
1066
|
};
|
|
645
1067
|
}, [
|
|
646
1068
|
active,
|
|
647
|
-
|
|
648
|
-
|
|
1069
|
+
endpointAuth,
|
|
1070
|
+
endpointSaved
|
|
649
1071
|
]);
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
1072
|
+
const saveEndpoint = () => {
|
|
1073
|
+
if (endpointAuth === void 0) return;
|
|
1074
|
+
setEndpointSaved(false);
|
|
1075
|
+
setEndpointError(false);
|
|
1076
|
+
const fields = {
|
|
1077
|
+
...baseUrlDraft !== null ? { baseUrl: baseUrlDraft.trim() === "" ? null : baseUrlDraft.trim() } : {},
|
|
1078
|
+
...apiKeyDraft !== null ? { apiKey: apiKeyDraft.trim() === "" ? null : apiKeyDraft.trim() } : {}
|
|
1079
|
+
};
|
|
1080
|
+
endpointAuth.write(fields).then((state) => {
|
|
1081
|
+
if (state !== void 0 && state !== null) {
|
|
1082
|
+
setEndpointState(state);
|
|
1083
|
+
if (state.apiKeySet) publishAuthStatus("kimi", "authenticated");
|
|
1084
|
+
}
|
|
1085
|
+
setBaseUrlDraft(null);
|
|
1086
|
+
setApiKeyDraft(null);
|
|
1087
|
+
setEndpointSaved(true);
|
|
663
1088
|
}, () => {
|
|
664
|
-
|
|
1089
|
+
setEndpointError(true);
|
|
665
1090
|
});
|
|
666
1091
|
};
|
|
667
1092
|
const write = (field, value) => {
|
|
@@ -673,194 +1098,165 @@ window.__ModuleLoader__.load({
|
|
|
673
1098
|
setError(true);
|
|
674
1099
|
});
|
|
675
1100
|
};
|
|
676
|
-
const choices = modelInfo?.choices ?? recentModels;
|
|
677
|
-
const [modelMenuOpen, setModelMenuOpen] = (0, react.useState)(false);
|
|
678
|
-
const [modelMenuUp, setModelMenuUp] = (0, react.useState)(false);
|
|
679
|
-
const modelFieldRef = (0, react.useRef)(null);
|
|
680
|
-
(0, react.useEffect)(() => {
|
|
681
|
-
if (!modelMenuOpen) return;
|
|
682
|
-
const onPointerDown = (event) => {
|
|
683
|
-
if (modelFieldRef.current?.contains(event.target) === true) return;
|
|
684
|
-
setModelMenuOpen(false);
|
|
685
|
-
};
|
|
686
|
-
const onKeyDown = (event) => {
|
|
687
|
-
if (event.key === "Escape") setModelMenuOpen(false);
|
|
688
|
-
};
|
|
689
|
-
document.addEventListener("mousedown", onPointerDown);
|
|
690
|
-
document.addEventListener("keydown", onKeyDown);
|
|
691
|
-
return () => {
|
|
692
|
-
document.removeEventListener("mousedown", onPointerDown);
|
|
693
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
694
|
-
};
|
|
695
|
-
}, [modelMenuOpen]);
|
|
696
|
-
const toggleModelMenu = () => {
|
|
697
|
-
if (!modelMenuOpen) {
|
|
698
|
-
const rect = modelFieldRef.current?.getBoundingClientRect();
|
|
699
|
-
if (rect !== void 0) {
|
|
700
|
-
const spaceBelow = window.innerHeight - rect.bottom;
|
|
701
|
-
setModelMenuUp(spaceBelow < 260 && rect.top > spaceBelow);
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
setModelMenuOpen((open) => !open);
|
|
705
|
-
};
|
|
706
1101
|
return {
|
|
707
1102
|
snapshot,
|
|
708
1103
|
saved,
|
|
709
1104
|
error,
|
|
710
1105
|
ready,
|
|
711
1106
|
live,
|
|
712
|
-
storedModel,
|
|
713
|
-
modelValue,
|
|
714
|
-
modelSaved,
|
|
715
|
-
modelError,
|
|
716
|
-
choices,
|
|
717
|
-
modelMenuOpen,
|
|
718
|
-
modelMenuUp,
|
|
719
|
-
modelFieldRef,
|
|
720
|
-
modelPlaceholder: (modelInfo?.cliDefault !== void 0 && modelInfo.cliDefault !== "" ? modelInfo.cliDefault : modelInfo?.source === "cli-builtin" && modelInfo.effective !== void 0 && modelInfo.effective !== "" ? modelInfo.effective : modelInfo?.lastObserved !== void 0 && modelInfo.lastObserved !== "" ? modelInfo.lastObserved : void 0) ?? t("model.placeholder"),
|
|
721
|
-
modelDefaultItem: modelInfo?.cliDefault !== void 0 && modelInfo.cliDefault !== "" ? t("model.menuDefault.cliConfig", { model: modelInfo.cliDefault }) : modelInfo?.source === "cli-builtin" && modelInfo.effective !== void 0 && modelInfo.effective !== "" ? t("model.menuDefault.cliBuiltin", { model: modelInfo.effective }) : modelInfo?.lastObserved !== void 0 && modelInfo.lastObserved !== "" ? t("model.menuDefault.lastObserved", { model: modelInfo.lastObserved }) : t("model.menuDefault"),
|
|
722
|
-
saveModel,
|
|
723
1107
|
write,
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
1108
|
+
endpointUnavailable,
|
|
1109
|
+
endpointLoading,
|
|
1110
|
+
baseUrlValue: baseUrlDraft ?? (endpointState !== null && endpointState !== "unavailable" ? endpointState.baseUrl ?? "" : ""),
|
|
1111
|
+
apiKeyConfigured,
|
|
1112
|
+
apiKeyDraft,
|
|
1113
|
+
endpointSaved,
|
|
1114
|
+
endpointError,
|
|
1115
|
+
endpointDirty,
|
|
1116
|
+
saveEndpoint,
|
|
1117
|
+
setBaseUrlDraft,
|
|
1118
|
+
setApiKeyDraft
|
|
727
1119
|
};
|
|
728
1120
|
}
|
|
729
|
-
/** The card body both settings surfaces share: the auth block, the
|
|
730
|
-
function CardBody({ state, auth, authT,
|
|
731
|
-
const { snapshot, saved, error, ready, live,
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}
|
|
742
|
-
|
|
1121
|
+
/** The card body both settings surfaces share: the auth block, the model-list section, and the resident-mode block. */
|
|
1122
|
+
function CardBody({ state, active, auth, authT, modelList, modelDirectory, checkEndpoint, useSessions, t }) {
|
|
1123
|
+
const { snapshot, saved, error, ready, live, write, endpointUnavailable, endpointLoading, baseUrlValue, apiKeyConfigured, apiKeyDraft, endpointSaved, endpointError, endpointDirty, saveEndpoint, setBaseUrlDraft, setApiKeyDraft } = state;
|
|
1124
|
+
const [checking, setChecking] = (0, react.useState)(false);
|
|
1125
|
+
const [checkText, setCheckText] = (0, react.useState)(null);
|
|
1126
|
+
const runCheck = () => {
|
|
1127
|
+
if (checkEndpoint === void 0) return;
|
|
1128
|
+
setChecking(true);
|
|
1129
|
+
setCheckText(null);
|
|
1130
|
+
checkEndpoint().then((text) => {
|
|
1131
|
+
setCheckText(text ?? t("endpoint.checkUnavailable"));
|
|
1132
|
+
setChecking(false);
|
|
1133
|
+
}, () => {
|
|
1134
|
+
setCheckText(t("endpoint.checkFailed"));
|
|
1135
|
+
setChecking(false);
|
|
1136
|
+
});
|
|
1137
|
+
};
|
|
743
1138
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
744
1139
|
className: SettingsCard_module_css_default.body,
|
|
745
1140
|
children: [
|
|
746
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
747
|
-
className: SettingsCard_module_css_default.block,
|
|
748
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
749
|
-
className: SettingsCard_module_css_default.blockTitle,
|
|
750
|
-
children: t("auth.title")
|
|
751
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderAuthBlock, {
|
|
752
|
-
harness: {
|
|
753
|
-
id: "kimi",
|
|
754
|
-
label: "Kimi Code"
|
|
755
|
-
},
|
|
756
|
-
useSessions,
|
|
757
|
-
status: auth.status,
|
|
758
|
-
runCommand: auth.runCommand,
|
|
759
|
-
t: authT
|
|
760
|
-
})]
|
|
761
|
-
}),
|
|
762
1141
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
763
1142
|
className: SettingsCard_module_css_default.block,
|
|
764
1143
|
children: [
|
|
765
1144
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
|
|
766
1145
|
className: SettingsCard_module_css_default.blockTitle,
|
|
767
|
-
children: [t("
|
|
768
|
-
label: t("
|
|
1146
|
+
children: [t("auth.title"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
1147
|
+
label: t("endpoint.info"),
|
|
769
1148
|
side: "bottom",
|
|
770
1149
|
maxWidth: 360,
|
|
771
1150
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
772
1151
|
type: "button",
|
|
773
1152
|
className: SettingsCard_module_css_default.info,
|
|
774
|
-
"aria-label": t("
|
|
1153
|
+
"aria-label": t("endpoint.info.aria"),
|
|
775
1154
|
children: "ⓘ"
|
|
776
1155
|
})
|
|
777
1156
|
})]
|
|
778
1157
|
}),
|
|
779
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
"aria-label": t("
|
|
807
|
-
|
|
1158
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderAuthBlock, {
|
|
1159
|
+
harness: {
|
|
1160
|
+
id: "kimi",
|
|
1161
|
+
label: "Kimi Code"
|
|
1162
|
+
},
|
|
1163
|
+
useSessions,
|
|
1164
|
+
status: auth.status,
|
|
1165
|
+
runCommand: auth.runCommand,
|
|
1166
|
+
t: authT
|
|
1167
|
+
}),
|
|
1168
|
+
endpointUnavailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1169
|
+
className: SettingsCard_module_css_default.hint,
|
|
1170
|
+
children: t("endpoint.unavailable")
|
|
1171
|
+
}),
|
|
1172
|
+
!endpointUnavailable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1173
|
+
className: SettingsCard_module_css_default.endpointFields,
|
|
1174
|
+
children: [
|
|
1175
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1176
|
+
className: SettingsCard_module_css_default.endpointField,
|
|
1177
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1178
|
+
className: SettingsCard_module_css_default.endpointLabel,
|
|
1179
|
+
children: t("endpoint.baseUrl")
|
|
1180
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1181
|
+
type: "text",
|
|
1182
|
+
className: SettingsCard_module_css_default.modelInput,
|
|
1183
|
+
value: baseUrlValue,
|
|
1184
|
+
placeholder: t("endpoint.baseUrl.placeholder"),
|
|
1185
|
+
"aria-label": t("endpoint.baseUrl"),
|
|
1186
|
+
disabled: endpointLoading,
|
|
1187
|
+
onChange: (event) => {
|
|
1188
|
+
setBaseUrlDraft(event.currentTarget.value);
|
|
1189
|
+
}
|
|
1190
|
+
})]
|
|
1191
|
+
}),
|
|
1192
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1193
|
+
className: SettingsCard_module_css_default.endpointField,
|
|
1194
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1195
|
+
className: SettingsCard_module_css_default.endpointLabel,
|
|
1196
|
+
children: [t("endpoint.apiKey"), apiKeyConfigured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1197
|
+
className: SettingsCard_module_css_default.configuredChip,
|
|
1198
|
+
children: t("endpoint.configured")
|
|
1199
|
+
})]
|
|
1200
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1201
|
+
type: "password",
|
|
1202
|
+
className: SettingsCard_module_css_default.modelInput,
|
|
1203
|
+
value: apiKeyDraft ?? "",
|
|
1204
|
+
placeholder: apiKeyConfigured ? t("endpoint.secret.configured") : t("endpoint.secret.placeholder"),
|
|
1205
|
+
"aria-label": t("endpoint.apiKey"),
|
|
1206
|
+
autoComplete: "off",
|
|
1207
|
+
disabled: endpointLoading,
|
|
1208
|
+
onChange: (event) => {
|
|
1209
|
+
setApiKeyDraft(event.currentTarget.value);
|
|
1210
|
+
}
|
|
1211
|
+
})]
|
|
1212
|
+
}),
|
|
1213
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1214
|
+
className: SettingsCard_module_css_default.row,
|
|
1215
|
+
children: [
|
|
1216
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
808
1217
|
type: "button",
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
className: modelValue.trim() === "" ? `${SettingsCard_module_css_default.modelItemDefault} ${SettingsCard_module_css_default.modelItemCurrent}` : SettingsCard_module_css_default.modelItemDefault,
|
|
1218
|
+
className: SettingsCard_module_css_default.modelSave,
|
|
1219
|
+
disabled: endpointLoading || !endpointDirty,
|
|
812
1220
|
onClick: () => {
|
|
813
|
-
|
|
814
|
-
setModelMenuOpen(false);
|
|
1221
|
+
saveEndpoint();
|
|
815
1222
|
},
|
|
816
|
-
children:
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
820
|
-
className: SettingsCard_module_css_default.modelItemCheck,
|
|
821
|
-
"aria-hidden": true,
|
|
822
|
-
children: modelValue.trim() === "" ? "✓" : ""
|
|
823
|
-
})]
|
|
824
|
-
}), choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1223
|
+
children: t("endpoint.save")
|
|
1224
|
+
}),
|
|
1225
|
+
checkEndpoint !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
825
1226
|
type: "button",
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1227
|
+
className: SettingsCard_module_css_default.modelSave,
|
|
1228
|
+
disabled: endpointLoading || endpointDirty || checking,
|
|
1229
|
+
title: endpointDirty ? t("endpoint.checkDirtyHint") : void 0,
|
|
829
1230
|
onClick: () => {
|
|
830
|
-
|
|
831
|
-
setModelMenuOpen(false);
|
|
1231
|
+
runCheck();
|
|
832
1232
|
},
|
|
833
|
-
children:
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
},
|
|
851
|
-
children: t("model.save")
|
|
852
|
-
})]
|
|
853
|
-
}),
|
|
854
|
-
modelSaved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
855
|
-
className: SettingsCard_module_css_default.saved,
|
|
856
|
-
children: t("model.applied")
|
|
857
|
-
}),
|
|
858
|
-
modelError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
859
|
-
className: SettingsCard_module_css_default.errorText,
|
|
860
|
-
children: t("model.error")
|
|
1233
|
+
children: checking ? t("endpoint.checking") : t("endpoint.check")
|
|
1234
|
+
}),
|
|
1235
|
+
endpointSaved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1236
|
+
className: SettingsCard_module_css_default.saved,
|
|
1237
|
+
children: t("endpoint.applied")
|
|
1238
|
+
}),
|
|
1239
|
+
endpointError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1240
|
+
className: SettingsCard_module_css_default.errorText,
|
|
1241
|
+
children: t("endpoint.error")
|
|
1242
|
+
})
|
|
1243
|
+
]
|
|
1244
|
+
}),
|
|
1245
|
+
checkText !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1246
|
+
className: SettingsCard_module_css_default.hint,
|
|
1247
|
+
children: checkText
|
|
1248
|
+
})
|
|
1249
|
+
]
|
|
861
1250
|
})
|
|
862
1251
|
]
|
|
863
1252
|
}),
|
|
1253
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelListSection, {
|
|
1254
|
+
active,
|
|
1255
|
+
modelList,
|
|
1256
|
+
modelDirectory,
|
|
1257
|
+
directoryRefresh: endpointSaved,
|
|
1258
|
+
t: authT
|
|
1259
|
+
}),
|
|
864
1260
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
865
1261
|
className: SettingsCard_module_css_default.block,
|
|
866
1262
|
children: [
|
|
@@ -910,8 +1306,9 @@ window.__ModuleLoader__.load({
|
|
|
910
1306
|
});
|
|
911
1307
|
}
|
|
912
1308
|
/**
|
|
913
|
-
* The kimi harness settings card
|
|
914
|
-
*
|
|
1309
|
+
* The kimi harness settings card of the retired 0.1.5 plugin configuration
|
|
1310
|
+
* tab (no longer registered; the live surface is the plugins.item entry
|
|
1311
|
+
* below): the same collapsible chrome the official plugin cards use, re-implemented
|
|
915
1312
|
* locally (the bundle-purity gate forbids value-importing the official chrome
|
|
916
1313
|
* — the context-guard pattern), with the at-a-glance credential dot in the
|
|
917
1314
|
* header. Explanation copy lives in hover/focus bubbles behind ⓘ anchors —
|
|
@@ -920,9 +1317,9 @@ window.__ModuleLoader__.load({
|
|
|
920
1317
|
* @returns the card.
|
|
921
1318
|
*/
|
|
922
1319
|
function KimiSettingsCard(props) {
|
|
923
|
-
const { useSettings, scope, auth, authT,
|
|
1320
|
+
const { useSettings, scope, auth, authT, modelList, modelDirectory, checkEndpoint, endpointAuth, useSessions, t } = props;
|
|
924
1321
|
const [open, setOpen] = (0, react.useState)(false);
|
|
925
|
-
const state = useCardState(
|
|
1322
|
+
const state = useCardState(open, useSettings, scope, endpointAuth);
|
|
926
1323
|
const authStatus = useHarnessAuthStatus("kimi", auth.status);
|
|
927
1324
|
const dotLabel = authT(authStatus === "authenticated" ? "settings.authenticated" : authStatus === "anonymous" ? "settings.notAuthenticated" : authStatus === "checking" ? "loading" : "error");
|
|
928
1325
|
const title = t("card.title");
|
|
@@ -954,33 +1351,62 @@ window.__ModuleLoader__.load({
|
|
|
954
1351
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronDownOutlineMedium, { className: open ? `${SettingsCard_module_css_default.chevron} ${SettingsCard_module_css_default.chevronOpen}` : SettingsCard_module_css_default.chevron })]
|
|
955
1352
|
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardBody, {
|
|
956
1353
|
state,
|
|
1354
|
+
active: open,
|
|
957
1355
|
auth,
|
|
958
1356
|
authT,
|
|
959
|
-
|
|
1357
|
+
modelList,
|
|
1358
|
+
modelDirectory,
|
|
1359
|
+
checkEndpoint,
|
|
960
1360
|
useSessions,
|
|
961
1361
|
t
|
|
962
1362
|
})]
|
|
963
1363
|
});
|
|
964
1364
|
}
|
|
965
1365
|
/**
|
|
966
|
-
* The
|
|
967
|
-
*
|
|
968
|
-
*
|
|
969
|
-
*
|
|
1366
|
+
* The provider's card on the Plugins page (the `plugins.item` entry
|
|
1367
|
+
* client/index.ts registers while the Host serves the namespace AND the core
|
|
1368
|
+
* predates the family card): the page
|
|
1369
|
+
* draws the title, the icon, and the crumb itself, so the entry renders the
|
|
1370
|
+
* one-liner for the `summary` view and the bare form — with its own save
|
|
1371
|
+
* control — for `page`.
|
|
970
1372
|
* @param props - the owner view, the injected scope/auth faces, and copy.
|
|
971
1373
|
* @returns the entry.
|
|
972
1374
|
*/
|
|
973
|
-
function KimiBundleConfig({ view, useSettings, scope, auth, authT,
|
|
974
|
-
const state = useCardState(view === "page", useSettings, scope,
|
|
1375
|
+
function KimiBundleConfig({ view, useSettings, scope, auth, authT, modelList, modelDirectory, checkEndpoint, endpointAuth, useSessions, t }) {
|
|
1376
|
+
const state = useCardState(view === "page", useSettings, scope, endpointAuth);
|
|
975
1377
|
if (view === "summary") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
976
1378
|
className: SettingsCard_module_css_default.description,
|
|
977
1379
|
children: t("card.description")
|
|
978
1380
|
});
|
|
979
1381
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardBody, {
|
|
980
1382
|
state,
|
|
1383
|
+
active: view === "page",
|
|
1384
|
+
auth,
|
|
1385
|
+
authT,
|
|
1386
|
+
modelList,
|
|
1387
|
+
modelDirectory,
|
|
1388
|
+
checkEndpoint,
|
|
1389
|
+
useSessions,
|
|
1390
|
+
t
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* The harness's section inside the core's「本机 Agent 委派」family card: the
|
|
1395
|
+
* same useCardState + CardBody the plugins.item page view renders — the
|
|
1396
|
+
* collapsible chrome belongs to the family card now.
|
|
1397
|
+
* @param props - the injected scope/auth faces, the forwarded session seat, and copy.
|
|
1398
|
+
* @returns the section body.
|
|
1399
|
+
*/
|
|
1400
|
+
function KimiCardSection({ active, useSettings, scope, auth, authT, modelList, modelDirectory, checkEndpoint, endpointAuth, useSessions, t }) {
|
|
1401
|
+
const state = useCardState(active, useSettings, scope, endpointAuth);
|
|
1402
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardBody, {
|
|
1403
|
+
state,
|
|
1404
|
+
active,
|
|
981
1405
|
auth,
|
|
982
1406
|
authT,
|
|
983
|
-
|
|
1407
|
+
modelList,
|
|
1408
|
+
modelDirectory,
|
|
1409
|
+
checkEndpoint,
|
|
984
1410
|
useSessions,
|
|
985
1411
|
t
|
|
986
1412
|
});
|
|
@@ -988,18 +1414,35 @@ window.__ModuleLoader__.load({
|
|
|
988
1414
|
//#endregion
|
|
989
1415
|
//#region src/client/index.ts
|
|
990
1416
|
/**
|
|
991
|
-
*
|
|
992
|
-
*
|
|
993
|
-
*
|
|
1417
|
+
* Local-agent-kimi plugin, browser half: the kimi settings card — a section
|
|
1418
|
+
* of the family core's「本机 Agent 委派」family card on the Plugins page
|
|
1419
|
+
* (registered through the core's `localAgentUi.registerHarnessCard` while the
|
|
1420
|
+
* Host serves the `local-agent-kimi` namespace), or this package's own
|
|
1421
|
+
* `plugins.item` entry when the core predates the family card (the
|
|
1422
|
+
* declare-and-degrade fallback). Every
|
|
1423
|
+
* install shape serves the row's volatile Config under the row id —
|
|
1424
|
+
* standalone install, family bundle, or mode pack — so the card follows the
|
|
1425
|
+
* served namespace rather than any carrier bundle, and a composition without
|
|
1426
|
+
* the row shows no trace of it. The card carries the family core's shared
|
|
1427
|
+
* ProviderAuthBlock (login/logout/device-code, backed by the core's
|
|
1428
|
+
* localAgentGateway Remote and the commands channel), the endpoint credential
|
|
1429
|
+
* form, the family core's shared ModelListSection (the curated ordered
|
|
1430
|
+
* shortlist — first entry is the default model — edited through the
|
|
1431
|
+
* gateway's modelList/configureModelList Remotes), and the
|
|
1432
|
+
* resident-mode switch, whose writes ride the bound settingsScope — the host
|
|
1433
|
+
* watcher hot-applies them, no reload. Every read degrades: an absent gateway
|
|
1434
|
+
* renders the auth block's 'unavailable' state and drops the model surfaces,
|
|
1435
|
+
* an unregistered namespace disables the live controls.
|
|
1436
|
+
* @module @khorsheed/dsh-local-agent-kimi/client
|
|
994
1437
|
*/
|
|
995
|
-
const PACKAGE_NAME = "@khorsheed/dsh-local-agent-kimi";
|
|
996
1438
|
/**
|
|
997
1439
|
* Required services: slot registry, command Remote, and locale registry. The
|
|
998
1440
|
* settings scope is NOT a static inject — its service name differs per host
|
|
999
1441
|
* line (`settingsScope` on 0.1.5, `configForms` on rc.1), so a static entry
|
|
1000
1442
|
* would pend the whole client plugin on the other line; bindSettingsScope
|
|
1001
1443
|
* probes the serving one instead (the settings client package is a declared
|
|
1002
|
-
* client inject, so one of them is always already up).
|
|
1444
|
+
* client inject, so one of them is always already up). The card track probes
|
|
1445
|
+
* `configForms` through the same kind of deferred inject (see apply).
|
|
1003
1446
|
*/
|
|
1004
1447
|
const inject = [
|
|
1005
1448
|
"slots",
|
|
@@ -1008,8 +1451,8 @@ window.__ModuleLoader__.load({
|
|
|
1008
1451
|
"locale"
|
|
1009
1452
|
];
|
|
1010
1453
|
/**
|
|
1011
|
-
* Client plugin body: register the dictionaries and the kimi settings
|
|
1012
|
-
*
|
|
1454
|
+
* Client plugin body: register the dictionaries and the kimi settings card
|
|
1455
|
+
* bound to the local-agent-kimi namespace.
|
|
1013
1456
|
* @param ctx - client root context.
|
|
1014
1457
|
*/
|
|
1015
1458
|
function apply(ctx) {
|
|
@@ -1017,42 +1460,91 @@ window.__ModuleLoader__.load({
|
|
|
1017
1460
|
zh,
|
|
1018
1461
|
en
|
|
1019
1462
|
}), "local-agent-kimi: dictionaries");
|
|
1463
|
+
const t = ctx.locale.bind(NS);
|
|
1020
1464
|
const scope = bindSettingsScope(ctx, "local-agent-kimi");
|
|
1021
1465
|
const authT = ctx.locale.bind("local-agent");
|
|
1022
1466
|
const gateway = () => ctx.get("remote.localAgentGateway");
|
|
1023
|
-
const
|
|
1467
|
+
const cardFace = () => ({
|
|
1024
1468
|
scope,
|
|
1025
|
-
hooks: { settings: scope },
|
|
1026
1469
|
authT,
|
|
1027
|
-
|
|
1028
|
-
|
|
1470
|
+
modelList: {
|
|
1471
|
+
read: () => {
|
|
1472
|
+
const gw = gateway();
|
|
1473
|
+
if (gw === void 0 || typeof gw.modelList !== "function") return Promise.resolve(void 0);
|
|
1474
|
+
return gw.modelList("kimi").then((result) => result.ok ? result.value : void 0);
|
|
1475
|
+
},
|
|
1476
|
+
write: (models) => {
|
|
1477
|
+
const gw = gateway();
|
|
1478
|
+
if (gw === void 0 || typeof gw.configureModelList !== "function") return Promise.resolve(void 0);
|
|
1479
|
+
return gw.configureModelList("kimi", models).then((result) => result.ok ? result.value : void 0);
|
|
1480
|
+
}
|
|
1481
|
+
},
|
|
1482
|
+
modelDirectory: (refresh) => {
|
|
1483
|
+
const gw = gateway();
|
|
1484
|
+
if (gw === void 0 || typeof gw.modelDirectory !== "function") return Promise.resolve(void 0);
|
|
1485
|
+
return gw.modelDirectory("kimi", void 0, refresh ?? false).then((result) => result.ok ? result.value : void 0);
|
|
1486
|
+
},
|
|
1487
|
+
checkEndpoint: () => {
|
|
1488
|
+
const gw = gateway();
|
|
1489
|
+
if (gw === void 0 || typeof gw.checkEndpoint !== "function") return Promise.resolve(void 0);
|
|
1490
|
+
return gw.checkEndpoint("kimi").then((result) => result.ok ? result.value : void 0);
|
|
1491
|
+
},
|
|
1492
|
+
endpointAuth: {
|
|
1493
|
+
read: () => {
|
|
1494
|
+
const gw = gateway();
|
|
1495
|
+
if (gw === void 0 || typeof gw.endpointAuth !== "function") return Promise.resolve(void 0);
|
|
1496
|
+
return gw.endpointAuth("kimi").then((result) => result.ok ? result.value : void 0);
|
|
1497
|
+
},
|
|
1498
|
+
write: (fields) => {
|
|
1499
|
+
const gw = gateway();
|
|
1500
|
+
if (gw === void 0 || typeof gw.configureEndpoint !== "function") return Promise.resolve(void 0);
|
|
1501
|
+
return gw.configureEndpoint("kimi", fields).then((result) => result.ok ? result.value : void 0);
|
|
1502
|
+
}
|
|
1503
|
+
},
|
|
1029
1504
|
auth: {
|
|
1030
1505
|
status: (name) => gateway()?.status(name, void 0).then((result) => result.ok ? result.value : void 0) ?? Promise.resolve(void 0),
|
|
1031
1506
|
runCommand: (sessionId, line) => ctx.remote.commands.execute(sessionId, line, []).then((result) => result.ok ? result.value?.result.text : void 0)
|
|
1032
1507
|
}
|
|
1033
1508
|
});
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1509
|
+
const cardInject = () => ({
|
|
1510
|
+
...cardFace(),
|
|
1511
|
+
hooks: { settings: scope }
|
|
1512
|
+
});
|
|
1513
|
+
const subscribeScope = (listener) => scope.subscribe(listener);
|
|
1514
|
+
const readScope = () => scope.getSnapshot();
|
|
1515
|
+
const useSettings = (select) => select((0, react.useSyncExternalStore)(subscribeScope, readScope));
|
|
1516
|
+
ctx.inject(["configForms"], (formsCtx) => {
|
|
1517
|
+
const forms = formsCtx.configForms;
|
|
1518
|
+
if (typeof forms.whileServed !== "function") return;
|
|
1519
|
+
return forms.whileServed(["local-agent-kimi"], () => {
|
|
1520
|
+
const ui = ctx.get("localAgentUi");
|
|
1521
|
+
if (typeof ui?.registerHarnessCard === "function") return ui.registerHarnessCard({
|
|
1522
|
+
name: "kimi",
|
|
1523
|
+
order: 110,
|
|
1524
|
+
locale: NS,
|
|
1525
|
+
label: () => t("card.title"),
|
|
1526
|
+
render: ({ active, useSessions }) => (0, react.createElement)(KimiCardSection, {
|
|
1527
|
+
active,
|
|
1528
|
+
useSessions,
|
|
1529
|
+
...cardFace(),
|
|
1530
|
+
useSettings,
|
|
1531
|
+
t
|
|
1532
|
+
})
|
|
1533
|
+
});
|
|
1534
|
+
return ctx.slots.inject("plugins.item", () => ctx.slots.register({
|
|
1535
|
+
name: "plugins.item",
|
|
1536
|
+
id: "local-agent-kimi",
|
|
1537
|
+
order: 110,
|
|
1538
|
+
label: () => t("card.title"),
|
|
1539
|
+
locale: NS,
|
|
1540
|
+
inject: cardInject
|
|
1541
|
+
}, KimiBundleConfig));
|
|
1542
|
+
});
|
|
1543
|
+
});
|
|
1053
1544
|
}
|
|
1054
1545
|
//#endregion
|
|
1055
1546
|
exports.KimiBundleConfig = KimiBundleConfig;
|
|
1547
|
+
exports.KimiCardSection = KimiCardSection;
|
|
1056
1548
|
exports.KimiSettingsCard = KimiSettingsCard;
|
|
1057
1549
|
exports.NS = NS;
|
|
1058
1550
|
exports.apply = apply;
|