@fa-software/semi2-dsh 0.0.13 → 0.0.14-preview.20260922151653

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +20 -7
  2. package/lib/api/generated/documents.js +10 -1
  3. package/lib/api/generated/schema.js +2 -9
  4. package/lib/api/index.js +13 -0
  5. package/lib/client.js +54 -48
  6. package/lib/client.js.map +1 -1
  7. package/lib/contract.js +6 -0
  8. package/lib/domains/models/domain.js +11 -4
  9. package/lib/domains/models/web-search.js +61 -0
  10. package/lib/domains/redmine/domain.js +139 -0
  11. package/lib/domains/redmine/index.js +57 -0
  12. package/lib/domains/skills/candidates.js +4 -2
  13. package/lib/domains/skills/domain.js +5 -3
  14. package/lib/domains/workspace/domain.js +3 -2
  15. package/lib/hub/facts.js +1 -0
  16. package/lib/index.js +10 -11
  17. package/lib/service/audit.js +21 -7
  18. package/lib/service/config-service.js +9 -22
  19. package/lib/service/lifecycle.js +32 -34
  20. package/lib/service/namespaces.js +46 -16
  21. package/lib/service/ports.js +36 -13
  22. package/lib/service/publish.js +8 -8
  23. package/lib/service/registry.js +2 -0
  24. package/lib/service/sessions.js +90 -0
  25. package/lib/service/settings-sections.js +23 -62
  26. package/lib/types/api/generated/documents.d.ts +1 -1
  27. package/lib/types/api/generated/graphql.d.ts +27 -5
  28. package/lib/types/api/generated/schema.d.ts +265 -60
  29. package/lib/types/api/index.d.ts +13 -1
  30. package/lib/types/contract.d.ts +11 -0
  31. package/lib/types/domains/models/web-search.d.ts +8 -0
  32. package/lib/types/domains/redmine/domain.d.ts +59 -0
  33. package/lib/types/domains/redmine/index.d.ts +10 -0
  34. package/lib/types/domains/skills/domain.d.ts +1 -1
  35. package/lib/types/domains/types.d.ts +8 -2
  36. package/lib/types/hub/facts.d.ts +18 -0
  37. package/lib/types/index.d.ts +28 -24
  38. package/lib/types/service/audit.d.ts +10 -0
  39. package/lib/types/service/config-service.d.ts +3 -1
  40. package/lib/types/service/lifecycle.d.ts +5 -0
  41. package/lib/types/service/namespaces.d.ts +15 -17
  42. package/lib/types/service/ports.d.ts +19 -15
  43. package/lib/types/service/publish.d.ts +6 -1
  44. package/lib/types/service/sessions.d.ts +8 -0
  45. package/lib/types/service/settings-sections.d.ts +5 -14
  46. package/lib/types/web/routes.d.ts +4 -2
  47. package/lib/types/web/welcome-ack.d.ts +3 -3
  48. package/lib/web/routes.js +25 -1
  49. package/lib/web/welcome-ack.js +5 -5
  50. package/package.json +19 -11
package/README.md CHANGED
@@ -1,10 +1,15 @@
1
1
  # @fa-software/semi2-dsh
2
2
 
3
3
  跑在 DeepSeek Harness(dsh)之上的单插件,三个运行面共用。它从 semi2-hub 领取用户级配置
4
- (身份、模型目录与密钥、技能目录、自画像、已登记工作区命中的项目绑定),把结果落成 dsh 的设置
5
- 命名空间与服务,并注册设置页用的登录 / 登出 / 健康路由。CodeGraph 不在本插件里:工具面由
4
+ (身份、模型目录与密钥、技能目录、自画像、已登记工作区命中的项目绑定),把结果落成**自身设置段**
5
+ (Profile 条目 `semi2-dsh`,状态 / 归属表 / 工作区映射同段)与服务,并注册设置页用的登录 / 登出 /
6
+ 同步 / 健康路由。CodeGraph 不在本插件里:工具面由
6
7
  bundle patch 挂载的官方 MCP 服务提供。
7
8
 
9
+ Redmine 走另一条路:地址与密钥都来自 hub,插件按 hub 下发的 `runtimeRedmine` 在运行期用官方
10
+ `@deepseek-ai/dsh-mcp-client` 起 `redmine-mcp-server`(`mcp__redmine__*`,只读)。未配置即不挂,
11
+ 配置变化先卸旧光纤再挂新的,登出时卸载。
12
+
8
13
  ## Config
9
14
 
10
15
  每个字段都在 patch 行不写 `config` 时取默认值,消费方 overlay 才覆盖。
@@ -14,11 +19,11 @@ bundle patch 挂载的官方 MCP 服务提供。
14
19
  | `contractTimeoutMs` | 5000 | 等运行面契约 `semi2Runtime` 出现的上限;超时按宿主直跑处理 |
15
20
  | `domainAttachTimeoutMs` | 2000 | 等领域装配的上限;超时的领域记「本面不提供该能力」 |
16
21
  | `settingsTimeoutMs` | 5000 | 等 `settings` 服务的上限;本面无该服务时不阻塞启动 |
17
- | `namespaceWaitMs` | 2000 | 等命名空间注册完成再写的上限 |
22
+ | `namespaceWaitMs` | 2000 | 等设置段可读可写(条目 ACTIVE 且声明了 volatile 字段)的上限 |
18
23
  | `credentialRetryTries` | 10 | 凭据存储首次读盘的重试次数 |
19
24
  | `credentialRetryIntervalMs` | 150 | 凭据重试间隔(ms) |
20
25
  | `webFenceTimeoutMs` | 5000 | `webServer` 在而校验面迟迟不出现时补一条诊断日志的上限 |
21
- | `webRouteBodyLimitBytes` | 8192 | `/semi2/{login,logout,health}` 的请求体上限(字节) |
26
+ | `webRouteBodyLimitBytes` | 8192 | `/semi2/{login,logout,sync,health}` 的请求体上限(字节) |
22
27
 
23
28
  ## 提供的服务与事件
24
29
 
@@ -27,7 +32,7 @@ bundle patch 挂载的官方 MCP 服务提供。
27
32
  | 服务 | 读取面 | 缺省语义 |
28
33
  |---|---|---|
29
34
  | `semi2Config` | `state` / `ready` / `platform` / `selectHeadlessModel` | 配置未就绪 `state.status != 'ready'` |
30
- | `semi2Session` | `login` / `logout` | 部署面给了凭据时登录以 `CREDENTIAL_SOURCE_READONLY` 拒绝 |
35
+ | `semi2Session` | `login` / `logout` / `sync` | 部署面给了凭据时登录以 `CREDENTIAL_SOURCE_READONLY` 拒绝 |
31
36
  | `semi2Health` | `snapshot()` | 每项 `ok` / `degraded` / `unavailable` / `failed` |
32
37
  | `semi2Audit` | `report(event)` | 未连接时返回 `ok:false` + `MISSING_ACCESS_TOKEN` |
33
38
 
@@ -47,5 +52,13 @@ bundle patch 挂载的官方 MCP 服务提供。
47
52
  - 任何解析 / 注入 / 领取失败只 warn,绝不 reject 或阻断会话;单块失败只降级该块。
48
53
  - 三个能力面之外的领域按自身依赖自门禁:缺 `skills` / `systemPrompt` 的宿主上领域光纤停在等待,
49
54
  编排层记为「本面不提供该能力」,插件整体照常加载。
50
- - 优雅卸载(`ctx.effect` 的 disposer)回一条 `SESSION_END`;进程被 SIGKILL / 容器停止没有结束行。
51
- - `personaPrefix` 无法运行时改:dsh-system-prompt 不注册 settings 命名空间,那份配置只来自组合文件。
55
+ - Redmine 领域挂载 MCP 服务:`REDMINE_MCP_READ_ONLY=true` 保证只读;`runtimeRedmine` 读取失败时
56
+ 保持现状(不动已挂服务),两项任缺即卸载;挂载 / 就绪失败只 warn 并把健康项记为 `degraded`。
57
+ 缺 `redmine-mcp-server`(PATH)或 `@deepseek-ai/dsh-mcp-client`(闭包)都只影响这一项,
58
+ 可用 `SEMI2_REDMINE_MCP_BIN` 指到别处的可执行文件。
59
+ - 每次会话由 `service/sessions.ts` 旁听 dsh 的 `session/created` / `session/disposed` 各回一条;进程被 SIGKILL / 容器停止没有销毁行(控制台显示「无结束行」),子 agent 会话不上报。
60
+ - `personaPrefix` 无法运行时改:dsh-system-prompt 的配置只来自组合文件。
61
+ - 设置段只列「光纤 ACTIVE 且 Config 声明了 volatile 字段」的条目:本插件的状态 / 归属表 / 工作区映射
62
+ 全部 declared volatile(可实时写、不重挂载),数值旋钮是加载期参数不在此列。
63
+ - 状态写入用合并语义(同一段里还有归属表与工作区映射):`replace` 会把它们一起重置,故本插件不在
64
+ 自身段上用 `replace`。
@@ -24,12 +24,17 @@ export const RUNTIME_BOOT_DOCUMENT = `query RuntimeBoot {
24
24
  connectionId
25
25
  value
26
26
  }
27
- runtimeSkills {
27
+ runtimeSkillCatalog {
28
28
  id
29
29
  projectId
30
30
  name
31
31
  description
32
32
  whenToUse
33
+ invocation {
34
+ modelInvocable
35
+ userInvocable
36
+ }
37
+ metadata
33
38
  content
34
39
  version
35
40
  files {
@@ -42,6 +47,10 @@ export const RUNTIME_BOOT_DOCUMENT = `query RuntimeBoot {
42
47
  filesBytes
43
48
  }
44
49
  runtimeSelfPortrait
50
+ runtimeRedmine {
51
+ baseUrl
52
+ apiKey
53
+ }
45
54
  }`;
46
55
  /** 技能附属资源字节:boot 文档只带清单,真正加载某个技能时才按需取这一条。可空根字段:读取者不可见 / 不存在回空数组(权威「没有」),领域失败回 null(降级,不物化)。 */
47
56
  export const RUNTIME_SKILL_FILES_DOCUMENT = `query RuntimeSkillFiles($skillId: ID!) {
@@ -6,14 +6,6 @@ export var AuditActorKind;
6
6
  AuditActorKind["Session"] = "SESSION";
7
7
  AuditActorKind["UserKey"] = "USER_KEY";
8
8
  })(AuditActorKind || (AuditActorKind = {}));
9
- /** 审查类别:读 / 写 / 身份凭据 / 运行面生命周期。 */
10
- export var AuditCategory;
11
- (function (AuditCategory) {
12
- AuditCategory["Auth"] = "AUTH";
13
- AuditCategory["Read"] = "READ";
14
- AuditCategory["Runtime"] = "RUNTIME";
15
- AuditCategory["Write"] = "WRITE";
16
- })(AuditCategory || (AuditCategory = {}));
17
9
  /** 来源面:控制台 / NPC / 云开发工作站 / 容器 Web / 宿主直跑 / 未标注。 */
18
10
  export var AuditChannel;
19
11
  (function (AuditChannel) {
@@ -112,7 +104,8 @@ export var RuntimeEventAction;
112
104
  (function (RuntimeEventAction) {
113
105
  RuntimeEventAction["DeliveryReady"] = "DELIVERY_READY";
114
106
  RuntimeEventAction["DeliveryVerified"] = "DELIVERY_VERIFIED";
115
- RuntimeEventAction["SessionEnd"] = "SESSION_END";
107
+ RuntimeEventAction["SessionCreated"] = "SESSION_CREATED";
108
+ RuntimeEventAction["SessionDisposed"] = "SESSION_DISPOSED";
116
109
  RuntimeEventAction["SessionFailed"] = "SESSION_FAILED";
117
110
  RuntimeEventAction["SessionRefused"] = "SESSION_REFUSED";
118
111
  RuntimeEventAction["SessionStart"] = "SESSION_START";
package/lib/api/index.js CHANGED
@@ -50,6 +50,19 @@ export function createSemi2Api(options) {
50
50
  ? {}
51
51
  : { targetLabel: event.targetLabel }),
52
52
  ...(event.detail === undefined ? {} : { detail: event.detail }),
53
+ ...(event.sessionId === undefined ? {} : { sessionId: event.sessionId }),
54
+ ...(event.clientId === undefined ? {} : { clientId: event.clientId }),
55
+ ...(event.runRef === undefined ? {} : { runRef: event.runRef }),
56
+ ...(event.workspacePath === undefined
57
+ ? {}
58
+ : { workspacePath: event.workspacePath }),
59
+ ...(event.workspaceSlug === undefined
60
+ ? {}
61
+ : { workspaceSlug: event.workspaceSlug }),
62
+ ...(event.modelId === undefined ? {} : { modelId: event.modelId }),
63
+ ...(event.reasoningLevel === undefined
64
+ ? {}
65
+ : { reasoningLevel: event.reasoningLevel }),
53
66
  },
54
67
  }),
55
68
  };
package/lib/client.js CHANGED
@@ -7,6 +7,14 @@ window.__ModuleLoader__.load({
7
7
  let react = require("react");
8
8
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region src/contract.ts
11
+ /**
12
+ * 插件自身设置段的条目 id:dsh 的设置命名空间就是 Profile 插件条目 id(bundle patch 里那一行的 id),
13
+ * 状态 / 健康 / 归属表 / 工作区映射都写在这一段里。host 与浏览器半边共用这一个常量
14
+ * (`cordis.patch.yml` 的插件行 id 必须与它一致,`test/dsh/unit/profile-patch.test.mjs` 对账)。
15
+ */
16
+ const SEMI2_SETTINGS_ENTRY = "semi2-dsh";
17
+ //#endregion
10
18
  //#region src/client/controller.js
11
19
  const OVERVIEW_KEY = "overview";
12
20
  const STATUS_KEYS = /* @__PURE__ */ new Set([
@@ -118,7 +126,7 @@ window.__ModuleLoader__.load({
118
126
  var Semi2Controller = class {
119
127
  constructor(ctx) {
120
128
  this.ctx = ctx;
121
- this.scope = ctx.settingsScope.bind({ namespace: "semi2" });
129
+ this.scope = ctx.configForms.get(SEMI2_SETTINGS_ENTRY);
122
130
  this.listeners = /* @__PURE__ */ new Set();
123
131
  this.snapshot = this.scope.getSnapshot();
124
132
  this.unsubscribe = this.scope.subscribe(() => {
@@ -174,15 +182,14 @@ window.__ModuleLoader__.load({
174
182
  return outcome;
175
183
  }
176
184
  /**
177
- * 同步:写 `sync` 字段(用户写入即触发 host 重载,host 回报后复位为空)。
185
+ * 同步:POST 到自建路由(与登录 / 登出同一条通道),host 侧据此重载。
178
186
  * value 带范围:`global`(默认)或 `workspace:<slug>`(只同步该工作区)。
179
187
  */
180
188
  async sync(value = "global") {
181
189
  if (!this.getSnapshot().projected.writable) return;
182
- try {
183
- await this.scope.set("sync", value);
184
- } catch (error) {
185
- this.actionError = "CONFIG_REQUEST_FAILED";
190
+ const outcome = await callRoute("/semi2/sync", { scope: value });
191
+ if (!outcome.ok) {
192
+ this.actionError = outcome.code;
186
193
  this.notify();
187
194
  }
188
195
  }
@@ -270,6 +277,16 @@ window.__ModuleLoader__.load({
270
277
  label: t("domainSelfPortrait"),
271
278
  value: fields.selfPortrait || t("none")
272
279
  }]
280
+ },
281
+ {
282
+ id: "redmine",
283
+ labelKey: "domainRedmine",
284
+ /** 总览行:hub 下发的 Redmine 地址 + 本人密钥是否齐备(未配置 / 读取失败 / 已启用)。 */
285
+ overviewRow: (t, fields) => [{
286
+ key: "redmine",
287
+ label: t("domainRedmine"),
288
+ value: fields.redmine || t("none")
289
+ }]
273
290
  }
274
291
  ];
275
292
  /** 健康项解码(host 写的是 `state:text` 编码串;解析失败按未知处理)。 */
@@ -318,6 +335,10 @@ window.__ModuleLoader__.load({
318
335
  {
319
336
  key: "health:self-portrait",
320
337
  labelKey: "domainSelfPortrait"
338
+ },
339
+ {
340
+ key: "health:redmine",
341
+ labelKey: "domainRedmine"
321
342
  }
322
343
  ];
323
344
  //#endregion
@@ -377,7 +398,7 @@ window.__ModuleLoader__.load({
377
398
  //#region src/client/page.jsx
378
399
  /** 侧栏导航行图标(官方写法:function PanelIcon({ size }))。 */
379
400
  function Semi2PanelIcon({ size }) {
380
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size });
401
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutlineRegular, { size });
381
402
  }
382
403
  /** tab 键:slug 暂未解析出来的工作区退回标题占位。 */
383
404
  function tabKey(tab) {
@@ -606,7 +627,7 @@ window.__ModuleLoader__.load({
606
627
  }),
607
628
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
608
629
  className: "semi2-disclosure",
609
- icon: fields.error === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInfoOutline14, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16, {}),
630
+ icon: fields.error === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInfoOutlineRegular, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutlineRegular, {}),
610
631
  title: fields.error === "" ? t("diagnostics") : `${t("diagnostics")}:${fields.error}`,
611
632
  open: diagnosticsOpen,
612
633
  expandable: true,
@@ -773,6 +794,7 @@ window.__ModuleLoader__.load({
773
794
  domainWorkspace: "工作区",
774
795
  domainDefaultModel: "默认模型",
775
796
  domainSelfPortrait: "自画像",
797
+ domainRedmine: "Redmine",
776
798
  workspaces: "工作区列表",
777
799
  projects: "项目绑定",
778
800
  model: "默认模型(hub 下发)",
@@ -842,6 +864,7 @@ window.__ModuleLoader__.load({
842
864
  domainWorkspace: "Workspaces",
843
865
  domainDefaultModel: "Default model",
844
866
  domainSelfPortrait: "Self-portrait",
867
+ domainRedmine: "Redmine",
845
868
  workspaces: "Workspaces",
846
869
  projects: "Project bindings",
847
870
  model: "Default model (from hub)",
@@ -956,7 +979,7 @@ window.__ModuleLoader__.load({
956
979
  const PANEL_ID = "semi2";
957
980
  const inject = [
958
981
  "slots",
959
- "settingsScope",
982
+ "configForms",
960
983
  "locale"
961
984
  ];
962
985
  function apply(ctx) {
@@ -993,51 +1016,34 @@ window.__ModuleLoader__.load({
993
1016
  workspaceEntries.set(key, dispose);
994
1017
  }
995
1018
  };
996
- const describeFace = ctx.settingsScope.describe();
997
- ctx.effect(() => {
1019
+ ctx.effect(() => ctx.configForms.whileServed([SEMI2_SETTINGS_ENTRY], () => {
998
1020
  const registered = /* @__PURE__ */ new Map();
999
- const sync = () => {
1000
- const available = new Set(describeFace.getSnapshot().view?.namespaces.map((view) => view.ns) ?? []).has(NS);
1001
- const off = registered.get("panel");
1002
- if (available && off === void 0) {
1003
- syncWorkspaceEntries();
1004
- const unsubscribe = controller.subscribe(syncWorkspaceEntries);
1005
- registered.set("tabs", unsubscribe);
1006
- registered.set("panel", ctx.slots.inject("main", () => ctx.slots.register({
1007
- name: "main",
1008
- key: PANEL_ID,
1009
- locale: NS,
1010
- children: { "semi2.workspace": {
1011
- kind: "keyed",
1012
- scope: "root"
1013
- } },
1014
- inject: () => ({ controller })
1015
- }, Semi2Page)));
1016
- registered.set("sidebar", ctx.slots.inject("sidebar.panellist", () => ctx.slots.register({
1017
- name: "sidebar.panellist",
1018
- id: PANEL_ID,
1019
- order: 10,
1020
- label: () => t("panel"),
1021
- locale: NS
1022
- }, Semi2PanelIcon)));
1023
- } else if (!available && off !== void 0) {
1024
- for (const dispose of registered.values()) dispose();
1025
- registered.clear();
1026
- for (const dispose of workspaceEntries.values()) dispose();
1027
- workspaceEntries.clear();
1028
- }
1029
- };
1030
- const unsubscribe = describeFace.subscribe(sync);
1031
- describeFace.ensure();
1032
- sync();
1021
+ syncWorkspaceEntries();
1022
+ registered.set("tabs", controller.subscribe(syncWorkspaceEntries));
1023
+ registered.set("panel", ctx.slots.inject("main", () => ctx.slots.register({
1024
+ name: "main",
1025
+ key: PANEL_ID,
1026
+ locale: NS,
1027
+ children: { "semi2.workspace": {
1028
+ kind: "keyed",
1029
+ scope: "root"
1030
+ } },
1031
+ inject: () => ({ controller })
1032
+ }, Semi2Page)));
1033
+ registered.set("sidebar", ctx.slots.inject("sidebar.panellist", () => ctx.slots.register({
1034
+ name: "sidebar.panellist",
1035
+ id: PANEL_ID,
1036
+ order: 10,
1037
+ label: () => t("panel"),
1038
+ locale: NS
1039
+ }, Semi2PanelIcon)));
1033
1040
  return () => {
1034
- unsubscribe();
1035
1041
  for (const dispose of registered.values()) dispose();
1042
+ registered.clear();
1036
1043
  for (const dispose of workspaceEntries.values()) dispose();
1037
1044
  workspaceEntries.clear();
1038
- registered.clear();
1039
1045
  };
1040
- }, "semi2: sidebar entry + main page");
1046
+ }), "semi2: sidebar entry + main page");
1041
1047
  }
1042
1048
  //#endregion
1043
1049
  exports.PANEL_ID = PANEL_ID;
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["relativeTime","useState","useMemo","Row","IconLinkOutline16","useState","Input","Button","StateDot","DisclosureRow","IconInfoOutline14","IconWarningOutline16","useMemo"],"sources":["../src/client/controller.js","../src/client/domains.js","../src/client/workspace-tab.jsx","../src/client/page.jsx","../src/client/locales.js","../src/client/styles.js","../src/client/index.jsx"],"sourcesContent":["// @fa-software/semi2-dsh/client/controller —— Semi2 控制器:设置作用域镜像 + 动作(登录/登出/同步)。\n// 交互语义照官方:输入只在提交时发出;写入失败保留草稿并报错;离开页面丢弃草稿。\n// 同步走 `sync` 字段(用户写入即触发 host 重载,无令牌比对轮询)。\nimport { useEffect, useMemo, useState } from 'react'\nimport { relativeTime } from '@deepseek-ai/dsh-client-ui-primitives'\n\nexport const OVERVIEW_KEY = 'overview'\n\nconst STATUS_KEYS = new Set(['local', 'loading', 'ready', 'failed'])\n\n/** 状态字段由 host 侧 STATUS_FIELDS + 健康字段定义:全为扁平标量字符串。 */\nfunction projectSnapshot(snapshot) {\n const value = snapshot?.value\n if (value === undefined || typeof value.status !== 'string' || !STATUS_KEYS.has(value.status)) {\n return { ready: false, fields: {}, tabs: [], writable: false, revision: undefined }\n }\n const tabs = Array.isArray(value.workspaceTabs) ? value.workspaceTabs : []\n return {\n ready: true,\n fields: value,\n tabs,\n writable: snapshot.writable === true,\n revision: snapshot.revision,\n }\n}\n\n/** 运行面原值(数据层只存 cnb / container / host)→ 展示标签(本地化)。 */\nexport function platformText(t, platform) {\n if (platform === '' || platform === undefined) return '—'\n return t(`surface${platform}`) || platform\n}\n\nexport function statusText(t, status) {\n return (\n { local: t('statusLocal'), loading: t('statusLoading'), ready: t('statusReady'), failed: t('statusFailed') }[status] ??\n status\n )\n}\n\n/** 时间分桶(官方 relativeTime)→ 本字典措辞;解析不了的时间戳原样返回。 */\nfunction timeUnitKey(unit) {\n switch (unit) {\n case 'minutes':\n return 'timeMinutes'\n case 'hours':\n return 'timeHours'\n case 'days':\n return 'timeDays'\n case 'months':\n return 'timeMonths'\n case 'years':\n return 'timeYears'\n default:\n return null\n }\n}\n\nexport function timeText(t, value) {\n if (value === undefined || value === '') return '—'\n const at = Date.parse(value)\n if (Number.isNaN(at)) return value\n const { unit, n } = relativeTime(at, Date.now())\n const key = timeUnitKey(unit)\n return key === null ? t('timeNow') : t(key, { n })\n}\n\n/** 错误码 → 一句人话(表驱动;查不到原样显示码,非 JSON 应答由调用方落 HTTP 码)。 */\nexport function errorText(t, code) {\n return t(`err${code}`) || code\n}\n\n/**\n * 一次动作接口调用的统一出口:非 JSON 应答 → `HTTP <status>`;404/405 → WEB_ROUTE_UNAVAILABLE;\n * JSON 体带 code → 该码。绝不把非凭据错误伪装成 LOGIN_FAILED。\n */\nasync function callRoute(path, body) {\n let response\n try {\n response = await fetch(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body ?? {}),\n })\n } catch (error) {\n return { ok: false, code: 'CONFIG_REQUEST_FAILED' }\n }\n const text = await response.text()\n let parsed = null\n try {\n parsed = JSON.parse(text)\n } catch {\n parsed = null\n }\n if (parsed === null || typeof parsed !== 'object') {\n if (response.status === 404 || response.status === 405)\n return { ok: false, code: 'WEB_ROUTE_UNAVAILABLE' }\n return { ok: false, code: `HTTP ${String(response.status)}` }\n }\n const code = typeof parsed.code === 'string' ? parsed.code : ''\n if (!response.ok || parsed.ok !== true) return { ok: false, code: code || 'LOGIN_FAILED' }\n return { ok: true, code, body: parsed }\n}\n\nexport class Semi2Controller {\n constructor(ctx) {\n this.ctx = ctx\n this.scope = ctx.settingsScope.bind({ namespace: 'semi2' })\n this.listeners = new Set()\n this.snapshot = this.scope.getSnapshot()\n this.unsubscribe = this.scope.subscribe(() => {\n this.snapshot = this.scope.getSnapshot()\n for (const listener of this.listeners) listener()\n })\n this.loginBusy = false\n this.logoutBusy = false\n this.actionError = null\n }\n\n dispose() {\n this.unsubscribe()\n this.listeners.clear()\n }\n\n subscribe(listener) {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot() {\n return {\n projected: projectSnapshot(this.snapshot),\n loginBusy: this.loginBusy,\n logoutBusy: this.logoutBusy,\n actionError: this.actionError,\n }\n }\n\n notify() {\n for (const listener of this.listeners) listener()\n }\n\n /** 登录:草稿只在提交时发出;成功清空密码,失败保留草稿并报错。 */\n async login(draft) {\n if (this.loginBusy) return\n this.loginBusy = true\n this.actionError = null\n this.notify()\n const outcome = await callRoute('/semi2/login', draft)\n this.loginBusy = false\n if (!outcome.ok) this.actionError = outcome.code\n this.notify()\n return outcome\n }\n\n async logout() {\n if (this.logoutBusy) return\n this.logoutBusy = true\n this.actionError = null\n this.notify()\n const outcome = await callRoute('/semi2/logout', {})\n this.logoutBusy = false\n if (!outcome.ok) this.actionError = outcome.code\n this.notify()\n return outcome\n }\n\n /**\n * 同步:写 `sync` 字段(用户写入即触发 host 重载,host 回报后复位为空)。\n * value 带范围:`global`(默认)或 `workspace:<slug>`(只同步该工作区)。\n */\n async sync(value = 'global') {\n if (!this.getSnapshot().projected.writable) return\n try {\n await this.scope.set('sync', value)\n } catch (error) {\n this.actionError = 'CONFIG_REQUEST_FAILED'\n this.notify()\n }\n }\n}\n\n/** useSyncExternalStore 适配(控制器快照是稳定引用,动作后手动 bump)。 */\nexport function useController(controller) {\n const [version, setVersion] = useState(0)\n useEffect(() => controller.subscribe(() => setVersion((n) => n + 1)), [controller])\n return useMemo(() => ({ ...controller.getSnapshot(), version }), [controller, version])\n}\n","// @fa-software/semi2-dsh/client/domains —— 领域行渲染(与 host 注册表对账:五者一致契约测试钉住)。\n// 每个领域一个条目:总览 tab 的领域行 + 工作区 tab 的领域切片;页面骨架只按这张表渲染。\nimport { timeText } from './controller.js'\n\nexport const DOMAIN_SECTIONS = [\n {\n id: 'models',\n labelKey: 'domainModels',\n /** 总览行:默认模型(hub 下发的全局默认)。 */\n overviewRow: (t, fields) => [\n { key: 'model', label: t('model'), value: fields.model || t('none') },\n ],\n },\n {\n id: 'secrets',\n labelKey: 'domainSecrets',\n overviewRow: null,\n },\n {\n id: 'skills',\n labelKey: 'domainSkills',\n /** 总览行:控制台技能条数(空串 = 没拿到权威目录)。 */\n overviewRow: (t, fields) => [\n { key: 'skills', label: t('skills'), value: fields.skills === '' ? '—' : fields.skills },\n ],\n },\n {\n id: 'workspace',\n labelKey: 'domainWorkspace',\n /** 总览行:工作区与项目绑定。 */\n overviewRow: (t, fields) => [\n { key: 'workspaceCount', label: t('workspaceTitle'), value: fields.workspaceCount },\n { key: 'projectCount', label: t('projects'), value: fields.projectCount },\n ],\n /** 工作区 tab 切片:项目绑定(只显示该工作区自己的解析结果)。 */\n workspaceRow: (t, tab) => [\n { key: 'slug', label: t('workspaceSlug'), value: tab.slug || '—' },\n {\n key: 'project',\n label: t('workspaceProject'),\n value: tab.project || tab.projectId || '—',\n },\n { key: 'syncedAt', label: t('workspaceSyncedAt'), value: timeText(t, tab.syncedAt) },\n ],\n },\n {\n id: 'default-model',\n labelKey: 'domainDefaultModel',\n overviewRow: null,\n },\n {\n id: 'self-portrait',\n labelKey: 'domainSelfPortrait',\n /** 总览行:注入状态(未配置 / 读取失败 / 已注入 · N 字)。 */\n overviewRow: (t, fields) => [\n {\n key: 'selfPortrait',\n label: t('domainSelfPortrait'),\n value: fields.selfPortrait || t('none'),\n },\n ],\n },\n]\n\n/** 健康项解码(host 写的是 `state:text` 编码串;解析失败按未知处理)。 */\nexport function decodeHealth(raw) {\n if (typeof raw !== 'string' || raw === '') return null\n const separator = raw.indexOf(':')\n if (separator === -1) return { state: raw, note: '' }\n return { state: raw.slice(0, separator), note: raw.slice(separator + 1) }\n}\n\n/** 健康行(key = host 命名空间字段;labelKey 自己带,不挂在领域上)。 */\nexport const HEALTH_ROWS = [\n { key: 'healthWeb', labelKey: 'healthWebLabel' },\n { key: 'healthCodegraph', labelKey: 'healthCodegraphLabel' },\n { key: 'health:models', labelKey: 'domainModels' },\n { key: 'health:secrets', labelKey: 'domainSecrets' },\n { key: 'health:skills', labelKey: 'domainSkills' },\n { key: 'health:workspace', labelKey: 'domainWorkspace' },\n { key: 'health:default-model', labelKey: 'domainDefaultModel' },\n { key: 'health:self-portrait', labelKey: 'domainSelfPortrait' },\n]\n","// @fa-software/semi2-dsh/client/workspace-tab —— 单个工作区 tab 内容(只读该工作区的数据桶)。\n// 该工作区自己的解析结果与「最近更新时间」;不混其它工作区的数据。\n// 只出内容段:页面容器(padding / 页头 / tab 条 / 滚动)与操作按钮归 Semi2Page。\nimport { useEffect } from 'react'\nimport { DOMAIN_SECTIONS } from './domains.js'\nimport { useController, timeText } from './controller.js'\n\nfunction Row({ label, value }) {\n return (\n <div className=\"semi2-row\">\n <span className=\"semi2-rowKey\">{label}</span>\n <span className=\"semi2-rowValue\">{value}</span>\n </div>\n )\n}\n\nexport function WorkspaceTab({ t, controller, tab }) {\n const state = useController(controller)\n const { fields } = state.projected\n // 该工作区 tab 打开即请求一次按需刷新(host 侧按 slug 点名取,不拉全量表)。\n useEffect(() => {\n if (tab.slug !== '') void controller.sync(`workspace:${tab.slug}`)\n }, [tab.slug])\n return (\n <>\n <section className=\"semi2-section\">\n <h2 className=\"semi2-sectionTitle\">{tab.title}</h2>\n {DOMAIN_SECTIONS.map((section) => {\n const rows = section.workspaceRow?.(t, tab) ?? null\n if (rows === null) return null\n return (\n <section className=\"semi2-section\" key={section.id}>\n <h3 className=\"semi2-sectionTitle\">{t(section.labelKey)}</h3>\n <div className=\"semi2-rows\">\n {rows.map((row) => (\n <Row key={row.key} label={row.label} value={row.value} />\n ))}\n </div>\n </section>\n )\n })}\n {tab.projectId === '' && <p className=\"semi2-error\">{t('workspaceUnresolved')}</p>}\n </section>\n <p className=\"semi2-hint\">{`${t('loadedAt')}:${timeText(t, fields.loadedAt)}`}</p>\n </>\n )\n}\n","// @fa-software/semi2-dsh/client/page —— 主列整页(页头 + tab 条 + 总览/工作区内容)与侧栏图标。\n// 版面照官方主列页:页面容器自带 padding / 居中 / 960 上限,页头 h1+intro 且右侧放操作按钮,\n// tab 为下划线形态且只有一个时不渲染;未连接态只有一张登录卡片。\n// 控件全部来自官方原子包(Button/Input/StateDot/DisclosureRow/图标),样式走 styles.js。\nimport { useEffect, useMemo, useState } from 'react'\nimport { Button, Input, StateDot, DisclosureRow } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { IconInfoOutline14, IconLinkOutline16, IconWarningOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { DOMAIN_SECTIONS, HEALTH_ROWS, decodeHealth } from './domains.js'\nimport { WorkspaceTab } from './workspace-tab.jsx'\nimport {\n OVERVIEW_KEY,\n errorText,\n platformText,\n statusText,\n timeText,\n useController,\n} from './controller.js'\n\n/** 侧栏导航行图标(官方写法:function PanelIcon({ size }))。 */\nexport function Semi2PanelIcon({ size }) {\n return <IconLinkOutline16 size={size} />\n}\n\n/** tab 键:slug 暂未解析出来的工作区退回标题占位。 */\nfunction tabKey(tab) {\n return tab.slug === '' ? `title:${tab.title}` : `workspace:${tab.slug}`\n}\n\n/** 连接面:`showLogin` 为真时整页只剩登录卡片,页头不给操作按钮。 */\nfunction connectionMode(projected) {\n const connected = projected.fields.status === 'ready' || projected.fields.status === 'failed'\n return { connected, showLogin: projected.fields.credentialSource === '' || !connected }\n}\n\n/** 动作失败码 → 一句人话(非 JSON 应答已是 HTTP 码,原样显示)。 */\nfunction actionErrorText(t, code) {\n return code.startsWith('HTTP') ? code : errorText(t, code)\n}\n\nfunction Row({ label, value, muted }) {\n return (\n <div className=\"semi2-row\">\n <span className=\"semi2-rowKey\">{label}</span>\n <span className={muted === true ? 'semi2-rowValue semi2-muted' : 'semi2-rowValue'}>{value}</span>\n </div>\n )\n}\n\n/** 页头:左列标题/说明/告示,右侧 `toolbar` 子节点放当前面的操作按钮(没有就不渲染工具条)。 */\nfunction PageHead({ t, hint, error, toolbar }) {\n return (\n <header className=\"semi2-head\">\n <div className=\"semi2-headText\">\n <h1 className=\"semi2-title\">{t('title')}</h1>\n <p className=\"semi2-intro\">{t('intro')}</p>\n {hint !== undefined && <p className=\"semi2-hint\">{hint}</p>}\n {error !== undefined && <p className=\"semi2-error\">{error}</p>}\n </div>\n {toolbar !== undefined && <div className=\"semi2-toolbar\">{toolbar}</div>}\n </header>\n )\n}\n\nconst DOT_OF_STATUS = { local: 'idle', loading: 'ongoing', ready: 'done', failed: 'error' }\n\nfunction tabDot(fields, tab) {\n if (fields.status === 'failed') return 'error'\n if (tab === null) return DOT_OF_STATUS[fields.status] ?? 'idle'\n return tab.projectId !== '' ? 'done' : 'idle'\n}\n\n/** 登录卡片:草稿只在提交时发出;未连接时整页只有它。 */\nfunction LoginCard({ t, projected, controller, actionError }) {\n const { fields, writable } = projected\n const [draft, setDraft] = useState(() => ({\n url: fields.consoleUrl ?? '',\n username: '',\n password: '',\n }))\n const snapshot = controller.getSnapshot()\n return (\n <section className=\"semi2-card\">\n <h2 className=\"semi2-cardTitle\">{t('loginTitle')}</h2>\n <form\n className=\"semi2-form\"\n onSubmit={(event) => {\n event.preventDefault()\n void controller.login(draft)\n }}\n >\n <Input\n aria-label={t('loginUrl')}\n placeholder={t('loginUrl')}\n value={draft.url}\n readOnly={!writable}\n onChange={(event) => setDraft((prev) => ({ ...prev, url: event.target.value }))}\n />\n <Input\n aria-label={t('loginUsername')}\n placeholder={t('loginUsername')}\n value={draft.username}\n onChange={(event) => setDraft((prev) => ({ ...prev, username: event.target.value }))}\n />\n <Input\n aria-label={t('loginPassword')}\n placeholder={t('loginPassword')}\n type=\"password\"\n value={draft.password}\n onChange={(event) => setDraft((prev) => ({ ...prev, password: event.target.value }))}\n />\n <div className=\"semi2-formActions\">\n <Button type=\"submit\" variant=\"primary\" disabled={snapshot.loginBusy}>\n {snapshot.loginBusy ? t('loginBusy') : t('loginSubmit')}\n </Button>\n </div>\n </form>\n {!writable && <p className=\"semi2-hint\">{t('errCREDENTIAL_SOURCE_READONLY')}</p>}\n {actionError !== undefined && <p className=\"semi2-error\">{actionError}</p>}\n </section>\n )\n}\n\nfunction OverviewTab({ t, projected, controller, actionError }) {\n const { fields } = projected\n const [diagnosticsOpen, setDiagnosticsOpen] = useState(false)\n const { showLogin } = connectionMode(projected)\n if (showLogin) return <LoginCard t={t} projected={projected} controller={controller} actionError={actionError} />\n const healthRows = HEALTH_ROWS.map((row) => ({\n ...row,\n item: decodeHealth(fields[row.key]),\n })).filter((row) => row.item !== null)\n const degraded = healthRows.filter((row) => row.item.state !== 'ok')\n return (\n <>\n <section className=\"semi2-section\">\n <h2 className=\"semi2-sectionTitle\">{t('status')}</h2>\n <div className=\"semi2-rows\">\n <Row label={t('status')} value={statusText(t, fields.status)} />\n <Row label={t('identity')} value={fields.identity || '—'} />\n <Row label={t('platform')} value={platformText(t, fields.platform)} />\n <Row label={t('consoleUrl')} value={fields.consoleUrl || '—'} />\n <Row label={t('loadedAt')} value={timeText(t, fields.loadedAt)} />\n </div>\n </section>\n {degraded.length > 0 && (\n <section className=\"semi2-section\">\n <h2 className=\"semi2-sectionTitle\">{t('healthTitle')}</h2>\n <div className=\"semi2-rows\">\n {degraded.map((row) => (\n <div className=\"semi2-row\" key={row.key}>\n <span className=\"semi2-rowKey\">{t(row.labelKey)}</span>\n <span className=\"semi2-rowValue\">\n <StateDot state={row.item.state === 'unavailable' ? 'idle' : 'warning'} />\n {row.item.note || row.item.state}\n </span>\n </div>\n ))}\n </div>\n </section>\n )}\n {DOMAIN_SECTIONS.map((section) => {\n const rows = section.overviewRow?.(t, fields) ?? null\n if (rows === null) return null\n return (\n <section className=\"semi2-section\" key={section.id}>\n <h2 className=\"semi2-sectionTitle\">{t(section.labelKey)}</h2>\n <div className=\"semi2-rows\">\n {rows.map((row) => (\n <Row key={row.key} label={row.label} value={row.value} />\n ))}\n </div>\n </section>\n )\n })}\n <DisclosureRow\n className=\"semi2-disclosure\"\n icon={fields.error === '' ? <IconInfoOutline14 /> : <IconWarningOutline16 />}\n title={fields.error === '' ? t('diagnostics') : `${t('diagnostics')}:${fields.error}`}\n open={diagnosticsOpen}\n expandable\n expandOnRowClick\n onToggle={() => setDiagnosticsOpen((open) => !open)}\n >\n <div className=\"semi2-rows\">\n <Row label={t('error')} value={fields.error === '' ? t('none') : errorText(t, fields.error)} />\n <Row label={t('workspaces')} value={fields.workspaces || t('workspaceNone')} muted />\n <Row label={t('projects')} value={fields.projects || t('none')} muted />\n </div>\n </DisclosureRow>\n </>\n )\n}\n\n/**\n * 主列整页:页头(未连接时无操作按钮)+ 「总览」tab + 按已登记工作区动态生成的 tab\n * (登记表增减即增减;只有一个时不渲染 tab 条)。同步按钮按当前 tab 定域:总览 = 全局,工作区 = 只同步该工作区。\n * `renderSlot` 由官方槽位机制注入(页面声明 keyed 子槽 `semi2.workspace`,各 tab 按 key 贡献内容)。\n */\nexport function Semi2Page(props) {\n const { t, controller, renderSlot } = props\n const state = useController(controller)\n const { projected } = state\n const [active, setActive] = useState(OVERVIEW_KEY)\n const tabs = useMemo(\n () => projected.tabs.filter((tab) => tab.title !== ''),\n [projected.tabs],\n )\n const keys = useMemo(() => [OVERVIEW_KEY, ...tabs.map(tabKey)], [tabs])\n useEffect(() => {\n if (!keys.includes(active)) setActive(OVERVIEW_KEY)\n }, [active, keys])\n if (!projected.ready) {\n return (\n <div className=\"semi2-page\">\n <div className=\"semi2-column\">\n <PageHead t={t} />\n <p className=\"semi2-empty\">{t('statusLoading')}</p>\n </div>\n </div>\n )\n }\n const activeTab = tabs.find((tab) => tabKey(tab) === active) ?? null\n const snapshot = controller.getSnapshot()\n const { showLogin } = connectionMode(projected)\n const actionError =\n snapshot.actionError === null ? undefined : actionErrorText(t, snapshot.actionError)\n const syncScope = activeTab === null || activeTab.slug === '' ? 'global' : `workspace:${activeTab.slug}`\n return (\n <div className=\"semi2-page\">\n <div className=\"semi2-column\">\n <PageHead\n t={t}\n hint={!showLogin && !projected.writable ? t('errCREDENTIAL_SOURCE_READONLY') : undefined}\n error={showLogin ? undefined : actionError}\n toolbar={\n showLogin ? undefined : (\n <>\n <Button variant=\"outline\" disabled={!projected.writable} onClick={() => void controller.sync(syncScope)}>\n {syncScope === 'global' ? t('sync') : t('syncWorkspace')}\n </Button>\n <Button\n variant=\"outline\"\n disabled={!projected.writable || snapshot.logoutBusy}\n onClick={() => void controller.logout()}\n >\n {snapshot.logoutBusy ? t('logoutBusy') : t('logout')}\n </Button>\n </>\n )\n }\n />\n {tabs.length > 0 && (\n <nav className=\"semi2-tabs\" aria-label={t('tabMenuLabel')}>\n {keys.map((key, index) => {\n const tab =\n index === 0 ? null : (tabs.find((candidate) => tabKey(candidate) === key) ?? null)\n const selected = key === active\n return (\n <button\n key={key}\n type=\"button\"\n className=\"semi2-tab\"\n data-active={selected ? 'true' : undefined}\n aria-current={selected ? 'page' : undefined}\n onClick={() => setActive(key)}\n >\n <span className=\"semi2-tabLabel\">{tab === null ? t('tabOverview') : tab.title}</span>\n <StateDot state={tabDot(projected.fields, tab)} />\n </button>\n )\n })}\n </nav>\n )}\n {active === OVERVIEW_KEY ? (\n <OverviewTab t={t} projected={projected} controller={controller} actionError={showLogin ? actionError : undefined} />\n ) : renderSlot !== undefined ? (\n renderSlot('semi2.workspace', { view: 'page' }, { entryKey: active })\n ) : (\n <WorkspaceTab t={t} projected={projected} controller={controller} tab={activeTab ?? tabs[0]} />\n )}\n </div>\n </div>\n )\n}\n","// @fa-software/semi2-dsh/client/locales —— 浏览器半边字典(NS=semi2;键与 host 字段一一对应)。\n// 中文为主、英文键兜底;错误码对照表是硬契约(§3.6:绝不再把非凭据错误伪装成 LOGIN_FAILED)。\nexport const NS = 'semi2'\n\nexport const zh = {\n panel: 'Semi2',\n title: 'Semi2',\n intro: 'semi2-hub 配置总览',\n tabOverview: '总览',\n tabMenuLabel: '切换工作区',\n status: '状态',\n statusLocal: '未连接',\n statusLoading: '读取中',\n statusReady: '已连接',\n statusFailed: '失败',\n identity: '身份',\n platform: '运行面',\n surfacecnb: 'CNB',\n surfacecontainer: '容器',\n surfacehost: '宿主直跑',\n consoleUrl: 'hub 地址',\n loadedAt: '最近更新',\n timeNow: '刚刚',\n timeMinutes: '{n}分钟',\n timeHours: '{n}小时',\n timeDays: '{n}天',\n timeMonths: '{n}个月',\n timeYears: '{n}年',\n error: '最近失败',\n healthTitle: '能力健康',\n healthWebLabel: '网页能力',\n healthCodegraphLabel: '代码索引',\n actions: '操作',\n diagnostics: '诊断',\n loginTitle: '登录 semi2-hub',\n loginUrl: '地址',\n loginUsername: '用户名',\n loginPassword: '密码',\n loginSubmit: '登录',\n logout: '登出',\n logoutBusy: '正在登出…',\n loginBusy: '正在登录…',\n sync: '同步',\n syncWorkspace: '只同步该工作区',\n workspaceTitle: '工作区',\n workspaceSlug: 'git slug',\n workspaceProject: '项目',\n workspaceSyncedAt: '同步时间',\n workspaceUnresolved: '未解析(不归 semi2-hub 管)',\n workspaceNone: '没有已登记的工作区',\n domainModels: '模型',\n domainSecrets: '模型密钥',\n domainSkills: '技能',\n domainWorkspace: '工作区',\n domainDefaultModel: '默认模型',\n domainSelfPortrait: '自画像',\n workspaces: '工作区列表',\n projects: '项目绑定',\n model: '默认模型(hub 下发)',\n skills: '控制台技能',\n none: '无',\n errINVALID_CREDENTIALS: '账号或密码不正确',\n errINVALID_CONFIG_URL: 'hub 地址不合法(必须 https,或本机回环 http)',\n errORIGIN_DENIED: '该 hub 不接受这个地址(请用 hub 自己的域名)',\n errCONFIG_REQUEST_FAILED: '连不上 hub(网络、域名解析或证书问题)',\n errCREDENTIAL_SOURCE_READONLY: '地址由部署环境固定,不能在这里修改',\n errCREDENTIAL_STORE_UNAVAILABLE: '本机凭据存储不可用,登录态无法保存',\n errWEB_ROUTE_UNAVAILABLE: '宿主插件没有注册动作接口(版本或装配异常;重启 dsh 或升级插件)',\n errINVALID_INPUT: '输入不完整',\n errMETHOD_NOT_ALLOWED: '请求方法不受支持',\n errLOGIN_FAILED: '登录失败',\n errLOGOUT_FAILED: '登出失败',\n}\n\nexport const en = {\n panel: 'Semi2',\n title: 'Semi2',\n intro: 'semi2-hub configuration',\n tabOverview: 'Overview',\n tabMenuLabel: 'Switch workspace',\n status: 'Status',\n statusLocal: 'Not connected',\n statusLoading: 'Loading',\n statusReady: 'Connected',\n statusFailed: 'Failed',\n identity: 'Identity',\n platform: 'Surface',\n surfacecnb: 'CNB',\n surfacecontainer: 'Container',\n surfacehost: 'Host',\n consoleUrl: 'Hub URL',\n loadedAt: 'Updated',\n timeNow: 'now',\n timeMinutes: '{n}min',\n timeHours: '{n}h',\n timeDays: '{n}d',\n timeMonths: '{n}mo',\n timeYears: '{n}y',\n error: 'Last error',\n healthTitle: 'Capability health',\n healthWebLabel: 'Web surface',\n healthCodegraphLabel: 'Code index',\n actions: 'Actions',\n diagnostics: 'Diagnostics',\n loginTitle: 'Sign in to semi2-hub',\n loginUrl: 'URL',\n loginUsername: 'Username',\n loginPassword: 'Password',\n loginSubmit: 'Sign in',\n logout: 'Sign out',\n logoutBusy: 'Signing out…',\n loginBusy: 'Signing in…',\n sync: 'Sync',\n syncWorkspace: 'Sync this workspace only',\n workspaceTitle: 'Workspace',\n workspaceSlug: 'git slug',\n workspaceProject: 'Project',\n workspaceSyncedAt: 'Synced at',\n workspaceUnresolved: 'Unresolved (not managed by semi2-hub)',\n workspaceNone: 'No registered workspaces',\n domainModels: 'Models',\n domainSecrets: 'Model keys',\n domainSkills: 'Skills',\n domainWorkspace: 'Workspaces',\n domainDefaultModel: 'Default model',\n domainSelfPortrait: 'Self-portrait',\n workspaces: 'Workspaces',\n projects: 'Project bindings',\n model: 'Default model (from hub)',\n skills: 'Console skills',\n none: 'None',\n errINVALID_CREDENTIALS: 'Incorrect username or password',\n errINVALID_CONFIG_URL: 'Invalid hub URL (https required, or loopback http)',\n errORIGIN_DENIED: 'The hub rejects this address (use the hub\\u2019s own domain)',\n errCONFIG_REQUEST_FAILED: 'Cannot reach the hub (network, DNS, or certificate issue)',\n errCREDENTIAL_SOURCE_READONLY: 'The URL is pinned by the deployment environment',\n errCREDENTIAL_STORE_UNAVAILABLE: 'Local credential store unavailable; sign-in cannot persist',\n errWEB_ROUTE_UNAVAILABLE: 'Host plugin did not register the action routes (version or assembly issue; restart dsh or upgrade the plugin)',\n errINVALID_INPUT: 'Incomplete input',\n errMETHOD_NOT_ALLOWED: 'Method not allowed',\n errLOGIN_FAILED: 'Sign-in failed',\n errLOGOUT_FAILED: 'Sign-out failed',\n}\n","// @fa-software/semi2-dsh/client/styles —— 唯一的自绘样式模块(页面骨架 + tab 条 + 行)。\n// 控件本体全部来自官方原子包(样式随组件自带);版面值照官方主列页(plugin-manager 的 page/tabs/row),\n// 文字层级一律用 --dsw-alias-label-* 语义色,不拿 opacity 压暗。\nconst STYLE_ID = 'semi2-dsh-client-styles'\n\nconst CSS = `\n.semi2-page {\n box-sizing: border-box;\n height: 100%;\n overflow: auto;\n display: flex;\n justify-content: center;\n align-items: flex-start;\n padding: 28px clamp(24px, 4vw, 48px) 48px;\n color: var(--dsw-alias-label-primary);\n}\n.semi2-column { display: flex; flex-direction: column; gap: 32px; width: 100%; max-width: 960px; }\n.semi2-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }\n.semi2-headText { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n.semi2-title { margin: 0; font-size: 20px; font-weight: 500; line-height: 28px; }\n.semi2-intro { margin: 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n.semi2-toolbar { display: flex; align-items: center; gap: 8px; flex: none; }\n.semi2-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 420px;\n padding: 16px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n}\n.semi2-cardTitle { margin: 0; font-size: 14px; font-weight: 500; line-height: 20px; }\n.semi2-tabs {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-end;\n gap: 22px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n.semi2-tab {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n max-width: 240px;\n padding: 7px 1px 9px;\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-tertiary);\n background: none;\n border: 0;\n cursor: pointer;\n}\n.semi2-tab:hover, .semi2-tab[data-active='true'] { color: var(--dsw-alias-label-primary); }\n.semi2-tab[data-active='true']::after {\n content: '';\n position: absolute;\n inset: auto 0 -1px;\n height: 2px;\n background: var(--dsw-alias-label-primary);\n}\n.semi2-tabLabel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.semi2-section { display: flex; flex-direction: column; gap: 4px; }\n.semi2-section > .semi2-section { margin-top: 12px; }\n.semi2-sectionTitle { margin: 0; font-size: 14px; font-weight: 500; line-height: 20px; }\n.semi2-rows { display: flex; flex-direction: column; }\n.semi2-row {\n display: flex;\n gap: 16px;\n align-items: baseline;\n padding: 12px 2px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n.semi2-rowKey { flex: none; min-width: 120px; color: var(--dsw-alias-label-tertiary); }\n.semi2-rowValue { display: inline-flex; align-items: center; gap: 6px; min-width: 0; margin: 0; overflow-wrap: anywhere; }\n.semi2-empty { margin: 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n.semi2-form { display: flex; flex-direction: column; gap: 8px; }\n.semi2-formActions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }\n.semi2-hint { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.semi2-error { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-error, var(--dsw-alias-state-error-primary)); }\n.semi2-muted { color: var(--dsw-alias-label-tertiary); }\n.semi2-disclosure { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n`\n\n/** 幂等注入一次性 <style>(令牌缺位的极端情况由兜底值兜住)。 */\nexport function injectStyles() {\n if (typeof document === 'undefined') return\n if (document.getElementById(STYLE_ID) !== null) return\n const element = document.createElement('style')\n element.id = STYLE_ID\n element.textContent = CSS\n document.head.append(element)\n}\n","// @fa-software/semi2-dsh/client —— 浏览器半边:侧栏一级入口(与「插件」同级)+ 主列整页。\n// 门控照官方:宿主没服务 `semi2` 设置命名空间时,导航行与主列页**同时撤销**(不留坏入口)。\n// 传输走官方 settings 命名空间 `semi2`(host 侧插件注册);动作走 /semi2/* 自建路由(官方请求校验面后)。\nimport { Semi2Controller } from './controller.js'\nimport { Semi2Page, Semi2PanelIcon } from './page.jsx'\nimport { WorkspaceTab } from './workspace-tab.jsx'\nimport { NS, zh, en } from './locales.js'\nimport { injectStyles } from './styles.js'\n\nexport const PANEL_ID = 'semi2'\n\nexport const inject = ['slots', 'settingsScope', 'locale']\n\nexport function apply(ctx) {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'semi2: dictionaries')\n const t = ctx.locale.bind(NS)\n injectStyles()\n const controller = new Semi2Controller(ctx)\n ctx.effect(() => () => controller.dispose(), 'semi2: controller')\n\n // 工作区 tab 的 keyed 子槽条目:登记表增减即增减(每个 tab 按 key 贡献一份内容)。\n const workspaceEntries = new Map()\n const syncWorkspaceEntries = () => {\n const { tabs } = controller.getSnapshot().projected\n const wanted = new Set(\n tabs.filter((tab) => tab.title !== '').map((tab) => (tab.slug === '' ? `title:${tab.title}` : `workspace:${tab.slug}`)),\n )\n for (const [key, dispose] of workspaceEntries) {\n if (wanted.has(key)) continue\n dispose()\n workspaceEntries.delete(key)\n }\n for (const key of wanted) {\n if (workspaceEntries.has(key)) continue\n const tab = tabs.find((candidate) =>\n candidate.slug === '' ? `title:${candidate.title}` === key : `workspace:${candidate.slug}` === key,\n )\n if (tab === undefined) continue\n const dispose = ctx.slots.inject('semi2.workspace', () =>\n ctx.slots.register(\n {\n name: 'semi2.workspace',\n key,\n locale: NS,\n inject: () => ({ controller, tab }),\n },\n WorkspaceTab,\n ),\n )\n workspaceEntries.set(key, dispose)\n }\n }\n\n const describeFace = ctx.settingsScope.describe()\n ctx.effect(() => {\n const registered = new Map()\n const sync = () => {\n const served = new Set(\n describeFace.getSnapshot().view?.namespaces.map((view) => view.ns) ?? [],\n )\n const available = served.has(NS)\n const off = registered.get('panel')\n if (available && off === undefined) {\n syncWorkspaceEntries()\n const unsubscribe = controller.subscribe(syncWorkspaceEntries)\n registered.set('tabs', unsubscribe)\n registered.set(\n 'panel',\n ctx.slots.inject('main', () =>\n ctx.slots.register(\n {\n name: 'main',\n key: PANEL_ID,\n locale: NS,\n children: { 'semi2.workspace': { kind: 'keyed', scope: 'root' } },\n inject: () => ({ controller }),\n },\n Semi2Page,\n ),\n ),\n )\n registered.set(\n 'sidebar',\n ctx.slots.inject('sidebar.panellist', () =>\n ctx.slots.register(\n {\n name: 'sidebar.panellist',\n id: PANEL_ID,\n order: 10,\n label: () => t('panel'),\n locale: NS,\n },\n Semi2PanelIcon,\n ),\n ),\n )\n } else if (!available && off !== undefined) {\n for (const dispose of registered.values()) dispose()\n registered.clear()\n // 工作区 keyed 子槽随面板一起撤:注册表清空而子槽留着的话,重新上架时旧条目再也不会被回收。\n for (const dispose of workspaceEntries.values()) dispose()\n workspaceEntries.clear()\n }\n }\n const unsubscribe = describeFace.subscribe(sync)\n describeFace.ensure()\n sync()\n return () => {\n unsubscribe()\n for (const dispose of registered.values()) dispose()\n for (const dispose of workspaceEntries.values()) dispose()\n workspaceEntries.clear()\n registered.clear()\n }\n }, 'semi2: sidebar entry + main page')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["relativeTime","useState","useMemo","Row","IconLinkOutlineRegular","useState","Input","Button","StateDot","DisclosureRow","IconInfoOutlineRegular","IconWarningOutlineRegular","useMemo"],"sources":["../src/contract.ts","../src/client/controller.js","../src/client/domains.js","../src/client/workspace-tab.jsx","../src/client/page.jsx","../src/client/locales.js","../src/client/styles.js","../src/client/index.jsx"],"sourcesContent":["// @fa-software/semi2-dsh/contract —— 运行面契约(本包定义,三个运行面各自 provide)。\n// 适配器在 apply 里同步 provide(插件在首次领取前等它,见 runtime.ts),服务缺席 = 宿主直跑;headless/web 轴由 dsh 服务存在性决定,提示词段由适配器注入。\n\n// import 本模块才能形成模块增强(否则上面的 interface 会遮蔽 Context)。\nimport type {} from '@deepseek-ai/cordis'\n\n/**\n * semi2 提示词段的号段分配(偏移量,基准 = 官方 persona 段)。\n * 三段都落在官方人设区(persona + 1..3),不与任何官方工具 schema 号段重叠;\n * 段名与绝对位置由 `semi2SectionOrder` 现算,官方占用 1..3 时改这里并同步守卫。\n */\nexport const SEMI2_SECTION_ORDERS = {\n selfPortrait: 1,\n npcContract: 2,\n cnbWorkstation: 3,\n} as const\n\nexport type Semi2SectionKey = keyof typeof SEMI2_SECTION_ORDERS\n\n/**\n * 插件自身设置段的条目 id:dsh 的设置命名空间就是 Profile 插件条目 id(bundle patch 里那一行的 id),\n * 状态 / 健康 / 归属表 / 工作区映射都写在这一段里。host 与浏览器半边共用这一个常量\n * (`cordis.patch.yml` 的插件行 id 必须与它一致,`test/dsh/unit/profile-patch.test.mjs` 对账)。\n */\nexport const SEMI2_SETTINGS_ENTRY = 'semi2-dsh'\n\n/** 官方人设前缀段名(号段基准);服务不认这个名字时按 0 兜底。 */\nconst PERSONA_PREFIX_ORDER_NAME = 'DEPLOYMENT_PERSONA_PREFIX'\n\n/** 只读 systemPrompt 的号段解析面:老宿主没有 `getSectionOrder` 时回落本表偏移。 */\nexport interface SectionOrderSource {\n getSectionOrder?(name: string): number | undefined\n}\n\n/** 段的绝对位置 = 官方 persona 段号 + 本表偏移(服务缺席 / 不认名字时以偏移值兜底)。 */\nexport function semi2SectionOrder(\n systemPrompt: SectionOrderSource | undefined,\n key: Semi2SectionKey,\n): number {\n const persona = systemPrompt?.getSectionOrder?.(PERSONA_PREFIX_ORDER_NAME)\n const base =\n typeof persona === 'number' && Number.isFinite(persona) ? persona : 0\n return base + SEMI2_SECTION_ORDERS[key]\n}\n\n/** 连接 semi2-hub 的凭据;两项齐备才算可连。 */\nexport interface Semi2Credentials {\n configUrl?: string\n accessToken?: string\n}\n\n/** 运行面平台:适配器声明的事实;宿主直跑(无契约)由插件判为 `host`。 */\nexport type Semi2Platform = 'cnb' | 'container'\n\n/** 运行面标识:hub 的审查日志按它区分来源面(`host` = 无适配器的宿主直跑)。 */\nexport type Semi2Face = 'npc' | 'workstation' | 'container-web' | 'host'\n\nexport interface Semi2Runtime {\n /** 由 runtimeFrom*Env 工厂盖章(适配器不自己填)。 */\n platform: Semi2Platform\n /** 同上:本面是哪个运行面,hub 审查日志的来源面。 */\n face: Semi2Face\n /** semi2-hub 连接凭据;缺省 = 回落 dsh credentials 登录存储。 */\n credentials?: Semi2Credentials\n /**\n * 本次运行的稳定引用(NPC 面 = `<仓库>#<issue|pr>#<号>`),由适配器解析触发后填。\n * 客户端的会话日志按它把「起手 → 交付 → 会话 → 核对」并成一条:会话尚未创建的事件也带得上。\n */\n taskRef?: string\n}\n\n/** cordis 服务名(适配器 provide / 插件 get 共用同一常量)。 */\nexport const SEMI2_RUNTIME_SERVICE = 'semi2Runtime'\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n semi2Runtime: Semi2Runtime\n }\n}\n\nfunction text(value: string | undefined): string | undefined {\n const trimmed = value?.trim()\n return trimmed === undefined || trimmed === '' ? undefined : trimmed\n}\n\nfunction credentialsFromEnv(\n env: NodeJS.ProcessEnv,\n): Semi2Credentials | undefined {\n const configUrl = text(env.SEMI2_CONFIG_URL)\n // Hub 签发的 CNB 接入密钥(经 secret import 注入 SEMI2_ACCESS_TOKEN)优先:它由 Hub 自己校验,\n // 直接作为 Bearer 使用。缺失时才回退平台短期 CNB_TOKEN(换用户密钥)。\n const accessToken =\n text(env.SEMI2_ACCESS_TOKEN) === undefined ? text(env.CNB_TOKEN) : undefined\n return configUrl === undefined && accessToken === undefined\n ? undefined\n : {\n ...(configUrl === undefined ? {} : { configUrl }),\n ...(accessToken === undefined ? {} : { accessToken }),\n }\n}\n\n/** 按需字段:显式 undefined 与缺席等价(exactOptionalPropertyTypes)。 */\ninterface Semi2RuntimeFields {\n credentials?: Semi2Credentials | undefined\n}\n\nfunction runtime(\n platform: Semi2Platform,\n face: Semi2Face,\n fields: Semi2RuntimeFields,\n): Semi2Runtime {\n const contract: Semi2Runtime = { platform, face }\n if (fields.credentials !== undefined) contract.credentials = fields.credentials\n return contract\n}\n\n/**\n * CNB 运行面:优先用 secret import 注入的 hub 接入密钥(`SEMI2_ACCESS_TOKEN`),\n * 缺失时才回退平台短期 `CNB_TOKEN`(插件启动时换成 hub 用户密钥)。\n * face 由调用它的适配器给(NPC 面与云开发工作站面共用这条 env 通道)。\n */\nexport function runtimeFromCnbEnv(\n env: NodeJS.ProcessEnv,\n face: 'npc' | 'workstation',\n): Semi2Runtime {\n return runtime('cnb', face, { credentials: credentialsFromEnv(env) })\n}\n\n/**\n * 容器运行面:**只盖章,不给凭据也不给身份**——本地容器靠登录(设置页账号密码换用户密钥)。\n * 契约一旦提供 `credentials`,插件的 `login()` 会以 `CREDENTIAL_SOURCE_READONLY` 拒绝登录\n * (部署面地址不可被交互改写),所以这里刻意留空。\n * CNB 面相反:身份取平台注入的触发 env、凭据取 secret 注入的 env,见 `runtimeFromCnbEnv`。\n */\nexport function runtimeFromContainerEnv(_env: NodeJS.ProcessEnv): Semi2Runtime {\n return runtime('container', 'container-web', {})\n}\n","// @fa-software/semi2-dsh/client/controller —— Semi2 控制器:设置段镜像 + 动作(登录/登出/同步)。\n// 交互语义照官方:输入只在提交时发出;写入失败保留草稿并报错;离开页面丢弃草稿。\n// 状态经官方设置表单读(`configForms.get(条目 id)`),同步与登录一样走 /semi2/* 自建路由。\nimport { useEffect, useMemo, useState } from 'react'\nimport { relativeTime } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { SEMI2_SETTINGS_ENTRY } from '../contract.js'\n\nexport const OVERVIEW_KEY = 'overview'\n\nconst STATUS_KEYS = new Set(['local', 'loading', 'ready', 'failed'])\n\n/** 状态字段由 host 侧 STATUS_FIELDS + 健康字段定义:全为扁平标量字符串。 */\nfunction projectSnapshot(snapshot) {\n const value = snapshot?.value\n if (value === undefined || typeof value.status !== 'string' || !STATUS_KEYS.has(value.status)) {\n return { ready: false, fields: {}, tabs: [], writable: false, revision: undefined }\n }\n const tabs = Array.isArray(value.workspaceTabs) ? value.workspaceTabs : []\n return {\n ready: true,\n fields: value,\n tabs,\n writable: snapshot.writable === true,\n revision: snapshot.revision,\n }\n}\n\n/** 运行面原值(数据层只存 cnb / container / host)→ 展示标签(本地化)。 */\nexport function platformText(t, platform) {\n if (platform === '' || platform === undefined) return '—'\n return t(`surface${platform}`) || platform\n}\n\nexport function statusText(t, status) {\n return (\n { local: t('statusLocal'), loading: t('statusLoading'), ready: t('statusReady'), failed: t('statusFailed') }[status] ??\n status\n )\n}\n\n/** 时间分桶(官方 relativeTime)→ 本字典措辞;解析不了的时间戳原样返回。 */\nfunction timeUnitKey(unit) {\n switch (unit) {\n case 'minutes':\n return 'timeMinutes'\n case 'hours':\n return 'timeHours'\n case 'days':\n return 'timeDays'\n case 'months':\n return 'timeMonths'\n case 'years':\n return 'timeYears'\n default:\n return null\n }\n}\n\nexport function timeText(t, value) {\n if (value === undefined || value === '') return '—'\n const at = Date.parse(value)\n if (Number.isNaN(at)) return value\n const { unit, n } = relativeTime(at, Date.now())\n const key = timeUnitKey(unit)\n return key === null ? t('timeNow') : t(key, { n })\n}\n\n/** 错误码 → 一句人话(表驱动;查不到原样显示码,非 JSON 应答由调用方落 HTTP 码)。 */\nexport function errorText(t, code) {\n return t(`err${code}`) || code\n}\n\n/**\n * 一次动作接口调用的统一出口:非 JSON 应答 → `HTTP <status>`;404/405 → WEB_ROUTE_UNAVAILABLE;\n * JSON 体带 code → 该码。绝不把非凭据错误伪装成 LOGIN_FAILED。\n */\nasync function callRoute(path, body) {\n let response\n try {\n response = await fetch(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body ?? {}),\n })\n } catch (error) {\n return { ok: false, code: 'CONFIG_REQUEST_FAILED' }\n }\n const text = await response.text()\n let parsed = null\n try {\n parsed = JSON.parse(text)\n } catch {\n parsed = null\n }\n if (parsed === null || typeof parsed !== 'object') {\n if (response.status === 404 || response.status === 405)\n return { ok: false, code: 'WEB_ROUTE_UNAVAILABLE' }\n return { ok: false, code: `HTTP ${String(response.status)}` }\n }\n const code = typeof parsed.code === 'string' ? parsed.code : ''\n if (!response.ok || parsed.ok !== true) return { ok: false, code: code || 'LOGIN_FAILED' }\n return { ok: true, code, body: parsed }\n}\n\nexport class Semi2Controller {\n constructor(ctx) {\n this.ctx = ctx\n this.scope = ctx.configForms.get(SEMI2_SETTINGS_ENTRY)\n this.listeners = new Set()\n this.snapshot = this.scope.getSnapshot()\n this.unsubscribe = this.scope.subscribe(() => {\n this.snapshot = this.scope.getSnapshot()\n for (const listener of this.listeners) listener()\n })\n this.loginBusy = false\n this.logoutBusy = false\n this.actionError = null\n }\n\n dispose() {\n this.unsubscribe()\n this.listeners.clear()\n }\n\n subscribe(listener) {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot() {\n return {\n projected: projectSnapshot(this.snapshot),\n loginBusy: this.loginBusy,\n logoutBusy: this.logoutBusy,\n actionError: this.actionError,\n }\n }\n\n notify() {\n for (const listener of this.listeners) listener()\n }\n\n /** 登录:草稿只在提交时发出;成功清空密码,失败保留草稿并报错。 */\n async login(draft) {\n if (this.loginBusy) return\n this.loginBusy = true\n this.actionError = null\n this.notify()\n const outcome = await callRoute('/semi2/login', draft)\n this.loginBusy = false\n if (!outcome.ok) this.actionError = outcome.code\n this.notify()\n return outcome\n }\n\n async logout() {\n if (this.logoutBusy) return\n this.logoutBusy = true\n this.actionError = null\n this.notify()\n const outcome = await callRoute('/semi2/logout', {})\n this.logoutBusy = false\n if (!outcome.ok) this.actionError = outcome.code\n this.notify()\n return outcome\n }\n\n /**\n * 同步:POST 到自建路由(与登录 / 登出同一条通道),host 侧据此重载。\n * value 带范围:`global`(默认)或 `workspace:<slug>`(只同步该工作区)。\n */\n async sync(value = 'global') {\n if (!this.getSnapshot().projected.writable) return\n const outcome = await callRoute('/semi2/sync', { scope: value })\n if (!outcome.ok) {\n this.actionError = outcome.code\n this.notify()\n }\n }\n}\n\n/** useSyncExternalStore 适配(控制器快照是稳定引用,动作后手动 bump)。 */\nexport function useController(controller) {\n const [version, setVersion] = useState(0)\n useEffect(() => controller.subscribe(() => setVersion((n) => n + 1)), [controller])\n return useMemo(() => ({ ...controller.getSnapshot(), version }), [controller, version])\n}\n","// @fa-software/semi2-dsh/client/domains —— 领域行渲染(与 host 注册表对账:五者一致契约测试钉住)。\n// 每个领域一个条目:总览 tab 的领域行 + 工作区 tab 的领域切片;页面骨架只按这张表渲染。\nimport { timeText } from './controller.js'\n\nexport const DOMAIN_SECTIONS = [\n {\n id: 'models',\n labelKey: 'domainModels',\n /** 总览行:默认模型(hub 下发的全局默认)。 */\n overviewRow: (t, fields) => [\n { key: 'model', label: t('model'), value: fields.model || t('none') },\n ],\n },\n {\n id: 'secrets',\n labelKey: 'domainSecrets',\n overviewRow: null,\n },\n {\n id: 'skills',\n labelKey: 'domainSkills',\n /** 总览行:控制台技能条数(空串 = 没拿到权威目录)。 */\n overviewRow: (t, fields) => [\n { key: 'skills', label: t('skills'), value: fields.skills === '' ? '—' : fields.skills },\n ],\n },\n {\n id: 'workspace',\n labelKey: 'domainWorkspace',\n /** 总览行:工作区与项目绑定。 */\n overviewRow: (t, fields) => [\n { key: 'workspaceCount', label: t('workspaceTitle'), value: fields.workspaceCount },\n { key: 'projectCount', label: t('projects'), value: fields.projectCount },\n ],\n /** 工作区 tab 切片:项目绑定(只显示该工作区自己的解析结果)。 */\n workspaceRow: (t, tab) => [\n { key: 'slug', label: t('workspaceSlug'), value: tab.slug || '—' },\n {\n key: 'project',\n label: t('workspaceProject'),\n value: tab.project || tab.projectId || '—',\n },\n { key: 'syncedAt', label: t('workspaceSyncedAt'), value: timeText(t, tab.syncedAt) },\n ],\n },\n {\n id: 'default-model',\n labelKey: 'domainDefaultModel',\n overviewRow: null,\n },\n {\n id: 'self-portrait',\n labelKey: 'domainSelfPortrait',\n /** 总览行:注入状态(未配置 / 读取失败 / 已注入 · N 字)。 */\n overviewRow: (t, fields) => [\n {\n key: 'selfPortrait',\n label: t('domainSelfPortrait'),\n value: fields.selfPortrait || t('none'),\n },\n ],\n },\n {\n id: 'redmine',\n labelKey: 'domainRedmine',\n /** 总览行:hub 下发的 Redmine 地址 + 本人密钥是否齐备(未配置 / 读取失败 / 已启用)。 */\n overviewRow: (t, fields) => [\n { key: 'redmine', label: t('domainRedmine'), value: fields.redmine || t('none') },\n ],\n },\n]\n\n/** 健康项解码(host 写的是 `state:text` 编码串;解析失败按未知处理)。 */\nexport function decodeHealth(raw) {\n if (typeof raw !== 'string' || raw === '') return null\n const separator = raw.indexOf(':')\n if (separator === -1) return { state: raw, note: '' }\n return { state: raw.slice(0, separator), note: raw.slice(separator + 1) }\n}\n\n/** 健康行(key = host 命名空间字段;labelKey 自己带,不挂在领域上)。 */\nexport const HEALTH_ROWS = [\n { key: 'healthWeb', labelKey: 'healthWebLabel' },\n { key: 'healthCodegraph', labelKey: 'healthCodegraphLabel' },\n { key: 'health:models', labelKey: 'domainModels' },\n { key: 'health:secrets', labelKey: 'domainSecrets' },\n { key: 'health:skills', labelKey: 'domainSkills' },\n { key: 'health:workspace', labelKey: 'domainWorkspace' },\n { key: 'health:default-model', labelKey: 'domainDefaultModel' },\n { key: 'health:self-portrait', labelKey: 'domainSelfPortrait' },\n { key: 'health:redmine', labelKey: 'domainRedmine' },\n]\n","// @fa-software/semi2-dsh/client/workspace-tab —— 单个工作区 tab 内容(只读该工作区的数据桶)。\n// 该工作区自己的解析结果与「最近更新时间」;不混其它工作区的数据。\n// 只出内容段:页面容器(padding / 页头 / tab 条 / 滚动)与操作按钮归 Semi2Page。\nimport { useEffect } from 'react'\nimport { DOMAIN_SECTIONS } from './domains.js'\nimport { useController, timeText } from './controller.js'\n\nfunction Row({ label, value }) {\n return (\n <div className=\"semi2-row\">\n <span className=\"semi2-rowKey\">{label}</span>\n <span className=\"semi2-rowValue\">{value}</span>\n </div>\n )\n}\n\nexport function WorkspaceTab({ t, controller, tab }) {\n const state = useController(controller)\n const { fields } = state.projected\n // 该工作区 tab 打开即请求一次按需刷新(host 侧按 slug 点名取,不拉全量表)。\n useEffect(() => {\n if (tab.slug !== '') void controller.sync(`workspace:${tab.slug}`)\n }, [tab.slug])\n return (\n <>\n <section className=\"semi2-section\">\n <h2 className=\"semi2-sectionTitle\">{tab.title}</h2>\n {DOMAIN_SECTIONS.map((section) => {\n const rows = section.workspaceRow?.(t, tab) ?? null\n if (rows === null) return null\n return (\n <section className=\"semi2-section\" key={section.id}>\n <h3 className=\"semi2-sectionTitle\">{t(section.labelKey)}</h3>\n <div className=\"semi2-rows\">\n {rows.map((row) => (\n <Row key={row.key} label={row.label} value={row.value} />\n ))}\n </div>\n </section>\n )\n })}\n {tab.projectId === '' && <p className=\"semi2-error\">{t('workspaceUnresolved')}</p>}\n </section>\n <p className=\"semi2-hint\">{`${t('loadedAt')}:${timeText(t, fields.loadedAt)}`}</p>\n </>\n )\n}\n","// @fa-software/semi2-dsh/client/page —— 主列整页(页头 + tab 条 + 总览/工作区内容)与侧栏图标。\n// 版面照官方主列页:页面容器自带 padding / 居中 / 960 上限,页头 h1+intro 且右侧放操作按钮,\n// tab 为下划线形态且只有一个时不渲染;未连接态只有一张登录卡片。\n// 控件全部来自官方原子包(Button/Input/StateDot/DisclosureRow/图标),样式走 styles.js。\nimport { useEffect, useMemo, useState } from 'react'\nimport { Button, Input, StateDot, DisclosureRow } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { IconInfoOutlineRegular, IconLinkOutlineRegular, IconWarningOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { DOMAIN_SECTIONS, HEALTH_ROWS, decodeHealth } from './domains.js'\nimport { WorkspaceTab } from './workspace-tab.jsx'\nimport {\n OVERVIEW_KEY,\n errorText,\n platformText,\n statusText,\n timeText,\n useController,\n} from './controller.js'\n\n/** 侧栏导航行图标(官方写法:function PanelIcon({ size }))。 */\nexport function Semi2PanelIcon({ size }) {\n return <IconLinkOutlineRegular size={size} />\n}\n\n/** tab 键:slug 暂未解析出来的工作区退回标题占位。 */\nfunction tabKey(tab) {\n return tab.slug === '' ? `title:${tab.title}` : `workspace:${tab.slug}`\n}\n\n/** 连接面:`showLogin` 为真时整页只剩登录卡片,页头不给操作按钮。 */\nfunction connectionMode(projected) {\n const connected = projected.fields.status === 'ready' || projected.fields.status === 'failed'\n return { connected, showLogin: projected.fields.credentialSource === '' || !connected }\n}\n\n/** 动作失败码 → 一句人话(非 JSON 应答已是 HTTP 码,原样显示)。 */\nfunction actionErrorText(t, code) {\n return code.startsWith('HTTP') ? code : errorText(t, code)\n}\n\nfunction Row({ label, value, muted }) {\n return (\n <div className=\"semi2-row\">\n <span className=\"semi2-rowKey\">{label}</span>\n <span className={muted === true ? 'semi2-rowValue semi2-muted' : 'semi2-rowValue'}>{value}</span>\n </div>\n )\n}\n\n/** 页头:左列标题/说明/告示,右侧 `toolbar` 子节点放当前面的操作按钮(没有就不渲染工具条)。 */\nfunction PageHead({ t, hint, error, toolbar }) {\n return (\n <header className=\"semi2-head\">\n <div className=\"semi2-headText\">\n <h1 className=\"semi2-title\">{t('title')}</h1>\n <p className=\"semi2-intro\">{t('intro')}</p>\n {hint !== undefined && <p className=\"semi2-hint\">{hint}</p>}\n {error !== undefined && <p className=\"semi2-error\">{error}</p>}\n </div>\n {toolbar !== undefined && <div className=\"semi2-toolbar\">{toolbar}</div>}\n </header>\n )\n}\n\nconst DOT_OF_STATUS = { local: 'idle', loading: 'ongoing', ready: 'done', failed: 'error' }\n\nfunction tabDot(fields, tab) {\n if (fields.status === 'failed') return 'error'\n if (tab === null) return DOT_OF_STATUS[fields.status] ?? 'idle'\n return tab.projectId !== '' ? 'done' : 'idle'\n}\n\n/** 登录卡片:草稿只在提交时发出;未连接时整页只有它。 */\nfunction LoginCard({ t, projected, controller, actionError }) {\n const { fields, writable } = projected\n const [draft, setDraft] = useState(() => ({\n url: fields.consoleUrl ?? '',\n username: '',\n password: '',\n }))\n const snapshot = controller.getSnapshot()\n return (\n <section className=\"semi2-card\">\n <h2 className=\"semi2-cardTitle\">{t('loginTitle')}</h2>\n <form\n className=\"semi2-form\"\n onSubmit={(event) => {\n event.preventDefault()\n void controller.login(draft)\n }}\n >\n <Input\n aria-label={t('loginUrl')}\n placeholder={t('loginUrl')}\n value={draft.url}\n readOnly={!writable}\n onChange={(event) => setDraft((prev) => ({ ...prev, url: event.target.value }))}\n />\n <Input\n aria-label={t('loginUsername')}\n placeholder={t('loginUsername')}\n value={draft.username}\n onChange={(event) => setDraft((prev) => ({ ...prev, username: event.target.value }))}\n />\n <Input\n aria-label={t('loginPassword')}\n placeholder={t('loginPassword')}\n type=\"password\"\n value={draft.password}\n onChange={(event) => setDraft((prev) => ({ ...prev, password: event.target.value }))}\n />\n <div className=\"semi2-formActions\">\n <Button type=\"submit\" variant=\"primary\" disabled={snapshot.loginBusy}>\n {snapshot.loginBusy ? t('loginBusy') : t('loginSubmit')}\n </Button>\n </div>\n </form>\n {!writable && <p className=\"semi2-hint\">{t('errCREDENTIAL_SOURCE_READONLY')}</p>}\n {actionError !== undefined && <p className=\"semi2-error\">{actionError}</p>}\n </section>\n )\n}\n\nfunction OverviewTab({ t, projected, controller, actionError }) {\n const { fields } = projected\n const [diagnosticsOpen, setDiagnosticsOpen] = useState(false)\n const { showLogin } = connectionMode(projected)\n if (showLogin) return <LoginCard t={t} projected={projected} controller={controller} actionError={actionError} />\n const healthRows = HEALTH_ROWS.map((row) => ({\n ...row,\n item: decodeHealth(fields[row.key]),\n })).filter((row) => row.item !== null)\n const degraded = healthRows.filter((row) => row.item.state !== 'ok')\n return (\n <>\n <section className=\"semi2-section\">\n <h2 className=\"semi2-sectionTitle\">{t('status')}</h2>\n <div className=\"semi2-rows\">\n <Row label={t('status')} value={statusText(t, fields.status)} />\n <Row label={t('identity')} value={fields.identity || '—'} />\n <Row label={t('platform')} value={platformText(t, fields.platform)} />\n <Row label={t('consoleUrl')} value={fields.consoleUrl || '—'} />\n <Row label={t('loadedAt')} value={timeText(t, fields.loadedAt)} />\n </div>\n </section>\n {degraded.length > 0 && (\n <section className=\"semi2-section\">\n <h2 className=\"semi2-sectionTitle\">{t('healthTitle')}</h2>\n <div className=\"semi2-rows\">\n {degraded.map((row) => (\n <div className=\"semi2-row\" key={row.key}>\n <span className=\"semi2-rowKey\">{t(row.labelKey)}</span>\n <span className=\"semi2-rowValue\">\n <StateDot state={row.item.state === 'unavailable' ? 'idle' : 'warning'} />\n {row.item.note || row.item.state}\n </span>\n </div>\n ))}\n </div>\n </section>\n )}\n {DOMAIN_SECTIONS.map((section) => {\n const rows = section.overviewRow?.(t, fields) ?? null\n if (rows === null) return null\n return (\n <section className=\"semi2-section\" key={section.id}>\n <h2 className=\"semi2-sectionTitle\">{t(section.labelKey)}</h2>\n <div className=\"semi2-rows\">\n {rows.map((row) => (\n <Row key={row.key} label={row.label} value={row.value} />\n ))}\n </div>\n </section>\n )\n })}\n <DisclosureRow\n className=\"semi2-disclosure\"\n icon={fields.error === '' ? <IconInfoOutlineRegular /> : <IconWarningOutlineRegular />}\n title={fields.error === '' ? t('diagnostics') : `${t('diagnostics')}:${fields.error}`}\n open={diagnosticsOpen}\n expandable\n expandOnRowClick\n onToggle={() => setDiagnosticsOpen((open) => !open)}\n >\n <div className=\"semi2-rows\">\n <Row label={t('error')} value={fields.error === '' ? t('none') : errorText(t, fields.error)} />\n <Row label={t('workspaces')} value={fields.workspaces || t('workspaceNone')} muted />\n <Row label={t('projects')} value={fields.projects || t('none')} muted />\n </div>\n </DisclosureRow>\n </>\n )\n}\n\n/**\n * 主列整页:页头(未连接时无操作按钮)+ 「总览」tab + 按已登记工作区动态生成的 tab\n * (登记表增减即增减;只有一个时不渲染 tab 条)。同步按钮按当前 tab 定域:总览 = 全局,工作区 = 只同步该工作区。\n * `renderSlot` 由官方槽位机制注入(页面声明 keyed 子槽 `semi2.workspace`,各 tab 按 key 贡献内容)。\n */\nexport function Semi2Page(props) {\n const { t, controller, renderSlot } = props\n const state = useController(controller)\n const { projected } = state\n const [active, setActive] = useState(OVERVIEW_KEY)\n const tabs = useMemo(\n () => projected.tabs.filter((tab) => tab.title !== ''),\n [projected.tabs],\n )\n const keys = useMemo(() => [OVERVIEW_KEY, ...tabs.map(tabKey)], [tabs])\n useEffect(() => {\n if (!keys.includes(active)) setActive(OVERVIEW_KEY)\n }, [active, keys])\n if (!projected.ready) {\n return (\n <div className=\"semi2-page\">\n <div className=\"semi2-column\">\n <PageHead t={t} />\n <p className=\"semi2-empty\">{t('statusLoading')}</p>\n </div>\n </div>\n )\n }\n const activeTab = tabs.find((tab) => tabKey(tab) === active) ?? null\n const snapshot = controller.getSnapshot()\n const { showLogin } = connectionMode(projected)\n const actionError =\n snapshot.actionError === null ? undefined : actionErrorText(t, snapshot.actionError)\n const syncScope = activeTab === null || activeTab.slug === '' ? 'global' : `workspace:${activeTab.slug}`\n return (\n <div className=\"semi2-page\">\n <div className=\"semi2-column\">\n <PageHead\n t={t}\n hint={!showLogin && !projected.writable ? t('errCREDENTIAL_SOURCE_READONLY') : undefined}\n error={showLogin ? undefined : actionError}\n toolbar={\n showLogin ? undefined : (\n <>\n <Button variant=\"outline\" disabled={!projected.writable} onClick={() => void controller.sync(syncScope)}>\n {syncScope === 'global' ? t('sync') : t('syncWorkspace')}\n </Button>\n <Button\n variant=\"outline\"\n disabled={!projected.writable || snapshot.logoutBusy}\n onClick={() => void controller.logout()}\n >\n {snapshot.logoutBusy ? t('logoutBusy') : t('logout')}\n </Button>\n </>\n )\n }\n />\n {tabs.length > 0 && (\n <nav className=\"semi2-tabs\" aria-label={t('tabMenuLabel')}>\n {keys.map((key, index) => {\n const tab =\n index === 0 ? null : (tabs.find((candidate) => tabKey(candidate) === key) ?? null)\n const selected = key === active\n return (\n <button\n key={key}\n type=\"button\"\n className=\"semi2-tab\"\n data-active={selected ? 'true' : undefined}\n aria-current={selected ? 'page' : undefined}\n onClick={() => setActive(key)}\n >\n <span className=\"semi2-tabLabel\">{tab === null ? t('tabOverview') : tab.title}</span>\n <StateDot state={tabDot(projected.fields, tab)} />\n </button>\n )\n })}\n </nav>\n )}\n {active === OVERVIEW_KEY ? (\n <OverviewTab t={t} projected={projected} controller={controller} actionError={showLogin ? actionError : undefined} />\n ) : renderSlot !== undefined ? (\n renderSlot('semi2.workspace', { view: 'page' }, { entryKey: active })\n ) : (\n <WorkspaceTab t={t} projected={projected} controller={controller} tab={activeTab ?? tabs[0]} />\n )}\n </div>\n </div>\n )\n}\n","// @fa-software/semi2-dsh/client/locales —— 浏览器半边字典(NS=semi2;键与 host 字段一一对应)。\n// 中文为主、英文键兜底;错误码对照表是硬契约(§3.6:绝不再把非凭据错误伪装成 LOGIN_FAILED)。\nexport const NS = 'semi2'\n\nexport const zh = {\n panel: 'Semi2',\n title: 'Semi2',\n intro: 'semi2-hub 配置总览',\n tabOverview: '总览',\n tabMenuLabel: '切换工作区',\n status: '状态',\n statusLocal: '未连接',\n statusLoading: '读取中',\n statusReady: '已连接',\n statusFailed: '失败',\n identity: '身份',\n platform: '运行面',\n surfacecnb: 'CNB',\n surfacecontainer: '容器',\n surfacehost: '宿主直跑',\n consoleUrl: 'hub 地址',\n loadedAt: '最近更新',\n timeNow: '刚刚',\n timeMinutes: '{n}分钟',\n timeHours: '{n}小时',\n timeDays: '{n}天',\n timeMonths: '{n}个月',\n timeYears: '{n}年',\n error: '最近失败',\n healthTitle: '能力健康',\n healthWebLabel: '网页能力',\n healthCodegraphLabel: '代码索引',\n actions: '操作',\n diagnostics: '诊断',\n loginTitle: '登录 semi2-hub',\n loginUrl: '地址',\n loginUsername: '用户名',\n loginPassword: '密码',\n loginSubmit: '登录',\n logout: '登出',\n logoutBusy: '正在登出…',\n loginBusy: '正在登录…',\n sync: '同步',\n syncWorkspace: '只同步该工作区',\n workspaceTitle: '工作区',\n workspaceSlug: 'git slug',\n workspaceProject: '项目',\n workspaceSyncedAt: '同步时间',\n workspaceUnresolved: '未解析(不归 semi2-hub 管)',\n workspaceNone: '没有已登记的工作区',\n domainModels: '模型',\n domainSecrets: '模型密钥',\n domainSkills: '技能',\n domainWorkspace: '工作区',\n domainDefaultModel: '默认模型',\n domainSelfPortrait: '自画像',\n domainRedmine: 'Redmine',\n workspaces: '工作区列表',\n projects: '项目绑定',\n model: '默认模型(hub 下发)',\n skills: '控制台技能',\n none: '无',\n errINVALID_CREDENTIALS: '账号或密码不正确',\n errINVALID_CONFIG_URL: 'hub 地址不合法(必须 https,或本机回环 http)',\n errORIGIN_DENIED: '该 hub 不接受这个地址(请用 hub 自己的域名)',\n errCONFIG_REQUEST_FAILED: '连不上 hub(网络、域名解析或证书问题)',\n errCREDENTIAL_SOURCE_READONLY: '地址由部署环境固定,不能在这里修改',\n errCREDENTIAL_STORE_UNAVAILABLE: '本机凭据存储不可用,登录态无法保存',\n errWEB_ROUTE_UNAVAILABLE: '宿主插件没有注册动作接口(版本或装配异常;重启 dsh 或升级插件)',\n errINVALID_INPUT: '输入不完整',\n errMETHOD_NOT_ALLOWED: '请求方法不受支持',\n errLOGIN_FAILED: '登录失败',\n errLOGOUT_FAILED: '登出失败',\n}\n\nexport const en = {\n panel: 'Semi2',\n title: 'Semi2',\n intro: 'semi2-hub configuration',\n tabOverview: 'Overview',\n tabMenuLabel: 'Switch workspace',\n status: 'Status',\n statusLocal: 'Not connected',\n statusLoading: 'Loading',\n statusReady: 'Connected',\n statusFailed: 'Failed',\n identity: 'Identity',\n platform: 'Surface',\n surfacecnb: 'CNB',\n surfacecontainer: 'Container',\n surfacehost: 'Host',\n consoleUrl: 'Hub URL',\n loadedAt: 'Updated',\n timeNow: 'now',\n timeMinutes: '{n}min',\n timeHours: '{n}h',\n timeDays: '{n}d',\n timeMonths: '{n}mo',\n timeYears: '{n}y',\n error: 'Last error',\n healthTitle: 'Capability health',\n healthWebLabel: 'Web surface',\n healthCodegraphLabel: 'Code index',\n actions: 'Actions',\n diagnostics: 'Diagnostics',\n loginTitle: 'Sign in to semi2-hub',\n loginUrl: 'URL',\n loginUsername: 'Username',\n loginPassword: 'Password',\n loginSubmit: 'Sign in',\n logout: 'Sign out',\n logoutBusy: 'Signing out…',\n loginBusy: 'Signing in…',\n sync: 'Sync',\n syncWorkspace: 'Sync this workspace only',\n workspaceTitle: 'Workspace',\n workspaceSlug: 'git slug',\n workspaceProject: 'Project',\n workspaceSyncedAt: 'Synced at',\n workspaceUnresolved: 'Unresolved (not managed by semi2-hub)',\n workspaceNone: 'No registered workspaces',\n domainModels: 'Models',\n domainSecrets: 'Model keys',\n domainSkills: 'Skills',\n domainWorkspace: 'Workspaces',\n domainDefaultModel: 'Default model',\n domainSelfPortrait: 'Self-portrait',\n domainRedmine: 'Redmine',\n workspaces: 'Workspaces',\n projects: 'Project bindings',\n model: 'Default model (from hub)',\n skills: 'Console skills',\n none: 'None',\n errINVALID_CREDENTIALS: 'Incorrect username or password',\n errINVALID_CONFIG_URL: 'Invalid hub URL (https required, or loopback http)',\n errORIGIN_DENIED: 'The hub rejects this address (use the hub\\u2019s own domain)',\n errCONFIG_REQUEST_FAILED: 'Cannot reach the hub (network, DNS, or certificate issue)',\n errCREDENTIAL_SOURCE_READONLY: 'The URL is pinned by the deployment environment',\n errCREDENTIAL_STORE_UNAVAILABLE: 'Local credential store unavailable; sign-in cannot persist',\n errWEB_ROUTE_UNAVAILABLE: 'Host plugin did not register the action routes (version or assembly issue; restart dsh or upgrade the plugin)',\n errINVALID_INPUT: 'Incomplete input',\n errMETHOD_NOT_ALLOWED: 'Method not allowed',\n errLOGIN_FAILED: 'Sign-in failed',\n errLOGOUT_FAILED: 'Sign-out failed',\n}\n","// @fa-software/semi2-dsh/client/styles —— 唯一的自绘样式模块(页面骨架 + tab 条 + 行)。\n// 控件本体全部来自官方原子包(样式随组件自带);版面值照官方主列页(plugin-manager 的 page/tabs/row),\n// 文字层级一律用 --dsw-alias-label-* 语义色,不拿 opacity 压暗。\nconst STYLE_ID = 'semi2-dsh-client-styles'\n\nconst CSS = `\n.semi2-page {\n box-sizing: border-box;\n height: 100%;\n overflow: auto;\n display: flex;\n justify-content: center;\n align-items: flex-start;\n padding: 28px clamp(24px, 4vw, 48px) 48px;\n color: var(--dsw-alias-label-primary);\n}\n.semi2-column { display: flex; flex-direction: column; gap: 32px; width: 100%; max-width: 960px; }\n.semi2-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }\n.semi2-headText { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n.semi2-title { margin: 0; font-size: 20px; font-weight: 500; line-height: 28px; }\n.semi2-intro { margin: 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n.semi2-toolbar { display: flex; align-items: center; gap: 8px; flex: none; }\n.semi2-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 420px;\n padding: 16px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n}\n.semi2-cardTitle { margin: 0; font-size: 14px; font-weight: 500; line-height: 20px; }\n.semi2-tabs {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-end;\n gap: 22px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n.semi2-tab {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n max-width: 240px;\n padding: 7px 1px 9px;\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-tertiary);\n background: none;\n border: 0;\n cursor: pointer;\n}\n.semi2-tab:hover, .semi2-tab[data-active='true'] { color: var(--dsw-alias-label-primary); }\n.semi2-tab[data-active='true']::after {\n content: '';\n position: absolute;\n inset: auto 0 -1px;\n height: 2px;\n background: var(--dsw-alias-label-primary);\n}\n.semi2-tabLabel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.semi2-section { display: flex; flex-direction: column; gap: 4px; }\n.semi2-section > .semi2-section { margin-top: 12px; }\n.semi2-sectionTitle { margin: 0; font-size: 14px; font-weight: 500; line-height: 20px; }\n.semi2-rows { display: flex; flex-direction: column; }\n.semi2-row {\n display: flex;\n gap: 16px;\n align-items: baseline;\n padding: 12px 2px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n.semi2-rowKey { flex: none; min-width: 120px; color: var(--dsw-alias-label-tertiary); }\n.semi2-rowValue { display: inline-flex; align-items: center; gap: 6px; min-width: 0; margin: 0; overflow-wrap: anywhere; }\n.semi2-empty { margin: 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n.semi2-form { display: flex; flex-direction: column; gap: 8px; }\n.semi2-formActions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }\n.semi2-hint { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.semi2-error { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-error, var(--dsw-alias-state-error-primary)); }\n.semi2-muted { color: var(--dsw-alias-label-tertiary); }\n.semi2-disclosure { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n`\n\n/** 幂等注入一次性 <style>(令牌缺位的极端情况由兜底值兜住)。 */\nexport function injectStyles() {\n if (typeof document === 'undefined') return\n if (document.getElementById(STYLE_ID) !== null) return\n const element = document.createElement('style')\n element.id = STYLE_ID\n element.textContent = CSS\n document.head.append(element)\n}\n","// @fa-software/semi2-dsh/client —— 浏览器半边:侧栏一级入口(与「插件」同级)+ 主列整页。\n// 门控照官方:宿主没服务本插件设置段(`SEMI2_SETTINGS_ENTRY`)时,导航行与主列页**同时撤销**(不留坏入口)。\n// 状态经官方设置表单读(`configForms`),动作走 /semi2/* 自建路由(官方请求校验面后)。\nimport { Semi2Controller } from './controller.js'\nimport { Semi2Page, Semi2PanelIcon } from './page.jsx'\nimport { WorkspaceTab } from './workspace-tab.jsx'\nimport { NS, zh, en } from './locales.js'\nimport { injectStyles } from './styles.js'\nimport { SEMI2_SETTINGS_ENTRY } from '../contract.js'\n\nexport const PANEL_ID = 'semi2'\n\nexport const inject = ['slots', 'configForms', 'locale']\n\nexport function apply(ctx) {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'semi2: dictionaries')\n const t = ctx.locale.bind(NS)\n injectStyles()\n const controller = new Semi2Controller(ctx)\n ctx.effect(() => () => controller.dispose(), 'semi2: controller')\n\n // 工作区 tab 的 keyed 子槽条目:登记表增减即增减(每个 tab 按 key 贡献一份内容)。\n const workspaceEntries = new Map()\n const syncWorkspaceEntries = () => {\n const { tabs } = controller.getSnapshot().projected\n const wanted = new Set(\n tabs.filter((tab) => tab.title !== '').map((tab) => (tab.slug === '' ? `title:${tab.title}` : `workspace:${tab.slug}`)),\n )\n for (const [key, dispose] of workspaceEntries) {\n if (wanted.has(key)) continue\n dispose()\n workspaceEntries.delete(key)\n }\n for (const key of wanted) {\n if (workspaceEntries.has(key)) continue\n const tab = tabs.find((candidate) =>\n candidate.slug === '' ? `title:${candidate.title}` === key : `workspace:${candidate.slug}` === key,\n )\n if (tab === undefined) continue\n const dispose = ctx.slots.inject('semi2.workspace', () =>\n ctx.slots.register(\n {\n name: 'semi2.workspace',\n key,\n locale: NS,\n inject: () => ({ controller, tab }),\n },\n WorkspaceTab,\n ),\n )\n workspaceEntries.set(key, dispose)\n }\n }\n\n // 官方 `whileServed`:设置段出现在 describe 镜像里才注册(面板 + 侧栏入口 + 工作区子槽),\n // 撤下时整组回收——keyed 子槽留着不清的话,重新上架后旧条目再也回收不掉。\n ctx.effect(\n () =>\n ctx.configForms.whileServed([SEMI2_SETTINGS_ENTRY], () => {\n const registered = new Map()\n syncWorkspaceEntries()\n registered.set('tabs', controller.subscribe(syncWorkspaceEntries))\n registered.set(\n 'panel',\n ctx.slots.inject('main', () =>\n ctx.slots.register(\n {\n name: 'main',\n key: PANEL_ID,\n locale: NS,\n children: { 'semi2.workspace': { kind: 'keyed', scope: 'root' } },\n inject: () => ({ controller }),\n },\n Semi2Page,\n ),\n ),\n )\n registered.set(\n 'sidebar',\n ctx.slots.inject('sidebar.panellist', () =>\n ctx.slots.register(\n {\n name: 'sidebar.panellist',\n id: PANEL_ID,\n order: 10,\n label: () => t('panel'),\n locale: NS,\n },\n Semi2PanelIcon,\n ),\n ),\n )\n return () => {\n for (const dispose of registered.values()) dispose()\n registered.clear()\n for (const dispose of workspaceEntries.values()) dispose()\n workspaceEntries.clear()\n }\n }),\n 'semi2: sidebar entry + main page',\n )\n}\n"],"mappings":"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"}