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