@jingyi0605/codingns4dsh 0.2.1-rc.4 → 0.2.1-rc.5

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 (189) hide show
  1. package/README.en.md +3 -3
  2. package/README.md +3 -3
  3. package/data/build/dist/client/bundle.js +1672 -178
  4. package/data/build/dist/client/bundle.js.map +1 -1
  5. package/data/build/dist/client/cli-session-config-cache.d.ts.map +1 -1
  6. package/data/build/dist/client/cli-session-config-cache.js +9 -3
  7. package/data/build/dist/client/cli-session-config-cache.js.map +1 -1
  8. package/data/build/dist/client/client.native-workspace-store.js +7 -1
  9. package/data/build/dist/client/client.native-workspace-store.js.map +1 -1
  10. package/data/build/dist/client/client.transport.js +244 -50
  11. package/data/build/dist/client/client.transport.js.map +1 -1
  12. package/data/build/dist/client/desktop-assistant.js +242 -48
  13. package/data/build/dist/client/features/cli-adapters.d.ts.map +1 -1
  14. package/data/build/dist/client/features/cli-adapters.js +13 -1
  15. package/data/build/dist/client/features/cli-adapters.js.map +1 -1
  16. package/data/build/dist/client/features/index.d.ts.map +1 -1
  17. package/data/build/dist/client/features/index.js +2 -0
  18. package/data/build/dist/client/features/index.js.map +1 -1
  19. package/data/build/dist/client/features/magpie-management-page.d.ts.map +1 -1
  20. package/data/build/dist/client/features/magpie-management-page.js +80 -31
  21. package/data/build/dist/client/features/magpie-management-page.js.map +1 -1
  22. package/data/build/dist/client/features/magpie-management.d.ts.map +1 -1
  23. package/data/build/dist/client/features/magpie-management.js +3 -2
  24. package/data/build/dist/client/features/magpie-management.js.map +1 -1
  25. package/data/build/dist/client/features/plugin-update.d.ts +3 -0
  26. package/data/build/dist/client/features/plugin-update.d.ts.map +1 -0
  27. package/data/build/dist/client/features/plugin-update.js +8 -0
  28. package/data/build/dist/client/features/plugin-update.js.map +1 -0
  29. package/data/build/dist/client/features/types.d.ts +3 -0
  30. package/data/build/dist/client/features/types.d.ts.map +1 -1
  31. package/data/build/dist/client/locale.d.ts.map +1 -1
  32. package/data/build/dist/client/locale.js +3 -0
  33. package/data/build/dist/client/locale.js.map +1 -1
  34. package/data/build/dist/client/locales/magpie.d.ts.map +1 -1
  35. package/data/build/dist/client/locales/magpie.js +60 -2
  36. package/data/build/dist/client/locales/magpie.js.map +1 -1
  37. package/data/build/dist/client/locales/pluginUpdate.d.ts +3 -0
  38. package/data/build/dist/client/locales/pluginUpdate.d.ts.map +1 -0
  39. package/data/build/dist/client/locales/pluginUpdate.js +131 -0
  40. package/data/build/dist/client/locales/pluginUpdate.js.map +1 -0
  41. package/data/build/dist/client/locales/usage.d.ts.map +1 -1
  42. package/data/build/dist/client/locales/usage.js +2 -0
  43. package/data/build/dist/client/locales/usage.js.map +1 -1
  44. package/data/build/dist/client/magpie-context-meter.d.ts +18 -0
  45. package/data/build/dist/client/magpie-context-meter.d.ts.map +1 -0
  46. package/data/build/dist/client/magpie-context-meter.js +274 -0
  47. package/data/build/dist/client/magpie-context-meter.js.map +1 -0
  48. package/data/build/dist/client/magpie-context-store.d.ts +32 -0
  49. package/data/build/dist/client/magpie-context-store.d.ts.map +1 -0
  50. package/data/build/dist/client/magpie-context-store.js +165 -0
  51. package/data/build/dist/client/magpie-context-store.js.map +1 -0
  52. package/data/build/dist/client/settings-promo-styles.d.ts +5 -0
  53. package/data/build/dist/client/settings-promo-styles.d.ts.map +1 -1
  54. package/data/build/dist/client/settings-promo-styles.js +15 -2
  55. package/data/build/dist/client/settings-promo-styles.js.map +1 -1
  56. package/data/build/dist/client/settings-promo.d.ts +4 -2
  57. package/data/build/dist/client/settings-promo.d.ts.map +1 -1
  58. package/data/build/dist/client/settings-promo.js +4 -4
  59. package/data/build/dist/client/settings-promo.js.map +1 -1
  60. package/data/build/dist/client/settings-section.d.ts +2 -3
  61. package/data/build/dist/client/settings-section.d.ts.map +1 -1
  62. package/data/build/dist/client/settings-section.js +7 -7
  63. package/data/build/dist/client/settings-section.js.map +1 -1
  64. package/data/build/dist/client/settings-update.d.ts +8 -0
  65. package/data/build/dist/client/settings-update.d.ts.map +1 -0
  66. package/data/build/dist/client/settings-update.js +57 -0
  67. package/data/build/dist/client/settings-update.js.map +1 -0
  68. package/data/build/dist/client/subscription-slot.d.ts.map +1 -1
  69. package/data/build/dist/client/subscription-slot.js +47 -21
  70. package/data/build/dist/client/subscription-slot.js.map +1 -1
  71. package/data/build/dist/client/update-panel-styles.d.ts +29 -0
  72. package/data/build/dist/client/update-panel-styles.d.ts.map +1 -0
  73. package/data/build/dist/client/update-panel-styles.js +69 -0
  74. package/data/build/dist/client/update-panel-styles.js.map +1 -0
  75. package/data/build/dist/client/update-panel.d.ts +7 -0
  76. package/data/build/dist/client/update-panel.d.ts.map +1 -0
  77. package/data/build/dist/client/update-panel.js +52 -0
  78. package/data/build/dist/client/update-panel.js.map +1 -0
  79. package/data/build/dist/client/update-store.d.ts +43 -0
  80. package/data/build/dist/client/update-store.d.ts.map +1 -0
  81. package/data/build/dist/client/update-store.js +207 -0
  82. package/data/build/dist/client/update-store.js.map +1 -0
  83. package/data/build/dist/dsh-capabilities/client/plugin-reload-adapter.d.ts +4 -0
  84. package/data/build/dist/dsh-capabilities/client/plugin-reload-adapter.d.ts.map +1 -0
  85. package/data/build/dist/dsh-capabilities/client/plugin-reload-adapter.js +6 -0
  86. package/data/build/dist/dsh-capabilities/client/plugin-reload-adapter.js.map +1 -0
  87. package/data/build/dist/dsh-capabilities/client/session-performance-adapter.d.ts +15 -1
  88. package/data/build/dist/dsh-capabilities/client/session-performance-adapter.d.ts.map +1 -1
  89. package/data/build/dist/dsh-capabilities/client/session-performance-adapter.js +53 -21
  90. package/data/build/dist/dsh-capabilities/client/session-performance-adapter.js.map +1 -1
  91. package/data/build/dist/dsh-capabilities/host/plugin-update-adapter.d.ts +22 -0
  92. package/data/build/dist/dsh-capabilities/host/plugin-update-adapter.d.ts.map +1 -0
  93. package/data/build/dist/dsh-capabilities/host/plugin-update-adapter.js +71 -0
  94. package/data/build/dist/dsh-capabilities/host/plugin-update-adapter.js.map +1 -0
  95. package/data/build/dist/dsh-capabilities/host/session-model-selection-adapter.d.ts +4 -0
  96. package/data/build/dist/dsh-capabilities/host/session-model-selection-adapter.d.ts.map +1 -1
  97. package/data/build/dist/dsh-capabilities/host/session-model-selection-adapter.js +16 -1
  98. package/data/build/dist/dsh-capabilities/host/session-model-selection-adapter.js.map +1 -1
  99. package/data/build/dist/dsh-capabilities/matrix.d.ts.map +1 -1
  100. package/data/build/dist/dsh-capabilities/matrix.js +4 -0
  101. package/data/build/dist/dsh-capabilities/matrix.js.map +1 -1
  102. package/data/build/dist/dsh-capabilities/routes.d.ts.map +1 -1
  103. package/data/build/dist/dsh-capabilities/routes.js +10 -0
  104. package/data/build/dist/dsh-capabilities/routes.js.map +1 -1
  105. package/data/build/dist/dsh-capabilities/types.d.ts +1 -1
  106. package/data/build/dist/dsh-capabilities/types.d.ts.map +1 -1
  107. package/data/build/dist/dsh-capabilities/types.js.map +1 -1
  108. package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
  109. package/data/build/dist/host/cli-adapters/feature.js +174 -26
  110. package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
  111. package/data/build/dist/host/cli-adapters/magpie-context.d.ts +9 -0
  112. package/data/build/dist/host/cli-adapters/magpie-context.d.ts.map +1 -0
  113. package/data/build/dist/host/cli-adapters/magpie-context.js +128 -0
  114. package/data/build/dist/host/cli-adapters/magpie-context.js.map +1 -0
  115. package/data/build/dist/host/cli-adapters/magpie-update.d.ts.map +1 -1
  116. package/data/build/dist/host/cli-adapters/magpie-update.js +14 -4
  117. package/data/build/dist/host/cli-adapters/magpie-update.js.map +1 -1
  118. package/data/build/dist/host/cli-adapters/magpie-usage.d.ts +12 -2
  119. package/data/build/dist/host/cli-adapters/magpie-usage.d.ts.map +1 -1
  120. package/data/build/dist/host/cli-adapters/magpie-usage.js +114 -50
  121. package/data/build/dist/host/cli-adapters/magpie-usage.js.map +1 -1
  122. package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
  123. package/data/build/dist/host/cli-adapters/registry.js +6 -5
  124. package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
  125. package/data/build/dist/host/features/index.d.ts.map +1 -1
  126. package/data/build/dist/host/features/index.js +2 -0
  127. package/data/build/dist/host/features/index.js.map +1 -1
  128. package/data/build/dist/host/features/plugin-update.d.ts +6 -0
  129. package/data/build/dist/host/features/plugin-update.d.ts.map +1 -0
  130. package/data/build/dist/host/features/plugin-update.js +45 -0
  131. package/data/build/dist/host/features/plugin-update.js.map +1 -0
  132. package/data/build/dist/host/index.d.ts.map +1 -1
  133. package/data/build/dist/host/index.js +31 -1
  134. package/data/build/dist/host/index.js.map +1 -1
  135. package/data/build/dist/host/native-session-bridge.d.ts +8 -0
  136. package/data/build/dist/host/native-session-bridge.d.ts.map +1 -1
  137. package/data/build/dist/host/native-session-bridge.js +43 -0
  138. package/data/build/dist/host/native-session-bridge.js.map +1 -1
  139. package/data/build/dist/host/rpc.d.ts +4 -1
  140. package/data/build/dist/host/rpc.d.ts.map +1 -1
  141. package/data/build/dist/host/rpc.js +33 -7
  142. package/data/build/dist/host/rpc.js.map +1 -1
  143. package/data/build/dist/host/session-handle-eviction.d.ts +29 -0
  144. package/data/build/dist/host/session-handle-eviction.d.ts.map +1 -0
  145. package/data/build/dist/host/session-handle-eviction.js +413 -0
  146. package/data/build/dist/host/session-handle-eviction.js.map +1 -0
  147. package/data/build/dist/host/settings.d.ts.map +1 -1
  148. package/data/build/dist/host/settings.js +12 -1
  149. package/data/build/dist/host/settings.js.map +1 -1
  150. package/data/build/dist/host/update/application-result.d.ts +3 -0
  151. package/data/build/dist/host/update/application-result.d.ts.map +1 -0
  152. package/data/build/dist/host/update/application-result.js +13 -0
  153. package/data/build/dist/host/update/application-result.js.map +1 -0
  154. package/data/build/dist/host/update/http.d.ts +7 -0
  155. package/data/build/dist/host/update/http.d.ts.map +1 -0
  156. package/data/build/dist/host/update/http.js +55 -0
  157. package/data/build/dist/host/update/http.js.map +1 -0
  158. package/data/build/dist/host/update/metadata.d.ts +14 -0
  159. package/data/build/dist/host/update/metadata.d.ts.map +1 -0
  160. package/data/build/dist/host/update/metadata.js +75 -0
  161. package/data/build/dist/host/update/metadata.js.map +1 -0
  162. package/data/build/dist/host/update/release-notes.d.ts +6 -0
  163. package/data/build/dist/host/update/release-notes.d.ts.map +1 -0
  164. package/data/build/dist/host/update/release-notes.js +52 -0
  165. package/data/build/dist/host/update/release-notes.js.map +1 -0
  166. package/data/build/dist/host/update/service.d.ts +25 -0
  167. package/data/build/dist/host/update/service.d.ts.map +1 -0
  168. package/data/build/dist/host/update/service.js +209 -0
  169. package/data/build/dist/host/update/service.js.map +1 -0
  170. package/data/build/dist/shared/contracts/config.d.ts +17 -0
  171. package/data/build/dist/shared/contracts/config.d.ts.map +1 -1
  172. package/data/build/dist/shared/contracts/config.js +8 -0
  173. package/data/build/dist/shared/contracts/config.js.map +1 -1
  174. package/data/build/dist/shared/contracts/magpie-management.d.ts +40 -0
  175. package/data/build/dist/shared/contracts/magpie-management.d.ts.map +1 -1
  176. package/data/build/dist/shared/contracts/plugin-update.d.ts +93 -0
  177. package/data/build/dist/shared/contracts/plugin-update.d.ts.map +1 -0
  178. package/data/build/dist/shared/contracts/plugin-update.js +128 -0
  179. package/data/build/dist/shared/contracts/plugin-update.js.map +1 -0
  180. package/data/build/dist/shared/contracts/subscription.d.ts +3 -0
  181. package/data/build/dist/shared/contracts/subscription.d.ts.map +1 -1
  182. package/data/build/dist/shared/contracts/subscription.js.map +1 -1
  183. package/data/build/dist/shared/contracts/version.d.ts +1 -1
  184. package/data/build/dist/shared/contracts/version.js +1 -1
  185. package/package.json +2 -1
  186. package/profile/README.md +2 -2
  187. package/profile/package.json +2 -2
  188. package/profile/version.json +1 -1
  189. package/version.json +1 -1
@@ -8376,7 +8376,7 @@ window.__ModuleLoader__.load({
8376
8376
  return /^0\.1\.5(?:-|$)/u.test(version);
8377
8377
  }
8378
8378
  /** Codingns4DSH 插件自身的 npm 版本。 */
8379
- const CODINGNS_VERSION = "0.2.1-rc.4";
8379
+ const CODINGNS_VERSION = "0.2.1-rc.5";
8380
8380
  /** 判断宿主版本是否落在当前插件声明的 DSH 兼容范围内;范围省略上界时不校验上限。 */
8381
8381
  function isDshVersionCompatible(version) {
8382
8382
  const match = /^>=([^ ]+)(?: <=([^ ]+))?$/u.exec(DSH_COMPATIBILITY);
@@ -8493,6 +8493,11 @@ window.__ModuleLoader__.load({
8493
8493
  enabled: false,
8494
8494
  maxConcurrentSubagents: 8
8495
8495
  };
8496
+ const DEFAULT_SESSION_HANDLE_EVICTION_SETTINGS = {
8497
+ enabled: true,
8498
+ idleTtlMs: 6e5,
8499
+ maxOpenHandles: 32
8500
+ };
8496
8501
  /** 归一化子代理托管设置:只有显式 true 才算开启;并发数按上下限收敛。 */
8497
8502
  function normalizeSubagentBridgeSettings(value) {
8498
8503
  const record = typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
@@ -8704,6 +8709,7 @@ window.__ModuleLoader__.load({
8704
8709
  agentAdapterPreferences: {},
8705
8710
  subagentBridge: DEFAULT_SUBAGENT_BRIDGE_SETTINGS,
8706
8711
  sessionTranslation: require_session_translation.DEFAULT_SESSION_TRANSLATION_SETTINGS,
8712
+ sessionHandleEviction: DEFAULT_SESSION_HANDLE_EVICTION_SETTINGS,
8707
8713
  gitManagement: DEFAULT_GIT_MANAGEMENT_SETTINGS,
8708
8714
  terminalEnhancement: DEFAULT_TERMINAL_ENHANCEMENT_SETTINGS,
8709
8715
  workspaceSessionEnhancement: DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS,
@@ -17440,7 +17446,7 @@ window.__ModuleLoader__.load({
17440
17446
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
17441
17447
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
17442
17448
  */
17443
- const en$17 = {
17449
+ const en$18 = {
17444
17450
  "debug.title": "Debug",
17445
17451
  "debug.guideDescription": "Start workspace commands, check ports, and open services",
17446
17452
  "debug.readingWorkspace": "Reading workspace…",
@@ -17518,7 +17524,7 @@ window.__ModuleLoader__.load({
17518
17524
  "feature.debug.label": "Workspace debugging",
17519
17525
  "feature.debug.description": "Launch terminals and check services"
17520
17526
  };
17521
- const zh$17 = {
17527
+ const zh$18 = {
17522
17528
  "debug.title": "调试",
17523
17529
  "debug.guideDescription": "启动工作区命令、检查端口并访问服务",
17524
17530
  "debug.readingWorkspace": "正在读取工作区…",
@@ -17599,7 +17605,7 @@ window.__ModuleLoader__.load({
17599
17605
  //#endregion
17600
17606
  //#region src/client/locales/assistantDebug.ts
17601
17607
  /** 全局助理调试页词典;状态名与 JSON 只在明确的调试区域展示。 */
17602
- const zh$16 = {
17608
+ const zh$17 = {
17603
17609
  "assistant.debug.open": "全局项目状态调试",
17604
17610
  "assistant.debug.title": "全局助理管理状态调试",
17605
17611
  "assistant.debug.description": "独立检查工作区范围、会话状态和文字指令,无需启动语音。",
@@ -17779,7 +17785,7 @@ window.__ModuleLoader__.load({
17779
17785
  "assistant.debug.analysisState.cancelled": "总结已停止,原始索引材料已保留",
17780
17786
  "assistant.debug.rawEvidence": "以下是原始会话摘录,作为总结证据保留,不是 LLM 生成的进展判断。"
17781
17787
  };
17782
- const en$16 = {
17788
+ const en$17 = {
17783
17789
  "assistant.debug.open": "Global project state debug",
17784
17790
  "assistant.debug.title": "Global assistant management debug",
17785
17791
  "assistant.debug.description": "Inspect workspace scope, session state and text commands without starting voice.",
@@ -17961,7 +17967,7 @@ window.__ModuleLoader__.load({
17961
17967
  };
17962
17968
  //#endregion
17963
17969
  //#region src/client/locales/assistantAvatar.ts
17964
- const en$15 = {
17970
+ const en$16 = {
17965
17971
  "avatar.portraitTitle": "Avatar",
17966
17972
  "avatar.portraitEdit": "Adjust avatar",
17967
17973
  "avatar.portraitLocalHint": "Saved in this browser for this character; conversation and sidebar avatars update together.",
@@ -18097,7 +18103,7 @@ window.__ModuleLoader__.load({
18097
18103
  "avatar.desktopFallback": "Desktop companion unavailable; showing inside this window.",
18098
18104
  "avatar.dragHint": "Drag to move; click to open the assistant."
18099
18105
  };
18100
- const zh$15 = {
18106
+ const zh$16 = {
18101
18107
  "avatar.portraitTitle": "头像",
18102
18108
  "avatar.portraitEdit": "微调头像",
18103
18109
  "avatar.portraitLocalHint": "按形象保存在当前浏览器,对话与侧栏头像同步更新。",
@@ -18241,7 +18247,7 @@ window.__ModuleLoader__.load({
18241
18247
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
18242
18248
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
18243
18249
  */
18244
- const en$14 = {
18250
+ const en$15 = {
18245
18251
  "htmlFiles.confirmConnect": "Allow this HTML page to read, save, and delete files in these locations?\n\nPage: {path}\n\n{scopes}\n\nAccess lasts until this preview is closed or reloaded.",
18246
18252
  "htmlFiles.cancelled": "Workspace file connection cancelled.",
18247
18253
  "fileMenu.expandFolder": "Expand folder",
@@ -18314,7 +18320,7 @@ window.__ModuleLoader__.load({
18314
18320
  "pwaPrompt.dismiss": "Not now",
18315
18321
  "pwaPrompt.iosHint": "Tap \"Share\" then \"Add to Home Screen\" to install."
18316
18322
  };
18317
- const zh$14 = {
18323
+ const zh$15 = {
18318
18324
  "htmlFiles.confirmConnect": "允许此 HTML 页面读取、保存和删除以下位置中的文件吗?\n\n页面:{path}\n\n{scopes}\n\n授权在关闭或重新加载预览后失效。",
18319
18325
  "htmlFiles.cancelled": "已取消工作区文件连接。",
18320
18326
  "fileMenu.expandFolder": "展开文件夹",
@@ -18395,7 +18401,7 @@ window.__ModuleLoader__.load({
18395
18401
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
18396
18402
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
18397
18403
  */
18398
- const en$13 = {
18404
+ const en$14 = {
18399
18405
  "feature.gitManagement.label": "Git repository management",
18400
18406
  "feature.gitManagement.description": "View changes and manage commits",
18401
18407
  "git.tabTitle": "Git",
@@ -18517,7 +18523,7 @@ window.__ModuleLoader__.load({
18517
18523
  "git.unknownTime": "Unknown time",
18518
18524
  "git.dateLabel": "{month}/{day}"
18519
18525
  };
18520
- const zh$13 = {
18526
+ const zh$14 = {
18521
18527
  "feature.gitManagement.label": "Git 仓库管理",
18522
18528
  "feature.gitManagement.description": "查看改动并管理提交",
18523
18529
  "git.tabTitle": "Git",
@@ -18647,7 +18653,7 @@ window.__ModuleLoader__.load({
18647
18653
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
18648
18654
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
18649
18655
  */
18650
- const en$12 = {
18656
+ const en$13 = {
18651
18657
  "common.listSeparator": ", ",
18652
18658
  "settings.unknownVersion": "Unknown version",
18653
18659
  "settings.maintenanceDisabled": "This module is disabled by maintenance policy; the setting will not start it.",
@@ -18748,7 +18754,7 @@ window.__ModuleLoader__.load({
18748
18754
  "translation.adapter.cursor": "Cursor",
18749
18755
  "translation.adapter.kiro": "Kiro"
18750
18756
  };
18751
- const zh$12 = {
18757
+ const zh$13 = {
18752
18758
  "common.listSeparator": "、",
18753
18759
  "settings.unknownVersion": "未知版本",
18754
18760
  "settings.maintenanceDisabled": "该模块当前由维护策略停用,设置不会启动它。",
@@ -18857,7 +18863,7 @@ window.__ModuleLoader__.load({
18857
18863
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
18858
18864
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
18859
18865
  */
18860
- const en$11 = {
18866
+ const en$12 = {
18861
18867
  "feature.peerHost.label": "Manage other DSH Hosts",
18862
18868
  "feature.peerHost.description": "Aggregate sessions from multiple Hosts",
18863
18869
  "peerHost.panelTitle": "Manage other DSH Hosts",
@@ -18938,7 +18944,7 @@ window.__ModuleLoader__.load({
18938
18944
  "peerHost.stateActive": "The preboot shim has taken over the page Transport; the native Connection of this page keeps reusing the same instance.",
18939
18945
  "peerHost.statePending": "The preboot shim is installed with CodingNS; it takes effect as soon as PeerHost is enabled, and native workspaces read the aggregate Transport directly."
18940
18946
  };
18941
- const zh$11 = {
18947
+ const zh$12 = {
18942
18948
  "feature.peerHost.label": "管理其他 DSH Host",
18943
18949
  "feature.peerHost.description": "聚合多个 Host 会话",
18944
18950
  "peerHost.panelTitle": "管理其他 DSH Host",
@@ -19027,7 +19033,7 @@ window.__ModuleLoader__.load({
19027
19033
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
19028
19034
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
19029
19035
  */
19030
- const en$10 = {
19036
+ const en$11 = {
19031
19037
  "peerHostWorkspace.tabLocal": "Local folders",
19032
19038
  "peerHostWorkspace.tabRemote": "Remote HOST",
19033
19039
  "peerHostWorkspace.sourceLabel": "Workspace source",
@@ -19073,7 +19079,7 @@ window.__ModuleLoader__.load({
19073
19079
  "peerHostWorkspace.hintNotReady": "“{host}” is currently “{status}”; finish connecting it in the management panel first.",
19074
19080
  "peerHostWorkspace.manageHosts": "Manage other DSH Hosts"
19075
19081
  };
19076
- const zh$10 = {
19082
+ const zh$11 = {
19077
19083
  "peerHostWorkspace.tabLocal": "本机文件夹",
19078
19084
  "peerHostWorkspace.tabRemote": "远程 HOST",
19079
19085
  "peerHostWorkspace.sourceLabel": "工作区来源",
@@ -19127,7 +19133,7 @@ window.__ModuleLoader__.load({
19127
19133
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
19128
19134
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
19129
19135
  */
19130
- const en$9 = {
19136
+ const en$10 = {
19131
19137
  "terminalShare.title": "Share terminal output to a conversation",
19132
19138
  "terminalShare.menuTitle": "Share to a conversation",
19133
19139
  "terminalShare.more": "More conversations",
@@ -19200,7 +19206,7 @@ window.__ModuleLoader__.load({
19200
19206
  "loginProtection.errorTimeoutRange": "The session timeout must be between 60 and 604800 seconds",
19201
19207
  "loginProtection.errorScopesRequired": "Select at least one scope"
19202
19208
  };
19203
- const zh$9 = {
19209
+ const zh$10 = {
19204
19210
  "terminalShare.title": "分享终端输出至会话",
19205
19211
  "terminalShare.menuTitle": "分享至会话",
19206
19212
  "terminalShare.more": "更多会话",
@@ -19281,7 +19287,7 @@ window.__ModuleLoader__.load({
19281
19287
  * 只放该域新增的键;合并与命名空间注册由 ../locale.ts 统一完成。
19282
19288
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
19283
19289
  */
19284
- const en$8 = {
19290
+ const en$9 = {
19285
19291
  "usage.r4StatsPeriod": "Account usage · UTC",
19286
19292
  "usage.r4TodayIoTokens": "Input + output tokens today",
19287
19293
  "usage.r4WeekRequests": "Requests · last 7 days",
@@ -19402,6 +19408,7 @@ window.__ModuleLoader__.load({
19402
19408
  "usage.magpieTabRoute": "Route + quota",
19403
19409
  "usage.magpieAggregateTitle": "Gateway usage",
19404
19410
  "usage.magpieSessionTitle": "This Agent session",
19411
+ "usage.magpieSessionTodayTitle": "This Agent session · today",
19405
19412
  "usage.magpieRouteTitle": "Latest route",
19406
19413
  "usage.magpieUsageUnavailable": "Magpie usage is unavailable.",
19407
19414
  "usage.magpieRequests": "Requests",
@@ -19486,7 +19493,7 @@ window.__ModuleLoader__.load({
19486
19493
  "usage.magpieRequestsTitle": "Magpie requests",
19487
19494
  "usage.magpieRequestsClose": "Close"
19488
19495
  };
19489
- const zh$8 = {
19496
+ const zh$9 = {
19490
19497
  "usage.r4StatsPeriod": "账户用量 · UTC",
19491
19498
  "usage.r4TodayIoTokens": "今日输入与输出 Token",
19492
19499
  "usage.r4WeekRequests": "近 7 天请求数",
@@ -19607,6 +19614,7 @@ window.__ModuleLoader__.load({
19607
19614
  "usage.magpieTabRoute": "路由 + 配额",
19608
19615
  "usage.magpieAggregateTitle": "网关用量",
19609
19616
  "usage.magpieSessionTitle": "当前 Agent 会话",
19617
+ "usage.magpieSessionTodayTitle": "当前 Agent 会话 · 今日",
19610
19618
  "usage.magpieRouteTitle": "最近路由",
19611
19619
  "usage.magpieUsageUnavailable": "暂时无法读取 Magpie 用量。",
19612
19620
  "usage.magpieRequests": "请求数",
@@ -19693,7 +19701,7 @@ window.__ModuleLoader__.load({
19693
19701
  };
19694
19702
  //#endregion
19695
19703
  //#region src/client/locales/voiceModels.ts
19696
- const en$7 = {
19704
+ const en$8 = {
19697
19705
  "voice.models.prepared": "Model resources are ready. Save the configuration to use this recognition model.",
19698
19706
  "voice.settings.input": "Speech input",
19699
19707
  "voice.settings.output": "Speech output",
@@ -19736,7 +19744,7 @@ window.__ModuleLoader__.load({
19736
19744
  "voice.models.localHint": "Models are stored on this Host. Verification tests model loading and recognition without using your microphone.",
19737
19745
  "voice.models.close": "Close"
19738
19746
  };
19739
- const zh$7 = {
19747
+ const zh$8 = {
19740
19748
  "voice.models.prepared": "模型资源已准备好,保存配置后使用此识别模型。",
19741
19749
  "voice.settings.input": "语音输入",
19742
19750
  "voice.settings.output": "语音输出",
@@ -19782,7 +19790,7 @@ window.__ModuleLoader__.load({
19782
19790
  //#endregion
19783
19791
  //#region src/client/locales/assistantTts.ts
19784
19792
  /** 独立音色面板词典;官方名称保留原文,元数据标签随界面语言翻译。 */
19785
- const en$6 = {
19793
+ const en$7 = {
19786
19794
  "tts.wizardPrepareResources": "Prepare voice resources",
19787
19795
  "tts.wizardDraftReady": "Voice resources are ready. Configuration changes apply after saving.",
19788
19796
  "tts.prepare": "Prepare MOSS resources",
@@ -19859,7 +19867,7 @@ window.__ModuleLoader__.load({
19859
19867
  "tts.saveParameters": "Save speech controls",
19860
19868
  "tts.resetParameters": "Restore and save defaults"
19861
19869
  };
19862
- const zh$6 = {
19870
+ const zh$7 = {
19863
19871
  "tts.wizardPrepareResources": "准备语音资源",
19864
19872
  "tts.wizardDraftReady": "语音资源已就绪,配置保存后生效。",
19865
19873
  "tts.prepare": "准备 MOSS 资源",
@@ -19939,7 +19947,7 @@ window.__ModuleLoader__.load({
19939
19947
  //#endregion
19940
19948
  //#region src/client/locales/assistantWorkbench.ts
19941
19949
  /** 生命周期工作台文案;高级资源管理复用原有词典。 */
19942
- const zh$5 = {
19950
+ const zh$6 = {
19943
19951
  "awb.notifications.title": "会话提醒",
19944
19952
  "awb.notifications.hint": "在悬浮助理旁显示提醒,查看会话后标记已读。",
19945
19953
  "awb.notifications.enabled": "启用会话提醒",
@@ -20107,7 +20115,7 @@ window.__ModuleLoader__.load({
20107
20115
  "awb.prompts": "提示词",
20108
20116
  "awb.unavailableSelection": "原选择暂不可用:{id}"
20109
20117
  };
20110
- const en$5 = {
20118
+ const en$6 = {
20111
20119
  "awb.notifications.title": "Session notices",
20112
20120
  "awb.notifications.hint": "Show notices beside the floating assistant. Viewing a session marks its notice as read.",
20113
20121
  "awb.notifications.enabled": "Enable session notices",
@@ -20285,7 +20293,7 @@ window.__ModuleLoader__.load({
20285
20293
  * 注册仍使用同一份 zh/en。
20286
20294
  * 规范见 docs/开发规范/20260930-前端文案国际化规范.md。
20287
20295
  */
20288
- const zh$4 = {
20296
+ const zh$5 = {
20289
20297
  "subagentCollapsed.inactive.one": "已停止 {count} 个子智能体",
20290
20298
  "subagentCollapsed.inactive.other": "已停止 {count} 个子智能体",
20291
20299
  "subagentCollapsed.inactive.expand": "展开已停止的子智能体",
@@ -20328,7 +20336,7 @@ window.__ModuleLoader__.load({
20328
20336
  "subagentCollapsed.open.sidebar": "在侧边栏打开",
20329
20337
  "subagentCollapsed.open.sidebar.aria": "在侧边栏打开 {label}"
20330
20338
  };
20331
- const en$4 = {
20339
+ const en$5 = {
20332
20340
  "subagentCollapsed.inactive.one": "{count} stopped subagent",
20333
20341
  "subagentCollapsed.inactive.other": "{count} stopped subagents",
20334
20342
  "subagentCollapsed.inactive.expand": "Show stopped subagents",
@@ -20384,7 +20392,7 @@ window.__ModuleLoader__.load({
20384
20392
  };
20385
20393
  //#endregion
20386
20394
  //#region src/client/locales/quickApps.ts
20387
- const en$3 = {
20395
+ const en$4 = {
20388
20396
  "quickApps.storagePreview": "App data is saved in this browser. IndexedDB and URLs starting with / are not supported in this view.",
20389
20397
  "quickApps.storageFailed": "App data could not be saved in this browser: {message}",
20390
20398
  "quickApps.sandboxPreview": "Workspace preview. Browser storage and URLs starting with / may not work in this view.",
@@ -20517,7 +20525,7 @@ window.__ModuleLoader__.load({
20517
20525
  "quickApps.status.missing-workspace": "The original workspace is unavailable.",
20518
20526
  "quickApps.status.missing-file": "The entry file or application folder is missing or cannot be accessed."
20519
20527
  };
20520
- const zh$3 = {
20528
+ const zh$4 = {
20521
20529
  "quickApps.storagePreview": "应用数据保存在当前浏览器中。此视图不支持 IndexedDB 和以 / 开头的网址。",
20522
20530
  "quickApps.storageFailed": "无法在当前浏览器中保存应用数据:{message}",
20523
20531
  "quickApps.sandboxPreview": "工作区预览:浏览器存储和以 / 开头的网址可能无法在此视图中使用。",
@@ -20652,7 +20660,7 @@ window.__ModuleLoader__.load({
20652
20660
  };
20653
20661
  //#endregion
20654
20662
  //#region src/client/locales/cliManagement.ts
20655
- const en$2 = {
20663
+ const en$3 = {
20656
20664
  "cli.team.label": "Team eligibility",
20657
20665
  "cli.team.leadAndMember": "Collaborator and Lead",
20658
20666
  "cli.team.member": "Collaborator",
@@ -20729,7 +20737,7 @@ window.__ModuleLoader__.load({
20729
20737
  "cli.manage.retryStatus": "Retry status",
20730
20738
  "cli.manage.reviewAgain": "Review another operation"
20731
20739
  };
20732
- const zh$2 = {
20740
+ const zh$3 = {
20733
20741
  "cli.team.label": "团队适配能力",
20734
20742
  "cli.team.leadAndMember": "协作者和管理者",
20735
20743
  "cli.team.member": "协作者",
@@ -20809,10 +20817,37 @@ window.__ModuleLoader__.load({
20809
20817
  //#endregion
20810
20818
  //#region src/client/locales/magpie.ts
20811
20819
  /** Copy for the optional Magpie usage dashboard. */
20812
- const en$1 = {
20820
+ const en$2 = {
20813
20821
  "feature.magpieManagement.label": "Magpie management and usage",
20814
20822
  "feature.magpieManagement.description": "Enable to add a separate Magpie Management page below Plugins in the global sidebar.",
20815
20823
  "magpie.sidebarLabel": "Magpie",
20824
+ "magpie.context.system": "System prompt",
20825
+ "magpie.context.tools": "Tools",
20826
+ "magpie.context.memory": "Memory",
20827
+ "magpie.context.files": "Files",
20828
+ "magpie.context.results": "Tool results",
20829
+ "magpie.context.chat": "Conversation content",
20830
+ "magpie.context.usedPercent": "Context used {percent}%",
20831
+ "magpie.context.window": "Context window",
20832
+ "magpie.context.used": "Used context",
20833
+ "magpie.context.native": "DSH context",
20834
+ "magpie.context.nativeTools": "Tool definitions",
20835
+ "magpie.context.nativeMessages": "Conversation messages",
20836
+ "magpie.context.nativeComposition": "Estimated composition (share of total)",
20837
+ "magpie.context.modelWindow": "Model window {value}",
20838
+ "magpie.context.cache": "Prompt cache",
20839
+ "magpie.context.hit": "hit",
20840
+ "magpie.context.close": "Close context",
20841
+ "magpie.context.composition": "Context composition",
20842
+ "magpie.context.content": "Content",
20843
+ "magpie.context.all": "All",
20844
+ "magpie.context.allCount": "All · {count}",
20845
+ "magpie.context.empty": "No content available",
20846
+ "magpie.context.rounds": "{count} rounds",
20847
+ "magpie.context.requests": "{count} requests",
20848
+ "magpie.context.request": "Request {count}",
20849
+ "magpie.context.earlierRounds": "Earlier {count} rounds",
20850
+ "magpie.context.round": "Round {count}",
20816
20851
  "magpie.usage": "Usage",
20817
20852
  "magpie.routing": "Routing",
20818
20853
  "magpie.statTokens": "Tokens",
@@ -20859,8 +20894,10 @@ window.__ModuleLoader__.load({
20859
20894
  "magpie.refreshing": "Refreshing…",
20860
20895
  "magpie.update.title": "Magpie update",
20861
20896
  "magpie.update.open": "Magpie {version}; open update details",
20897
+ "magpie.update.openAvailable": "Magpie {version}; update {latest} available; open update details",
20898
+ "magpie.update.badge": "New",
20862
20899
  "magpie.update.close": "Close Magpie update details",
20863
- "magpie.update.description": "Automatic checks observe Magpie in the background. Download and restart only run after you confirm a manual update.",
20900
+ "magpie.update.description": "Opening this page checks for updates automatically. Download and restart only run after you confirm a manual update.",
20864
20901
  "magpie.update.unavailable": "Magpie update status is unavailable.",
20865
20902
  "magpie.update.unsupported": "This Magpie version does not expose a supported update API.",
20866
20903
  "magpie.update.invalid": "Magpie returned an update response CodingNS cannot safely read.",
@@ -21130,10 +21167,37 @@ window.__ModuleLoader__.load({
21130
21167
  "magpie.install.customApply": "Detect this path",
21131
21168
  "magpie.install.disabledNote": "Magpie management stays off until a working Magpie CLI is detected."
21132
21169
  };
21133
- const zh$1 = {
21170
+ const zh$2 = {
21134
21171
  "feature.magpieManagement.label": "Magpie 管理与用量",
21135
21172
  "feature.magpieManagement.description": "启用后,会在全局侧栏的「插件」下方添加独立的 Magpie 管理页面。",
21136
21173
  "magpie.sidebarLabel": "Magpie",
21174
+ "magpie.context.system": "系统提示词",
21175
+ "magpie.context.tools": "工具",
21176
+ "magpie.context.memory": "记忆",
21177
+ "magpie.context.files": "文件",
21178
+ "magpie.context.results": "工具结果",
21179
+ "magpie.context.chat": "会话内容",
21180
+ "magpie.context.usedPercent": "上下文已用 {percent}%",
21181
+ "magpie.context.window": "上下文窗口",
21182
+ "magpie.context.used": "已用上下文",
21183
+ "magpie.context.native": "DSH 上下文",
21184
+ "magpie.context.nativeTools": "工具定义",
21185
+ "magpie.context.nativeMessages": "对话消息",
21186
+ "magpie.context.nativeComposition": "估算组成(占估算总量的比例)",
21187
+ "magpie.context.modelWindow": "模型窗口 {value}",
21188
+ "magpie.context.cache": "提示词缓存",
21189
+ "magpie.context.hit": "命中",
21190
+ "magpie.context.close": "关闭上下文",
21191
+ "magpie.context.composition": "上下文组成",
21192
+ "magpie.context.content": "内容",
21193
+ "magpie.context.all": "全部",
21194
+ "magpie.context.allCount": "全部 · {count}",
21195
+ "magpie.context.empty": "没有可显示的内容",
21196
+ "magpie.context.rounds": "{count} 轮",
21197
+ "magpie.context.requests": "{count} 个请求",
21198
+ "magpie.context.request": "请求 {count}",
21199
+ "magpie.context.earlierRounds": "更早的 {count} 轮",
21200
+ "magpie.context.round": "第 {count} 轮",
21137
21201
  "magpie.usage": "用量",
21138
21202
  "magpie.routing": "路由",
21139
21203
  "magpie.statTokens": "Token",
@@ -21180,8 +21244,10 @@ window.__ModuleLoader__.load({
21180
21244
  "magpie.refreshing": "正在刷新…",
21181
21245
  "magpie.update.title": "Magpie 更新",
21182
21246
  "magpie.update.open": "Magpie {version};打开更新详情",
21247
+ "magpie.update.openAvailable": "Magpie {version};发现新版本 {latest};打开更新详情",
21248
+ "magpie.update.badge": "新",
21183
21249
  "magpie.update.close": "关闭 Magpie 更新详情",
21184
- "magpie.update.description": "后台会自动观察 Magpie 的更新状态;只有你确认手动更新后,才会下载或重启。",
21250
+ "magpie.update.description": "打开管理页时会自动检查更新;只有你确认手动更新后,才会下载或重启。",
21185
21251
  "magpie.update.unavailable": "暂时无法读取 Magpie 更新状态。",
21186
21252
  "magpie.update.unsupported": "当前 Magpie 版本没有可支持的更新 API。",
21187
21253
  "magpie.update.invalid": "Magpie 返回了 CodingNS 无法安全读取的更新数据。",
@@ -21452,6 +21518,138 @@ window.__ModuleLoader__.load({
21452
21518
  "magpie.install.disabledNote": "检测到可用的 Magpie CLI 前,Magpie 管理保持关闭。"
21453
21519
  };
21454
21520
  //#endregion
21521
+ //#region src/client/locales/pluginUpdate.ts
21522
+ const en$1 = {
21523
+ "update.localeTag": "en-US",
21524
+ "update.newVersionBadge": "New",
21525
+ "update.toggleDetails": "Show or hide update details",
21526
+ "update.newVersion": "New version {version}",
21527
+ "update.title": "Plugin updates",
21528
+ "update.description": "Check npm releases and review the exact GitHub tag.",
21529
+ "update.hostVersion": "Running Host:",
21530
+ "update.clientVersion": "Running Client:",
21531
+ "update.installedVersion": "Installed package:",
21532
+ "update.unknown": "Unknown",
21533
+ "update.activationHelp": "Package installation and live code activation are reported separately. This DSH version cannot confirm a Desktop Client reload.",
21534
+ "update.channel": "Release channel",
21535
+ "update.latest": "npm latest",
21536
+ "update.next": "npm next (prerelease)",
21537
+ "update.exact": "Exact version",
21538
+ "update.exactVersion": "Exact npm version",
21539
+ "update.check": "Check for updates",
21540
+ "update.checking": "Checking npm and GitHub...",
21541
+ "update.requestError": "The request could not be completed. Retry the check or review native DSH Plugins.",
21542
+ "update.previousResult": "Previous check shown. Check again before updating.",
21543
+ "update.targetVersion": "Target version:",
21544
+ "update.publishedAt": "Published:",
21545
+ "update.releasePublishedAt": "GitHub release published:",
21546
+ "update.commit": "Source commit:",
21547
+ "update.compatibility": "DSH compatibility:",
21548
+ "update.openRelease": "Open exact GitHub release",
21549
+ "update.noNotes": "Release notes are unavailable for this exact tag.",
21550
+ "update.nativeFallback": "Use native DSH Plugins to review package status and complete any required update or restart.",
21551
+ "update.review": "Review update",
21552
+ "update.confirmTitle": "Confirm the exact package update",
21553
+ "update.confirmHelp": "Install Codingns4DSH {version} through the DSH package manager? The new Host and Client code may require a DSH restart.",
21554
+ "update.confirm": "Confirm and update",
21555
+ "update.back": "Back",
21556
+ "update.cancel": "Request cancellation",
21557
+ "update.refreshStatus": "Refresh operation status",
21558
+ "update.operationHelp": "DSH owns this operation. Closing settings does not cancel it. Cancellation is confirmed only after DSH finishes restoring the package files.",
21559
+ "update.packageState": "Package:",
21560
+ "update.hostActivation": "Host activation:",
21561
+ "update.clientActivation": "Client activation:",
21562
+ "update.checkState.up-to-date": "This channel is up to date.",
21563
+ "update.checkState.update-available": "A newer version is available.",
21564
+ "update.checkState.no-newer-version": "This channel is older than the running or installed version.",
21565
+ "update.checkState.incompatible": "This target is incompatible with the running DSH.",
21566
+ "update.checkState.compatibility-unknown": "Target compatibility could not be confirmed. Updating is blocked.",
21567
+ "update.checkState.unavailable": "Update information is unavailable.",
21568
+ "update.checkState.unsupported": "This runtime does not support checking the active version.",
21569
+ "update.compatibilityState.compatible": "Compatible",
21570
+ "update.compatibilityState.incompatible": "Incompatible",
21571
+ "update.compatibilityState.unknown": "Unknown",
21572
+ "update.phase.installing": "Installing through DSH...",
21573
+ "update.phase.cancelling": "Waiting for DSH cancellation...",
21574
+ "update.phase.applying": "DSH is applying the package...",
21575
+ "update.phase.completed": "Operation completed",
21576
+ "update.application.applied-without-desktop-restart": "Host and Client are active at the target version.",
21577
+ "update.application.restart-required": "Package installed; restart required to activate the code.",
21578
+ "update.application.activation-unknown": "Live activation could not be confirmed.",
21579
+ "update.application.failed": "The update failed. Review package status before retrying.",
21580
+ "update.application.cancelled": "DSH cancelled the update.",
21581
+ "update.application.unsupported": "Use native DSH Plugins to update this package.",
21582
+ "update.package.installed": "Installed",
21583
+ "update.package.unchanged": "Unchanged",
21584
+ "update.package.rolled-back": "Profile files restored by DSH",
21585
+ "update.package.unknown": "Unknown; review native DSH Plugins"
21586
+ };
21587
+ const zh$1 = {
21588
+ "update.localeTag": "zh-CN",
21589
+ "update.newVersionBadge": "新版本",
21590
+ "update.toggleDetails": "展开或收起更新详情",
21591
+ "update.newVersion": "新版本 {version}",
21592
+ "update.title": "插件更新",
21593
+ "update.description": "检查 npm 发布版本,并查看对应的 GitHub 标签。",
21594
+ "update.hostVersion": "运行中的 Host:",
21595
+ "update.clientVersion": "运行中的 Client:",
21596
+ "update.installedVersion": "已安装的软件包:",
21597
+ "update.unknown": "未知",
21598
+ "update.activationHelp": "软件包安装状态与运行时代码激活状态分开显示。当前 DSH 版本无法确认 Desktop Client 是否已重新加载。",
21599
+ "update.channel": "发布渠道",
21600
+ "update.latest": "npm latest(稳定版)",
21601
+ "update.next": "npm next(预发布版)",
21602
+ "update.exact": "指定版本",
21603
+ "update.exactVersion": "npm 指定版本号",
21604
+ "update.check": "检查更新",
21605
+ "update.checking": "正在检查 npm 和 GitHub……",
21606
+ "update.requestError": "请求未完成。请重试,或到 DSH 原生插件页面查看状态。",
21607
+ "update.previousResult": "显示的是上一次检查结果。更新前请重新检查。",
21608
+ "update.targetVersion": "目标版本:",
21609
+ "update.publishedAt": "npm 发布时间:",
21610
+ "update.releasePublishedAt": "GitHub 发布时间:",
21611
+ "update.commit": "源代码提交:",
21612
+ "update.compatibility": "DSH 兼容性:",
21613
+ "update.openRelease": "打开对应的 GitHub Release",
21614
+ "update.noNotes": "该精确标签没有可用的 Release notes。",
21615
+ "update.nativeFallback": "请到 DSH 原生插件页面查看软件包状态,并完成必要的更新或重启。",
21616
+ "update.review": "查看更新",
21617
+ "update.confirmTitle": "确认更新指定软件包",
21618
+ "update.confirmHelp": "通过 DSH 软件包管理器安装 Codingns4DSH {version}?新的 Host 和 Client 代码可能需要重启 DSH 才能生效。",
21619
+ "update.confirm": "确认并更新",
21620
+ "update.back": "返回",
21621
+ "update.cancel": "请求取消",
21622
+ "update.refreshStatus": "刷新操作状态",
21623
+ "update.operationHelp": "此操作由 DSH 管理。关闭设置不会取消操作;只有 DSH 完成软件包恢复后,取消才会被确认。",
21624
+ "update.packageState": "软件包状态:",
21625
+ "update.hostActivation": "Host 激活状态:",
21626
+ "update.clientActivation": "Client 激活状态:",
21627
+ "update.checkState.up-to-date": "此渠道已经是最新版本。",
21628
+ "update.checkState.update-available": "发现新版本。",
21629
+ "update.checkState.no-newer-version": "此渠道版本低于当前运行或已安装版本。",
21630
+ "update.checkState.incompatible": "此目标版本与当前 DSH 不兼容。",
21631
+ "update.checkState.compatibility-unknown": "无法确认目标版本兼容性,更新已阻止。",
21632
+ "update.checkState.unavailable": "更新信息暂不可用。",
21633
+ "update.checkState.unsupported": "当前运行环境不支持检查活动版本。",
21634
+ "update.compatibilityState.compatible": "兼容",
21635
+ "update.compatibilityState.incompatible": "不兼容",
21636
+ "update.compatibilityState.unknown": "未知",
21637
+ "update.phase.installing": "正在通过 DSH 安装……",
21638
+ "update.phase.cancelling": "正在等待 DSH 完成取消……",
21639
+ "update.phase.applying": "DSH 正在应用软件包……",
21640
+ "update.phase.completed": "操作已完成",
21641
+ "update.application.applied-without-desktop-restart": "Host 和 Client 已运行目标版本。",
21642
+ "update.application.restart-required": "软件包已安装;需要重启才能激活新代码。",
21643
+ "update.application.activation-unknown": "无法确认运行时代码是否已激活。",
21644
+ "update.application.failed": "更新失败。请先检查软件包状态再重试。",
21645
+ "update.application.cancelled": "DSH 已取消更新。",
21646
+ "update.application.unsupported": "请使用 DSH 原生插件页面更新此软件包。",
21647
+ "update.package.installed": "已安装",
21648
+ "update.package.unchanged": "未改变",
21649
+ "update.package.rolled-back": "DSH 已恢复配置文件",
21650
+ "update.package.unknown": "未知;请检查 DSH 原生插件页面"
21651
+ };
21652
+ //#endregion
21455
21653
  //#region src/client/locale.ts
21456
21654
  /** Codingns4DSH 自有词典命名空间。词典缺少的语言由 DSH 自动回退到英文。 */
21457
21655
  const CODINGNS_LOCALE_NS = "codingns";
@@ -22379,19 +22577,20 @@ window.__ModuleLoader__.load({
22379
22577
  */
22380
22578
  const en = {
22381
22579
  ...CORE_EN,
22382
- ...en$15,
22383
22580
  ...en$16,
22384
- ...en$13,
22385
22581
  ...en$17,
22582
+ ...en$14,
22583
+ ...en$18,
22584
+ ...en$12,
22386
22585
  ...en$11,
22387
- ...en$10,
22586
+ ...en$9,
22388
22587
  ...en$8,
22389
22588
  ...en$7,
22390
22589
  ...en$6,
22590
+ ...en$15,
22591
+ ...en$10,
22592
+ ...en$13,
22391
22593
  ...en$5,
22392
- ...en$14,
22393
- ...en$9,
22394
- ...en$12,
22395
22594
  ...en$4,
22396
22595
  ...en$3,
22397
22596
  ...en$2,
@@ -22399,19 +22598,20 @@ window.__ModuleLoader__.load({
22399
22598
  };
22400
22599
  const zh = {
22401
22600
  ...CORE_ZH,
22402
- ...zh$15,
22403
22601
  ...zh$16,
22404
- ...zh$13,
22405
22602
  ...zh$17,
22603
+ ...zh$14,
22604
+ ...zh$18,
22605
+ ...zh$12,
22406
22606
  ...zh$11,
22407
- ...zh$10,
22607
+ ...zh$9,
22408
22608
  ...zh$8,
22409
22609
  ...zh$7,
22410
22610
  ...zh$6,
22611
+ ...zh$15,
22612
+ ...zh$10,
22613
+ ...zh$13,
22411
22614
  ...zh$5,
22412
- ...zh$14,
22413
- ...zh$9,
22414
- ...zh$12,
22415
22615
  ...zh$4,
22416
22616
  ...zh$3,
22417
22617
  ...zh$2,
@@ -22477,7 +22677,7 @@ window.__ModuleLoader__.load({
22477
22677
  Object.defineProperty(exports, "en", {
22478
22678
  enumerable: true,
22479
22679
  get: function() {
22480
- return en$4;
22680
+ return en$5;
22481
22681
  }
22482
22682
  });
22483
22683
  Object.defineProperty(exports, "registerCodingNsLocale", {
@@ -22501,7 +22701,7 @@ window.__ModuleLoader__.load({
22501
22701
  Object.defineProperty(exports, "zh", {
22502
22702
  enumerable: true,
22503
22703
  get: function() {
22504
- return zh$4;
22704
+ return zh$5;
22505
22705
  }
22506
22706
  });
22507
22707
  return module.exports;
@@ -23221,7 +23421,7 @@ window.__ModuleLoader__.load({
23221
23421
  const MOBILE_RIGHTBAR_MANUAL_OPEN_EVENT = "codingns4dsh-mobile-rightbar-manual-open";
23222
23422
  const MOBILE_RIGHTBAR_MANUAL_CLOSE_EVENT = "codingns4dsh-mobile-rightbar-manual-close";
23223
23423
  const MOBILE_RIGHTBAR_VISIBILITY_ATTRIBUTE = "data-codingns-mobile-rightbar";
23224
- const STYLE_ID$3 = "codingns4dsh-mobile-rightbar-visibility";
23424
+ const STYLE_ID$5 = "codingns4dsh-mobile-rightbar-visibility";
23225
23425
  /** 手势确认右栏呼出后、修改宿主状态前通知显示控制器。 */
23226
23426
  function notifyMobileRightbarManualOpen(documentLike) {
23227
23427
  documentLike?.dispatchEvent?.(new Event(MOBILE_RIGHTBAR_MANUAL_OPEN_EVENT));
@@ -23243,7 +23443,7 @@ window.__ModuleLoader__.load({
23243
23443
  let session = readSession();
23244
23444
  const style = dom?.createElement?.("style");
23245
23445
  if (style !== void 0) {
23246
- style.id = STYLE_ID$3;
23446
+ style.id = STYLE_ID$5;
23247
23447
  style.textContent = `html[${MOBILE_RIGHTBAR_VISIBILITY_ATTRIBUTE}="blocked"] [data-sidebar-right-panel] { display: none !important; }`;
23248
23448
  dom?.head?.appendChild(style);
23249
23449
  }
@@ -30306,6 +30506,7 @@ window.__ModuleLoader__.load({
30306
30506
  }
30307
30507
  //#endregion
30308
30508
  //#region src/dsh-capabilities/host/session-model-selection-adapter.ts
30509
+ const NATIVE_ACCESSOR = Symbol.for("codingns4dsh.native-model-selection");
30309
30510
  function selectionOwner(controller) {
30310
30511
  const owner = controller?.agents;
30311
30512
  return typeof owner?.selectionFor === "function" ? owner : void 0;
@@ -30332,9 +30533,13 @@ window.__ModuleLoader__.load({
30332
30533
  return key === "current" ? external : Reflect.get(target, key, receiver);
30333
30534
  } });
30334
30535
  };
30536
+ Object.defineProperty(selectionFor, NATIVE_ACCESSOR, { value: {
30537
+ native: original[NATIVE_ACCESSOR]?.native ?? original,
30538
+ installed: selectionFor
30539
+ } });
30335
30540
  owner.selectionFor = selectionFor;
30336
30541
  return () => {
30337
- if (owner.selectionFor !== selectionFor) return;
30542
+ if (owner.selectionFor[NATIVE_ACCESSOR]?.installed !== selectionFor) return;
30338
30543
  if (ownDescriptor !== void 0) Object.defineProperty(owner, "selectionFor", ownDescriptor);
30339
30544
  else Reflect.deleteProperty(owner, "selectionFor");
30340
30545
  };
@@ -30565,7 +30770,7 @@ window.__ModuleLoader__.load({
30565
30770
  /** Reuse the native activity pill, dialog, localization, settings, and session binding. */
30566
30771
  function createSessionPerformancePresentation(context) {
30567
30772
  const slots = context.slots;
30568
- return { install(useAdapter, element, hooks) {
30773
+ return { install(useAdapter, element, hooks, options) {
30569
30774
  const wrappers = /* @__PURE__ */ new Set();
30570
30775
  const removeActivity = followPresentationEntry(slots, "conversation.composer.dock", (entry) => entry.options.id === "activity" && !wrappers.has(entry.component), (native) => {
30571
30776
  const Activity = native.component;
@@ -30606,7 +30811,7 @@ window.__ModuleLoader__.load({
30606
30811
  };
30607
30812
  });
30608
30813
  try {
30609
- const removeContext = installGrokContextPresentation(context, slots, useAdapter, element, hooks);
30814
+ const removeContext = installGrokContextPresentation(context, slots, useAdapter, element, hooks, options);
30610
30815
  return () => {
30611
30816
  removeContext();
30612
30817
  removeActivity();
@@ -30618,22 +30823,57 @@ window.__ModuleLoader__.load({
30618
30823
  } };
30619
30824
  }
30620
30825
  /** ContextMeter lives inside the native composer bar, rather than in its own slot. */
30621
- function installGrokContextPresentation(owner, slots, useAdapter, element, hooks) {
30622
- return installComposerPresentation(owner, slots, (Native) => function ComposerWithGrokContext(props) {
30623
- const adapter = useAdapter(props.sessionId ?? "");
30624
- return element(Native, {
30625
- ...props,
30626
- useProjection: (key, ...args) => {
30627
- const original = props.useProjection(key, ...args);
30628
- if (key === "contextBreakdown" && adapter === "grok") return void 0;
30629
- if (key !== "contextPressure") return original;
30630
- const value = props.useProjection(GROK_CONTEXT_PROJECTION);
30631
- if (adapter !== "grok") return original;
30632
- const pressure = value ?? {};
30633
- return typeof args[0] === "function" ? args[0](pressure) : pressure;
30634
- }
30635
- });
30636
- }, element, hooks);
30826
+ function installGrokContextPresentation(owner, slots, useAdapter, element, hooks, options) {
30827
+ const magpieContext = options?.magpieContext;
30828
+ const removeMagpieMeter = magpieContext === void 0 ? () => void 0 : installMagpieContextDock(slots, magpieContext, element);
30829
+ try {
30830
+ const removeComposer = installComposerPresentation(owner, slots, (Native) => function ComposerWithGrokContext(props) {
30831
+ const adapter = useAdapter(props.sessionId ?? "");
30832
+ const magpieSnapshot = magpieContext?.useSnapshot?.(magpieContext.rpc, props.sessionId) ?? null;
30833
+ const legacyMagpieReady = magpieContext?.useReady?.(magpieContext.rpc, props.sessionId) === true;
30834
+ const magpieReady = magpieSnapshot !== null || legacyMagpieReady;
30835
+ return element(Native, {
30836
+ ...props,
30837
+ useProjection: (key, ...args) => {
30838
+ const original = props.useProjection(key, ...args);
30839
+ if (key === "contextBreakdown" && (adapter === "grok" || magpieReady)) return void 0;
30840
+ if (key !== "contextPressure") return original;
30841
+ const value = props.useProjection(GROK_CONTEXT_PROJECTION);
30842
+ if (magpieSnapshot !== null) {
30843
+ const pressure = {
30844
+ pressureTokens: magpieSnapshot.usedTokens,
30845
+ contextWindow: magpieSnapshot.contextWindow
30846
+ };
30847
+ return typeof args[0] === "function" ? args[0](pressure) : pressure;
30848
+ }
30849
+ if (magpieReady) return void 0;
30850
+ if (adapter !== "grok") return original;
30851
+ const pressure = value ?? {};
30852
+ return typeof args[0] === "function" ? args[0](pressure) : pressure;
30853
+ }
30854
+ });
30855
+ }, element, hooks);
30856
+ return () => {
30857
+ removeComposer();
30858
+ removeMagpieMeter();
30859
+ };
30860
+ } catch (error) {
30861
+ removeMagpieMeter();
30862
+ throw error;
30863
+ }
30864
+ }
30865
+ /** Mount a zero-layout Client enhancer beside the native ContextMeter. */
30866
+ function installMagpieContextDock(slots, magpieContext, element) {
30867
+ return slots.inject("conversation.composer.dock", () => slots.register({
30868
+ name: "conversation.composer.dock",
30869
+ id: "codingns-magpie-context",
30870
+ order: -10,
30871
+ inject: (sessionId) => ({
30872
+ rpc: magpieContext.rpc,
30873
+ sessionId,
30874
+ ...magpieContext.locale === void 0 ? {} : { locale: magpieContext.locale }
30875
+ })
30876
+ }, (props) => element(magpieContext.component, props)));
30637
30877
  }
30638
30878
  //#endregion
30639
30879
  //#region src/dsh-capabilities/host/agent-team-adapter.ts
@@ -30868,6 +31108,123 @@ window.__ModuleLoader__.load({
30868
31108
  }
30869
31109
  }
30870
31110
  //#endregion
31111
+ //#region src/shared/contracts/plugin-update.ts
31112
+ const CODINGNS_PACKAGE_NAME = "@jingyi0605/codingns4dsh";
31113
+ const CODINGNS_NPM_REGISTRY = "https://registry.npmjs.org";
31114
+ function isSemver(value) {
31115
+ return value.length <= 128 && parseSemver(value) !== null;
31116
+ }
31117
+ function updateError(code) {
31118
+ return Object.assign(new Error(code), { code });
31119
+ }
31120
+ /** Compare two semver values without treating prerelease strings lexically. */
31121
+ function compareSemver(left, right) {
31122
+ const a = parseSemver(left);
31123
+ const b = parseSemver(right);
31124
+ if (a === null || b === null) throw new Error("Invalid semver");
31125
+ for (const key of [
31126
+ "major",
31127
+ "minor",
31128
+ "patch"
31129
+ ]) if (a[key] !== b[key]) return a[key] - b[key];
31130
+ if (a.prerelease.length === 0 && b.prerelease.length > 0) return 1;
31131
+ if (a.prerelease.length > 0 && b.prerelease.length === 0) return -1;
31132
+ for (let index = 0; index < Math.max(a.prerelease.length, b.prerelease.length); index += 1) {
31133
+ const leftPart = a.prerelease[index];
31134
+ const rightPart = b.prerelease[index];
31135
+ if (leftPart === void 0) return -1;
31136
+ if (rightPart === void 0) return 1;
31137
+ if (leftPart === rightPart) continue;
31138
+ const leftNumeric = /^\d+$/u.test(leftPart);
31139
+ if (leftNumeric !== /^\d+$/u.test(rightPart)) return leftNumeric ? -1 : 1;
31140
+ if (leftNumeric && leftPart.length !== rightPart.length) return leftPart.length - rightPart.length;
31141
+ return leftPart < rightPart ? -1 : 1;
31142
+ }
31143
+ return 0;
31144
+ }
31145
+ function parseSemver(value) {
31146
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u.exec(value);
31147
+ if (match === null || match[4]?.split(".").some((part) => /^0\d+$/u.test(part))) return null;
31148
+ if (!match.slice(1, 4).map(Number).every(Number.isSafeInteger)) return null;
31149
+ return {
31150
+ major: Number(match[1]),
31151
+ minor: Number(match[2]),
31152
+ patch: Number(match[3]),
31153
+ prerelease: match[4]?.split(".") ?? []
31154
+ };
31155
+ }
31156
+ //#endregion
31157
+ //#region src/dsh-capabilities/host/plugin-update-adapter.ts
31158
+ function readUpdateService(context, name) {
31159
+ if (typeof context !== "object" || context === null) return void 0;
31160
+ try {
31161
+ const getter = Reflect.get(context, "get");
31162
+ return typeof getter === "function" ? getter.call(context, name) : Reflect.get(context, name);
31163
+ } catch {
31164
+ return;
31165
+ }
31166
+ }
31167
+ function supportsPluginUpdateManager(context) {
31168
+ const manager = readUpdateService(context, "pluginManager");
31169
+ return typeof manager?.listBundles === "function" && typeof manager.installBundle === "function";
31170
+ }
31171
+ /** Published 0.2.1-rc.2 contract. There is no updateBundle or self-uninstall fallback. */
31172
+ function createPluginUpdateManager(context) {
31173
+ const manager = readUpdateService(context, "pluginManager");
31174
+ const policy = () => {
31175
+ const profile = readUpdateService(context, "profileContext");
31176
+ if (!profile || typeof profile.name !== "string") return "UPDATE_PROFILE_UNKNOWN";
31177
+ if (profile.name === "desktop" || profile.packageManager !== void 0 || process.versions.electron !== void 0) return "UPDATE_DESKTOP_UNSUPPORTED";
31178
+ if (readUpdateService(context, "hmr") !== void 0) return "UPDATE_NATIVE_MANAGER_REQUIRED";
31179
+ };
31180
+ return {
31181
+ async installed() {
31182
+ const bundle = (await manager.listBundles()).find((item) => item.name === CODINGNS_PACKAGE_NAME);
31183
+ const version = typeof bundle?.version === "string" && isSemver(bundle.version) ? bundle.version : null;
31184
+ const blockCode = policy() ?? (bundle?.installed !== true || bundle.availability !== "profile" ? "UPDATE_PROFILE_UNKNOWN" : version === null ? "UPDATE_INSTALLED_VERSION_UNKNOWN" : void 0);
31185
+ return {
31186
+ version,
31187
+ ...blockCode === void 0 ? {} : { blockCode }
31188
+ };
31189
+ },
31190
+ async install(version, requestId) {
31191
+ if (!isSemver(version)) throw updateError("UPDATE_INVALID_VERSION");
31192
+ const { blockCode } = await this.installed();
31193
+ if (blockCode !== void 0) throw updateError(blockCode);
31194
+ return normalizePluginManagerOutcome(await manager.installBundle(`${CODINGNS_PACKAGE_NAME}@${version}`, {
31195
+ enabled: true,
31196
+ saveExact: true,
31197
+ registry: CODINGNS_NPM_REGISTRY,
31198
+ requestId
31199
+ }), version);
31200
+ },
31201
+ cancellationAvailable: typeof manager.cancelInstall === "function",
31202
+ async cancel(requestId) {
31203
+ return manager.cancelInstall ? (await manager.cancelInstall(requestId)).status : "not-running";
31204
+ }
31205
+ };
31206
+ }
31207
+ function normalizePluginManagerOutcome(value, version) {
31208
+ const result = value;
31209
+ const application = [
31210
+ "applied",
31211
+ "restart-required",
31212
+ "overridden",
31213
+ "failed",
31214
+ "cancelled"
31215
+ ].includes(String(result?.application)) ? result.application : "unknown";
31216
+ const accepted = result?.bundle === "@jingyi0605/codingns4dsh" && result.version === version;
31217
+ const error = result?.error;
31218
+ const code = typeof error?.code === "string" && /^[a-z-]{1,64}$/u.test(error.code) ? `UPDATE_MANAGER_${error.code.toUpperCase().replaceAll("-", "_")}` : void 0;
31219
+ return {
31220
+ application,
31221
+ installedVersion: accepted ? version : null,
31222
+ packageAccepted: accepted,
31223
+ restored: result?.stage === "install" && result.changed === false && result.packageResult !== void 0 && (application === "cancelled" || application === "failed" && error?.code === "incompatible-version"),
31224
+ ...code === void 0 ? {} : { errorCode: code }
31225
+ };
31226
+ }
31227
+ //#endregion
30871
31228
  //#region src/dsh-capabilities/routes.ts
30872
31229
  /**
30873
31230
  * 注册 Codingns4DSH 当前实际消费的 DSH 服务能力。
@@ -30882,6 +31239,28 @@ window.__ModuleLoader__.load({
30882
31239
  const range020 = require_native_workspace_store.DSH_COMPATIBILITY;
30883
31240
  const add = (route) => registry.register(route);
30884
31241
  if (runtime === "host") {
31242
+ for (const [capability, id] of [["plugin.update.inspect", "plugin-manager-inspect-021"], ["plugin.update.apply", "plugin-manager-install-021"]]) add({
31243
+ id,
31244
+ capability,
31245
+ supportedDsh: ">=0.2.1-rc.2 <=0.2.1-rc.2",
31246
+ runtime,
31247
+ priority: 10,
31248
+ status: "supported",
31249
+ introducedIn: "0.2.1-rc.2",
31250
+ detect: supportsPluginUpdateManager,
31251
+ create: createPluginUpdateManager
31252
+ });
31253
+ add({
31254
+ id: "plugin-host-version-020",
31255
+ capability: "plugin.host.activation-status",
31256
+ supportedDsh: range020,
31257
+ runtime,
31258
+ priority: 10,
31259
+ status: "supported",
31260
+ introducedIn: "0.2.0-rc.2",
31261
+ detect: () => true,
31262
+ create: () => ({ version: require_native_workspace_store.CODINGNS_VERSION })
31263
+ });
30885
31264
  for (const role of ["member", "lead"]) add({
30886
31265
  id: `agent-team-external-${role}-021`,
30887
31266
  capability: `agent-team.external-${role}`,
@@ -31077,6 +31456,17 @@ window.__ModuleLoader__.load({
31077
31456
  addDsh020HostRoutes(add, range020);
31078
31457
  addPeerHostHostRoutes(add);
31079
31458
  } else {
31459
+ add({
31460
+ id: "plugin-client-reload-unavailable-020",
31461
+ capability: "plugin.client.reload-status",
31462
+ supportedDsh: range020,
31463
+ runtime,
31464
+ priority: 10,
31465
+ status: "supported",
31466
+ introducedIn: "0.2.0-rc.2",
31467
+ detect: () => false,
31468
+ create: () => void 0
31469
+ });
31080
31470
  add({
31081
31471
  id: "sidebar-panellist-main-020",
31082
31472
  capability: "sidebar.global-panel",
@@ -31742,6 +32132,482 @@ window.__ModuleLoader__.load({
31742
32132
  return readKey(context, field);
31743
32133
  }
31744
32134
  //#endregion
32135
+ //#region src/client/rpc-call.ts
32136
+ const apiRoutes = /* @__PURE__ */ new WeakMap();
32137
+ /** 只在路由确实不存在或方法不兼容时回退,普通超时不能重复提交写操作。 */
32138
+ async function callCodingNsRpcResult(rpc, endpoint, payload, signal) {
32139
+ if (apiRoutes.get(rpc)?.has(endpoint)) return rpc.call("/api", `codingns/${endpoint}`, payload, signal);
32140
+ try {
32141
+ return await rpc.call(require_transport.CODINGNS_RPC_CHANNEL, endpoint, payload, signal);
32142
+ } catch (error) {
32143
+ if (signal?.aborted || !/HTTP (?:404|405)\b/u.test(error instanceof Error ? error.message : String(error))) throw error;
32144
+ const result = await rpc.call("/api", `codingns/${endpoint}`, payload, signal);
32145
+ let routes = apiRoutes.get(rpc);
32146
+ if (routes === void 0) {
32147
+ routes = /* @__PURE__ */ new Set();
32148
+ apiRoutes.set(rpc, routes);
32149
+ }
32150
+ routes.add(endpoint);
32151
+ return result;
32152
+ }
32153
+ }
32154
+ //#endregion
32155
+ //#region src/client/magpie-context-store.ts
32156
+ const POLL_INTERVAL_MS = 3e3;
32157
+ const IDLE_STATE = { status: "idle" };
32158
+ const NATIVE_STATE = { status: "native" };
32159
+ const stores$1 = /* @__PURE__ */ new WeakMap();
32160
+ const EMPTY_STORE = {
32161
+ subscribe: () => () => void 0,
32162
+ getSnapshot: () => NATIVE_STATE,
32163
+ getServerSnapshot: () => NATIVE_STATE
32164
+ };
32165
+ var MagpieContextStore = class {
32166
+ rpc;
32167
+ sessionId;
32168
+ listeners = /* @__PURE__ */ new Set();
32169
+ state = IDLE_STATE;
32170
+ request;
32171
+ timer;
32172
+ polling = false;
32173
+ constructor(rpc, sessionId) {
32174
+ this.rpc = rpc;
32175
+ this.sessionId = sessionId;
32176
+ }
32177
+ getSnapshot = () => this.state;
32178
+ getServerSnapshot = () => IDLE_STATE;
32179
+ subscribe = (listener) => {
32180
+ this.listeners.add(listener);
32181
+ if (this.listeners.size === 1) this.load(false);
32182
+ return () => {
32183
+ this.listeners.delete(listener);
32184
+ if (this.listeners.size === 0) this.stopPolling();
32185
+ };
32186
+ };
32187
+ setPolling(enabled) {
32188
+ this.polling = enabled;
32189
+ if (!enabled) {
32190
+ this.stopPolling();
32191
+ return;
32192
+ }
32193
+ this.schedulePoll();
32194
+ }
32195
+ refresh() {
32196
+ return this.load(true);
32197
+ }
32198
+ async load(force) {
32199
+ if (this.request !== void 0) return this.request;
32200
+ if (!force && this.state.status === "ready") return;
32201
+ if (this.state.status !== "ready") this.setState({ status: "loading" });
32202
+ const request = callCodingNsRpcResult(this.rpc, "magpie/context", { sessionId: this.sessionId }).then((result) => {
32203
+ if (!result.ok) {
32204
+ if (this.state.status !== "ready") this.setState({ status: "error" });
32205
+ return;
32206
+ }
32207
+ const value = readMagpieContextSession(result.value);
32208
+ this.setState(value === null ? NATIVE_STATE : {
32209
+ status: "ready",
32210
+ value
32211
+ });
32212
+ }).catch(() => {
32213
+ if (this.state.status !== "ready") this.setState({ status: "error" });
32214
+ }).finally(() => {
32215
+ if (this.request === request) this.request = void 0;
32216
+ this.schedulePoll();
32217
+ });
32218
+ this.request = request;
32219
+ return request;
32220
+ }
32221
+ schedulePoll() {
32222
+ if (!this.polling || this.listeners.size === 0 || this.timer !== void 0) return;
32223
+ this.timer = setTimeout(() => {
32224
+ this.timer = void 0;
32225
+ this.load(true);
32226
+ }, POLL_INTERVAL_MS);
32227
+ }
32228
+ stopPolling() {
32229
+ if (this.timer !== void 0) clearTimeout(this.timer);
32230
+ this.timer = void 0;
32231
+ }
32232
+ setState(next) {
32233
+ if (sameState(this.state, next)) return;
32234
+ this.state = next;
32235
+ for (const listener of [...this.listeners]) listener();
32236
+ }
32237
+ };
32238
+ function getMagpieContextStore(rpc, sessionId) {
32239
+ const normalized = sessionId.trim();
32240
+ let bySession = stores$1.get(rpc);
32241
+ if (bySession === void 0) {
32242
+ bySession = /* @__PURE__ */ new Map();
32243
+ stores$1.set(rpc, bySession);
32244
+ }
32245
+ let store = bySession.get(normalized);
32246
+ if (store === void 0) {
32247
+ store = new MagpieContextStore(rpc, normalized);
32248
+ bySession.set(normalized, store);
32249
+ }
32250
+ return store;
32251
+ }
32252
+ function useMagpieContext(rpc, sessionId) {
32253
+ const store = rpc === void 0 || sessionId === void 0 || sessionId.trim() === "" ? EMPTY_STORE : getMagpieContextStore(rpc, sessionId);
32254
+ return (0, react.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getServerSnapshot);
32255
+ }
32256
+ function readMagpieContextSession(value) {
32257
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
32258
+ const record = value;
32259
+ return typeof record.agent === "string" && typeof record.key === "string" && typeof record.model === "string" && Number.isSafeInteger(record.usedTokens) && Number.isSafeInteger(record.contextWindow) && Array.isArray(record.parts) ? value : null;
32260
+ }
32261
+ function sameState(left, right) {
32262
+ if (left.status !== right.status) return false;
32263
+ return left.status === "ready" && right.status === "ready" ? sameContextSession(left.value, right.value) : true;
32264
+ }
32265
+ function sameContextSession(left, right) {
32266
+ if (left.agent !== right.agent || left.key !== right.key || left.title !== right.title || left.model !== right.model || left.requests !== right.requests || left.turns !== right.turns || left.usedTokens !== right.usedTokens || left.contextWindow !== right.contextWindow || left.cacheTokens !== right.cacheTokens || left.cacheRate !== right.cacheRate || left.compacts !== right.compacts || left.latestId !== right.latestId || left.parts.length !== right.parts.length || left.points.length !== right.points.length) return false;
32267
+ for (let index = 0; index < left.parts.length; index += 1) {
32268
+ const a = left.parts[index];
32269
+ const b = right.parts[index];
32270
+ if (a.kind !== b.kind || a.tokens !== b.tokens || a.items.length !== b.items.length) return false;
32271
+ for (let itemIndex = 0; itemIndex < a.items.length; itemIndex += 1) {
32272
+ const item = a.items[itemIndex];
32273
+ const other = b.items[itemIndex];
32274
+ if (item.name !== other.name || item.tag !== other.tag || item.count !== other.count || item.tokens !== other.tokens) return false;
32275
+ }
32276
+ }
32277
+ for (let index = 0; index < left.points.length; index += 1) {
32278
+ const point = left.points[index];
32279
+ const other = right.points[index];
32280
+ if (point.id !== other.id || point.time !== other.time || point.tokens !== other.tokens || point.window !== other.window || point.cacheTokens !== other.cacheTokens) return false;
32281
+ }
32282
+ return true;
32283
+ }
32284
+ //#endregion
32285
+ //#region src/client/magpie-context-meter.ts
32286
+ const STYLE_ID$4 = "codingns4dsh-magpie-context-meter";
32287
+ const COLORS = {
32288
+ system: "#8b5cf6",
32289
+ tools: "#1ea7d9",
32290
+ memory: "#f1a31a",
32291
+ files: "#20b98b",
32292
+ results: "#e13d8d",
32293
+ chat: "#4f46d8"
32294
+ };
32295
+ const PART_LABEL_KEYS = {
32296
+ system: "magpie.context.system",
32297
+ tools: "magpie.context.tools",
32298
+ memory: "magpie.context.memory",
32299
+ files: "magpie.context.files",
32300
+ results: "magpie.context.results",
32301
+ chat: "magpie.context.chat"
32302
+ };
32303
+ const PART_ORDER = [
32304
+ "system",
32305
+ "tools",
32306
+ "memory",
32307
+ "files",
32308
+ "results",
32309
+ "chat"
32310
+ ];
32311
+ const NATIVE_PARTS = [
32312
+ {
32313
+ key: "systemTokens",
32314
+ label: "magpie.context.system",
32315
+ color: "var(--dsw-static-neutral-bluish-400, #aeb3bc)"
32316
+ },
32317
+ {
32318
+ key: "toolsTokens",
32319
+ label: "magpie.context.nativeTools",
32320
+ color: "#a78bfa"
32321
+ },
32322
+ {
32323
+ key: "messageTokens",
32324
+ label: "magpie.context.nativeMessages",
32325
+ color: "var(--dsw-static-blue-450, #4b8df8)"
32326
+ }
32327
+ ];
32328
+ const FALLBACK_LOCALE$2 = {
32329
+ bind: () => require_transport.resolveCodingNsTranslator(),
32330
+ getSnapshot: () => ({
32331
+ active: "en",
32332
+ locales: [],
32333
+ revision: 0
32334
+ }),
32335
+ subscribe: () => () => void 0,
32336
+ register: () => () => void 0
32337
+ };
32338
+ /**
32339
+ * Enhance DSH's native ContextMeter without adding another visible trigger.
32340
+ * The native button receives Magpie's pressure through the composer projection;
32341
+ * this zero-layout entry only redirects its dialog to the Magpie inspector.
32342
+ */
32343
+ function MagpieContextMeter({ rpc, sessionId, locale, useSession, useProjection }) {
32344
+ const state = useMagpieContext(rpc, sessionId);
32345
+ const store = rpc === void 0 || sessionId === void 0 ? void 0 : getMagpieContextStore(rpc, sessionId);
32346
+ const running = useSession?.((value) => value.running) === true;
32347
+ const revision = useSession?.((value) => JSON.stringify([value.modelSelection, value.running]));
32348
+ const nativePressure = useProjection?.("contextPressure");
32349
+ const nativeBreakdown = useProjection?.("contextBreakdown");
32350
+ const [open, setOpen] = (0, react.useState)(false);
32351
+ const [activeKind, setActiveKind] = (0, react.useState)("all");
32352
+ const [placement, setPlacement] = (0, react.useState)({
32353
+ left: 12,
32354
+ bottom: 52
32355
+ });
32356
+ const rootRef = (0, react.useRef)(null);
32357
+ const anchorRef = (0, react.useRef)(null);
32358
+ const panelRef = (0, react.useRef)(null);
32359
+ const openRef = (0, react.useRef)(open);
32360
+ const t = require_transport.useCodingNsTranslator(locale ?? FALLBACK_LOCALE$2);
32361
+ (0, react.useEffect)(() => {
32362
+ installStyles$1();
32363
+ }, []);
32364
+ (0, react.useEffect)(() => {
32365
+ if (revision !== void 0) store?.refresh();
32366
+ }, [revision, store]);
32367
+ (0, react.useEffect)(() => {
32368
+ openRef.current = open;
32369
+ store?.setPolling(open || running || state.status === "ready");
32370
+ return () => store?.setPolling(false);
32371
+ }, [
32372
+ open,
32373
+ running,
32374
+ state.status,
32375
+ store
32376
+ ]);
32377
+ (0, react.useEffect)(() => {
32378
+ if (state.status !== "ready" && open) setOpen(false);
32379
+ }, [open, state.status]);
32380
+ const updatePlacement = (0, react.useCallback)(() => {
32381
+ if (typeof window === "undefined") return;
32382
+ const rect = anchorRef.current?.getBoundingClientRect();
32383
+ if (rect === void 0) return;
32384
+ const panelWidth = Math.min(980, Math.max(280, window.innerWidth - 24));
32385
+ const left = Math.max(12, Math.min(rect.left - Math.max(0, (panelWidth - rect.width) / 2), window.innerWidth - panelWidth - 12));
32386
+ setPlacement({
32387
+ left,
32388
+ bottom: Math.max(12, window.innerHeight - rect.top + 8)
32389
+ });
32390
+ }, []);
32391
+ (0, react.useEffect)(() => {
32392
+ if (state.status !== "ready" || typeof document === "undefined") return;
32393
+ const dock = rootRef.current?.closest("[data-composer-dock]");
32394
+ if (dock === null || dock === void 0) return;
32395
+ let attached = null;
32396
+ let nativeExpanded = null;
32397
+ const onClick = (event) => {
32398
+ event.preventDefault();
32399
+ event.stopImmediatePropagation();
32400
+ updatePlacement();
32401
+ setOpen((value) => !value);
32402
+ };
32403
+ const detach = () => {
32404
+ if (attached === null) return;
32405
+ attached.removeEventListener("click", onClick, true);
32406
+ if (nativeExpanded === null) attached.removeAttribute("aria-expanded");
32407
+ else attached.setAttribute("aria-expanded", nativeExpanded);
32408
+ if (anchorRef.current === attached) anchorRef.current = null;
32409
+ };
32410
+ const bind = () => {
32411
+ const next = findNativeContextTrigger(dock);
32412
+ if (next === attached) return;
32413
+ detach();
32414
+ attached = next;
32415
+ anchorRef.current = next;
32416
+ if (next !== null) {
32417
+ nativeExpanded = next.getAttribute("aria-expanded");
32418
+ next.setAttribute("aria-expanded", String(openRef.current));
32419
+ next.addEventListener("click", onClick, true);
32420
+ }
32421
+ if (openRef.current) updatePlacement();
32422
+ };
32423
+ bind();
32424
+ const observer = typeof MutationObserver === "undefined" ? void 0 : new MutationObserver(bind);
32425
+ observer?.observe(dock, {
32426
+ childList: true,
32427
+ subtree: true
32428
+ });
32429
+ return () => {
32430
+ observer?.disconnect();
32431
+ detach();
32432
+ };
32433
+ }, [state.status, updatePlacement]);
32434
+ (0, react.useEffect)(() => {
32435
+ if (!open) return;
32436
+ updatePlacement();
32437
+ window.addEventListener("resize", updatePlacement);
32438
+ window.addEventListener("scroll", updatePlacement, true);
32439
+ return () => {
32440
+ window.removeEventListener("resize", updatePlacement);
32441
+ window.removeEventListener("scroll", updatePlacement, true);
32442
+ };
32443
+ }, [open]);
32444
+ useDismissOnOutsidePointer(anchorRef, open, () => setOpen(false), { portal: panelRef });
32445
+ (0, react.useEffect)(() => {
32446
+ const trigger = anchorRef.current;
32447
+ if (trigger === null) return;
32448
+ trigger.setAttribute("aria-expanded", String(open));
32449
+ }, [open]);
32450
+ if (state.status !== "ready") return (0, react.createElement)("span", {
32451
+ ref: rootRef,
32452
+ "data-codingns-magpie-context-enhancer": true,
32453
+ style: hiddenEnhancerStyle
32454
+ });
32455
+ const value = state.value;
32456
+ const panel = open && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(createContextPanel(value, t, activeKind, setActiveKind, () => setOpen(false), placement, panelRef, createNativeContextSummary(nativePressure, nativeBreakdown, t)), document.body) : null;
32457
+ return (0, react.createElement)("span", {
32458
+ ref: rootRef,
32459
+ "data-codingns-magpie-context-enhancer": true,
32460
+ style: hiddenEnhancerStyle
32461
+ }, panel);
32462
+ }
32463
+ const hiddenEnhancerStyle = { display: "none" };
32464
+ function findNativeContextTrigger(dock) {
32465
+ for (const button of dock.querySelectorAll("button.JObwrW_trigger")) if (button.closest("[data-composer-dock]") === dock && button.closest("[data-codingns-magpie-context-enhancer]") === null && button.closest(".JObwrW_root") !== null) return button;
32466
+ return null;
32467
+ }
32468
+ function createNativeContextSummary(pressure, breakdown, t) {
32469
+ const used = pressure?.projectedTokens ?? pressure?.pressureTokens;
32470
+ const capacity = pressure?.contextWindow;
32471
+ if (!isTokenCount(used) || !isTokenCount(capacity) || capacity === 0) return null;
32472
+ const percent = Math.min(100, Math.round(used / capacity * 100));
32473
+ const parts = breakdown !== void 0 && NATIVE_PARTS.every((part) => isTokenCount(breakdown?.[part.key])) ? NATIVE_PARTS.map((part) => ({
32474
+ ...part,
32475
+ tokens: breakdown[part.key]
32476
+ })) : [];
32477
+ const total = parts.reduce((sum, part) => sum + part.tokens, 0);
32478
+ return (0, react.createElement)("section", {
32479
+ className: "codingns4dsh-magpie-context-native",
32480
+ "aria-label": t("magpie.context.native")
32481
+ }, (0, react.createElement)("strong", { className: "codingns4dsh-magpie-context-heading-label" }, t("magpie.context.native")), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-native-usage" }, (0, react.createElement)("span", void 0, t("magpie.context.usedPercent", { percent })), (0, react.createElement)("strong", void 0, `~${formatTokens$1(used)} / ${formatTokens$1(capacity)}`)), (0, react.createElement)("div", {
32482
+ className: "codingns4dsh-magpie-context-native-bar",
32483
+ role: "meter",
32484
+ "aria-label": t("magpie.context.used"),
32485
+ "aria-valuemin": 0,
32486
+ "aria-valuemax": 100,
32487
+ "aria-valuenow": percent
32488
+ }, total > 0 ? parts.map((part) => (0, react.createElement)("span", {
32489
+ key: part.key,
32490
+ style: {
32491
+ width: `${percent * part.tokens / total}%`,
32492
+ background: part.color
32493
+ }
32494
+ })) : (0, react.createElement)("span", { style: {
32495
+ width: `${percent}%`,
32496
+ background: require_theme.dshThemeColor.labelTertiary
32497
+ } })), parts.length > 0 && (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-caption" }, t("magpie.context.nativeComposition")), parts.length > 0 && (0, react.createElement)("dl", { className: "codingns4dsh-magpie-context-native-parts" }, parts.map((part) => (0, react.createElement)("div", { key: part.key }, (0, react.createElement)("dt", void 0, (0, react.createElement)("i", {
32498
+ "aria-hidden": true,
32499
+ style: { background: part.color }
32500
+ }), t(part.label)), (0, react.createElement)("dd", void 0, (0, react.createElement)("span", void 0, `~${formatTokens$1(part.tokens)}`), (0, react.createElement)("span", { className: "codingns4dsh-magpie-context-caption" }, `${total > 0 ? trimDecimal(part.tokens / total * 100) : "0"}%`))))));
32501
+ }
32502
+ function isTokenCount(value) {
32503
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
32504
+ }
32505
+ function createContextPanel(value, t, activeKind, setActiveKind, close, placement, panelRef, nativeSummary) {
32506
+ const used = formatTokens$1(value.usedTokens);
32507
+ const windowSize = formatTokens$1(value.contextWindow);
32508
+ const cache = `${Math.round(value.cacheRate * 100)}%`;
32509
+ const parts = PART_ORDER.map((kind) => value.parts.find((part) => part.kind === kind) ?? emptyPart(kind));
32510
+ const total = Math.max(1, parts.reduce((sum, part) => sum + part.tokens, 0));
32511
+ const contentItems = (activeKind === "all" ? parts : parts.filter((part) => part.kind === activeKind)).flatMap((part) => part.items.map((item) => ({
32512
+ ...item,
32513
+ kind: part.kind
32514
+ }))).sort((left, right) => right.tokens - left.tokens);
32515
+ const rounds = value.points.slice(-12).reverse();
32516
+ return (0, react.createElement)("div", {
32517
+ ref: panelRef,
32518
+ className: "codingns4dsh-magpie-context-panel",
32519
+ role: "dialog",
32520
+ "aria-label": t("magpie.context.window"),
32521
+ style: {
32522
+ left: placement.left,
32523
+ bottom: placement.bottom
32524
+ }
32525
+ }, nativeSummary, (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-heading" }, (0, react.createElement)("div", void 0, (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-heading-label" }, t("magpie.context.used")), (0, react.createElement)("strong", { className: "codingns4dsh-magpie-context-heading-value" }, used), (0, react.createElement)("span", { className: "codingns4dsh-magpie-context-heading-unit" }, " token"), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-caption" }, t("magpie.context.modelWindow", { value: windowSize }))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-cache" }, (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-heading-label" }, t("magpie.context.cache")), (0, react.createElement)("strong", { className: "codingns4dsh-magpie-context-cache-value" }, cache), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-caption" }, t("magpie.context.hit")), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-cache-track" }, (0, react.createElement)("span", { style: { width: `${Math.round(value.cacheRate * 100)}%` } }))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-model" }, (0, react.createElement)("span", void 0, value.model), (0, react.createElement)("button", {
32526
+ type: "button",
32527
+ onClick: close,
32528
+ "aria-label": t("magpie.context.close")
32529
+ }, "×"))), (0, react.createElement)("div", {
32530
+ className: "codingns4dsh-magpie-context-treemap",
32531
+ "aria-label": t("magpie.context.composition")
32532
+ }, parts.map((part) => (0, react.createElement)("div", {
32533
+ key: part.kind,
32534
+ className: `codingns4dsh-magpie-context-block codingns4dsh-magpie-context-block-${part.kind}`,
32535
+ style: {
32536
+ "--codingns-magpie-part-color": COLORS[part.kind],
32537
+ "--codingns-magpie-part-size": `${Math.max(4, part.tokens / total * 100)}%`,
32538
+ flex: `${Math.max(.04, part.tokens / total)} 1 0`
32539
+ }
32540
+ }, (0, react.createElement)("strong", void 0, labelFor(part.kind, t)), (0, react.createElement)("span", void 0, formatTokens$1(part.tokens))))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-legend" }, parts.map((part) => (0, react.createElement)("button", {
32541
+ key: part.kind,
32542
+ type: "button",
32543
+ className: activeKind === part.kind ? "is-active" : "",
32544
+ onClick: () => setActiveKind(activeKind === part.kind ? "all" : part.kind)
32545
+ }, (0, react.createElement)("i", { style: { background: COLORS[part.kind] } }), labelFor(part.kind, t), formatTokens$1(part.tokens)))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-content-heading" }, (0, react.createElement)("strong", void 0, t("magpie.context.content")), (0, react.createElement)("span", void 0, t("magpie.context.allCount", { count: contentItems.length }))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-tabs" }, (0, react.createElement)("button", {
32546
+ type: "button",
32547
+ className: activeKind === "all" ? "is-active" : "",
32548
+ onClick: () => setActiveKind("all")
32549
+ }, t("magpie.context.all")), parts.map((part) => (0, react.createElement)("button", {
32550
+ key: part.kind,
32551
+ type: "button",
32552
+ className: activeKind === part.kind ? "is-active" : "",
32553
+ onClick: () => setActiveKind(part.kind)
32554
+ }, labelFor(part.kind, t)))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-list" }, contentItems.length === 0 ? (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-empty" }, t("magpie.context.empty")) : contentItems.slice(0, 61).map((item, index) => (0, react.createElement)("div", {
32555
+ key: `${item.kind}-${item.name}-${index}`,
32556
+ className: "codingns4dsh-magpie-context-row"
32557
+ }, (0, react.createElement)("span", { className: "codingns4dsh-magpie-context-row-name" }, displayItemName(item.name, item.kind, item.count, t)), (0, react.createElement)("span", { className: "codingns4dsh-magpie-context-row-tag" }, item.tag ?? labelFor(item.kind, t)), (0, react.createElement)("span", { className: "codingns4dsh-magpie-context-row-bar" }, (0, react.createElement)("i", { style: {
32558
+ width: `${Math.min(100, Math.max(2, item.tokens / Math.max(1, contentItems[0].tokens) * 100))}%`,
32559
+ background: COLORS[item.kind]
32560
+ } })), (0, react.createElement)("span", { className: "codingns4dsh-magpie-context-row-value" }, formatTokens$1(item.tokens))))), (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-session" }, (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-breadcrumb" }, `${value.agent} › ${truncate(value.key)} › #${value.latestId ?? "—"}`), (0, react.createElement)("span", void 0, `${t("magpie.context.rounds", { count: value.turns })} · ${t("magpie.context.requests", { count: value.requests })}`)), rounds.length > 0 && (0, react.createElement)("div", { className: "codingns4dsh-magpie-context-rounds" }, rounds.map((point, index) => (0, react.createElement)("div", {
32561
+ key: point.id,
32562
+ className: "codingns4dsh-magpie-context-round"
32563
+ }, (0, react.createElement)("span", void 0, t("magpie.context.request", { count: value.points.length - index })), (0, react.createElement)("i", void 0, (0, react.createElement)("b", { style: { width: `${Math.min(100, point.tokens / Math.max(1, value.contextWindow) * 100)}%` } })), (0, react.createElement)("span", void 0, formatTokens$1(point.tokens))))));
32564
+ }
32565
+ function installStyles$1() {
32566
+ if (typeof document === "undefined" || document.getElementById(STYLE_ID$4) !== null) return null;
32567
+ const style = document.createElement("style");
32568
+ style.id = STYLE_ID$4;
32569
+ style.textContent = `
32570
+ .codingns4dsh-magpie-context-panel{position:fixed;z-index:10000;width:min(980px,calc(100vw - 24px));max-height:min(82vh,780px);overflow:auto;box-sizing:border-box;padding:18px 20px 12px;color:${require_theme.dshThemeColor.labelPrimary};background:${require_theme.dshThemeColor.menuBackground};border:1px solid ${require_theme.dshThemeColor.menuBorder};border-radius:14px;box-shadow:${require_theme.dshThemeColor.prominentShadow};font-size:${require_theme.uiFontSize(12)};line-height:1.35}
32571
+ .codingns4dsh-magpie-context-native{border-bottom:1px solid ${require_theme.dshThemeColor.fieldBorder};padding-bottom:14px;margin-bottom:16px}.codingns4dsh-magpie-context-native-usage{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;margin-top:7px;color:${require_theme.dshThemeColor.labelSecondary};font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-native-usage strong{margin-left:auto;color:${require_theme.dshThemeColor.labelPrimary};font-weight:500}.codingns4dsh-magpie-context-native-bar{display:flex;height:4px;overflow:hidden;margin:10px 0 12px;border-radius:99px;background:${require_theme.dshThemeColor.surfaceSubtle}}.codingns4dsh-magpie-context-native-bar span{flex:none;height:100%;border-radius:1px}.codingns4dsh-magpie-context-native-parts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px 24px;margin:8px 0 0}.codingns4dsh-magpie-context-native-parts>div{display:flex;justify-content:space-between;align-items:center;gap:8px;min-width:0}.codingns4dsh-magpie-context-native-parts dt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:${require_theme.dshThemeColor.labelSecondary}}.codingns4dsh-magpie-context-native-parts dt i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:6px}.codingns4dsh-magpie-context-native-parts dd{display:flex;gap:8px;margin:0;white-space:nowrap;font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-native-parts dd .codingns4dsh-magpie-context-caption{margin:0}
32572
+ @media (max-width:640px){.codingns4dsh-magpie-context-native-parts{grid-template-columns:minmax(0,1fr)}}
32573
+ .codingns4dsh-magpie-context-heading{display:grid;grid-template-columns:minmax(180px,1fr) minmax(160px,1fr) minmax(160px,1fr);gap:18px;align-items:start;margin-bottom:14px}.codingns4dsh-magpie-context-heading-label{color:${require_theme.dshThemeColor.labelTertiary};font-size:${require_theme.uiFontSize(12)};font-weight:600}.codingns4dsh-magpie-context-heading-value{font-size:${require_theme.uiFontSize(28)};line-height:1;font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-heading-unit{color:${require_theme.dshThemeColor.labelSecondary};margin-left:4px}.codingns4dsh-magpie-context-caption{color:${require_theme.dshThemeColor.labelTertiary};margin-top:4px}.codingns4dsh-magpie-context-cache-value{display:block;color:#6bbd99;font-size:${require_theme.uiFontSize(28)};line-height:1;font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-cache-track{height:6px;margin-top:8px;border-radius:99px;background:var(--dsw-alias-fill-tertiary,rgba(127,127,127,.12));overflow:hidden}.codingns4dsh-magpie-context-cache-track span{display:block;height:100%;background:#8bcfae;border-radius:inherit}.codingns4dsh-magpie-context-model{display:flex;justify-content:space-between;gap:8px;color:${require_theme.dshThemeColor.labelSecondary};font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-model button{border:0;background:transparent;color:${require_theme.dshThemeColor.labelTertiary};font-size:20px;line-height:18px;cursor:pointer}
32574
+ .codingns4dsh-magpie-context-treemap{display:flex;min-height:168px;gap:4px;margin:8px 0 10px}.codingns4dsh-magpie-context-block{min-width:0;display:flex;flex-direction:column;justify-content:flex-start;padding:9px 10px;border:1px solid color-mix(in srgb,var(--codingns-magpie-part-color) 25%,transparent);border-radius:8px;background:color-mix(in srgb,var(--codingns-magpie-part-color) 9%,transparent);color:var(--codingns-magpie-part-color);overflow:hidden}.codingns4dsh-magpie-context-block strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:${require_theme.uiFontSize(12)}}.codingns4dsh-magpie-context-block span{font-size:${require_theme.uiFontSize(11)};color:${require_theme.dshThemeColor.labelTertiary};font-variant-numeric:tabular-nums}
32575
+ .codingns4dsh-magpie-context-legend{display:flex;flex-wrap:wrap;gap:5px 13px;border-bottom:1px solid ${require_theme.dshThemeColor.fieldBorder};padding-bottom:10px}.codingns4dsh-magpie-context-legend button,.codingns4dsh-magpie-context-tabs button{border:0;background:transparent;color:${require_theme.dshThemeColor.labelSecondary};cursor:pointer;padding:3px 0;font-size:${require_theme.uiFontSize(11)};font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-legend button.is-active,.codingns4dsh-magpie-context-tabs button.is-active{color:${require_theme.dshThemeColor.labelPrimary};font-weight:700}.codingns4dsh-magpie-context-legend i{display:inline-block;width:8px;height:8px;margin-right:5px;border-radius:2px}
32576
+ .codingns4dsh-magpie-context-content-heading{display:flex;justify-content:space-between;align-items:center;margin-top:13px;font-size:${require_theme.uiFontSize(13)}}.codingns4dsh-magpie-context-content-heading span{color:${require_theme.dshThemeColor.labelTertiary};font-size:${require_theme.uiFontSize(11)}}.codingns4dsh-magpie-context-tabs{display:flex;gap:13px;overflow:auto;margin:8px 0 2px;border-bottom:1px solid ${require_theme.dshThemeColor.fieldBorder}}.codingns4dsh-magpie-context-list{display:flex;flex-direction:column;min-height:60px}.codingns4dsh-magpie-context-row{display:grid;grid-template-columns:minmax(90px,1.1fr) minmax(70px,.7fr) minmax(100px,1fr) 52px;gap:9px;align-items:center;min-height:27px;border-bottom:1px solid color-mix(in srgb,currentColor 7%,transparent)}.codingns4dsh-magpie-context-row-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}.codingns4dsh-magpie-context-row-tag{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:${require_theme.dshThemeColor.labelTertiary};font-size:${require_theme.uiFontSize(10)}}.codingns4dsh-magpie-context-row-bar{height:5px;border-radius:99px;background:var(--dsw-alias-fill-tertiary,rgba(127,127,127,.12));overflow:hidden}.codingns4dsh-magpie-context-row-bar i{display:block;height:100%;border-radius:inherit}.codingns4dsh-magpie-context-row-value{text-align:right;color:${require_theme.dshThemeColor.labelSecondary};font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-empty{padding:22px;text-align:center;color:${require_theme.dshThemeColor.labelTertiary}}
32577
+ .codingns4dsh-magpie-context-session{display:flex;justify-content:space-between;gap:10px;margin-top:13px;color:${require_theme.dshThemeColor.labelTertiary};font-size:${require_theme.uiFontSize(11)};font-variant-numeric:tabular-nums}.codingns4dsh-magpie-context-breadcrumb{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.codingns4dsh-magpie-context-rounds{display:flex;flex-direction:column;gap:3px;margin-top:7px}.codingns4dsh-magpie-context-round{display:grid;grid-template-columns:75px minmax(80px,1fr) 50px;gap:8px;align-items:center;color:${require_theme.dshThemeColor.labelTertiary};font-size:${require_theme.uiFontSize(10)}}.codingns4dsh-magpie-context-round i{height:4px;border-radius:99px;background:var(--dsw-alias-fill-tertiary,rgba(127,127,127,.12));overflow:hidden}.codingns4dsh-magpie-context-round b{display:block;height:100%;border-radius:inherit;background:#4f46d8}.codingns4dsh-magpie-context-round>span:last-child{text-align:right;font-variant-numeric:tabular-nums}
32578
+ @media (max-width:640px){.codingns4dsh-magpie-context-panel{padding:13px 12px 10px}.codingns4dsh-magpie-context-heading{grid-template-columns:1fr 1fr;gap:10px}.codingns4dsh-magpie-context-model{grid-column:1 / -1}.codingns4dsh-magpie-context-treemap{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:repeat(2,54px)}.codingns4dsh-magpie-context-block{flex:initial!important}.codingns4dsh-magpie-context-row{grid-template-columns:minmax(90px,1fr) minmax(90px,1fr) 52px}.codingns4dsh-magpie-context-row-tag{display:none}.codingns4dsh-magpie-context-session{display:block}.codingns4dsh-magpie-context-session>span{display:block;margin-top:3px}}
32579
+ @media (prefers-reduced-motion:reduce){.codingns4dsh-magpie-context-panel{transition:none}}
32580
+ `;
32581
+ document.head.appendChild(style);
32582
+ return null;
32583
+ }
32584
+ function formatTokens$1(value) {
32585
+ if (value < 1e3) return String(Math.round(value));
32586
+ if (value < 1e6) return `${trimDecimal(value / 1e3)}K`;
32587
+ return `${trimDecimal(value / 1e6)}M`;
32588
+ }
32589
+ function trimDecimal(value) {
32590
+ return (value >= 100 ? Math.round(value) : Math.round(value * 10) / 10).toString();
32591
+ }
32592
+ function labelFor(kind, t) {
32593
+ return t(PART_LABEL_KEYS[kind]);
32594
+ }
32595
+ function emptyPart(kind) {
32596
+ return {
32597
+ kind,
32598
+ tokens: 0,
32599
+ items: []
32600
+ };
32601
+ }
32602
+ function displayItemName(name, kind, count, t) {
32603
+ if (kind === "chat" && name === "earlier") return t("magpie.context.earlierRounds", { count: count ?? 0 });
32604
+ if (kind === "chat" && /^\d+$/u.test(name)) return t("magpie.context.round", { count: name });
32605
+ return name;
32606
+ }
32607
+ function truncate(value) {
32608
+ return value.length > 24 ? `${value.slice(0, 24)}…` : value;
32609
+ }
32610
+ //#endregion
31745
32611
  //#region src/client/peer-host-scoped-client.ts
31746
32612
  /** 根据当前 Host 自有端点生成作用域 WebSocket 工厂;不接受目标 Host URL。 */
31747
32613
  function createPeerHostWebSocketFactory(endpoint, options = {}) {
@@ -32790,7 +33656,15 @@ window.__ModuleLoader__.load({
32790
33656
  if (performance !== void 0) context.resources.add(performance.install((sessionId) => (0, react.useSyncExternalStore)(subscribeSessionAdapters, () => sessionAdapterId(sessionId), () => sessionAdapterId(sessionId)), react.createElement, {
32791
33657
  useMemo: react.useMemo,
32792
33658
  useSyncExternalStore: react.useSyncExternalStore
32793
- }));
33659
+ }, { magpieContext: {
33660
+ component: MagpieContextMeter,
33661
+ rpc: context.services.rpc,
33662
+ locale: context.services.locale,
33663
+ useSnapshot: (rpc, sessionId) => {
33664
+ const state = useMagpieContext(rpc, sessionId);
33665
+ return state.status === "ready" ? state.value : null;
33666
+ }
33667
+ } }));
32794
33668
  const { registerDelegateCommand } = await require.async("./client.delegate-command.js");
32795
33669
  context.resources.add(registerDelegateCommand(uiContext, {
32796
33670
  rpc: context.services.rpc,
@@ -33564,26 +34438,6 @@ window.__ModuleLoader__.load({
33564
34438
  } }, t("cli.thinkingLevel", { value: model.efforts.length > 0 ? model.efforts.map((effort) => model.effortLabels?.[effort] ?? effort).join(t("common.listSeparator")) : t("cli.defaultEffort") })));
33565
34439
  }
33566
34440
  //#endregion
33567
- //#region src/client/rpc-call.ts
33568
- const apiRoutes = /* @__PURE__ */ new WeakMap();
33569
- /** 只在路由确实不存在或方法不兼容时回退,普通超时不能重复提交写操作。 */
33570
- async function callCodingNsRpcResult(rpc, endpoint, payload, signal) {
33571
- if (apiRoutes.get(rpc)?.has(endpoint)) return rpc.call("/api", `codingns/${endpoint}`, payload, signal);
33572
- try {
33573
- return await rpc.call(require_transport.CODINGNS_RPC_CHANNEL, endpoint, payload, signal);
33574
- } catch (error) {
33575
- if (signal?.aborted || !/HTTP (?:404|405)\b/u.test(error instanceof Error ? error.message : String(error))) throw error;
33576
- const result = await rpc.call("/api", `codingns/${endpoint}`, payload, signal);
33577
- let routes = apiRoutes.get(rpc);
33578
- if (routes === void 0) {
33579
- routes = /* @__PURE__ */ new Set();
33580
- apiRoutes.set(rpc, routes);
33581
- }
33582
- routes.add(endpoint);
33583
- return result;
33584
- }
33585
- }
33586
- //#endregion
33587
34441
  //#region src/client/feature-requirement.ts
33588
34442
  /** Magpie 安装探测的 RPC 端点;设置卡片与模块面板共用一个探测结果。 */
33589
34443
  const MAGPIE_DETECTION_ENDPOINT = "magpie/management/detection";
@@ -35567,40 +36421,73 @@ window.__ModuleLoader__.load({
35567
36421
  loadManagement(controller.signal);
35568
36422
  return () => controller.abort();
35569
36423
  }, [loadManagement, refreshKey]);
35570
- const loadUpdates = (0, react.useCallback)(async (signal) => {
36424
+ const loadUpdates = (0, react.useCallback)(async (signal, check = false) => {
35571
36425
  setUpdateLoading(true);
35572
36426
  setUpdateError(null);
35573
36427
  try {
35574
- const [status, notes] = await Promise.all([callMagpieRpc(rpc, "update/status", {}, signal), callMagpieRpc(rpc, "update/notes", {}, signal)]);
36428
+ const status = await callMagpieRpc(rpc, "update/status", {}, signal);
35575
36429
  if (signal.aborted) return;
35576
36430
  setUpdateStatus(status);
35577
- setUpdateNotes(notes);
36431
+ if (check && ![
36432
+ "checking",
36433
+ "downloading",
36434
+ "ready"
36435
+ ].includes(status.state)) {
36436
+ const checked = await callMagpieRpc(rpc, "update/check", {}, signal);
36437
+ if (signal.aborted) return;
36438
+ setUpdateStatus(checked);
36439
+ }
35578
36440
  } catch (error) {
35579
36441
  if (signal.aborted) return;
35580
36442
  setUpdateError(magpieUpdateIssueForRpcError(error));
35581
36443
  } finally {
35582
36444
  if (!signal.aborted) setUpdateLoading(false);
35583
36445
  }
36446
+ if (signal.aborted) return;
36447
+ const notes = await callMagpieRpc(rpc, "update/notes", {}, signal).catch(() => null);
36448
+ if (!signal.aborted && notes !== null) setUpdateNotes(notes);
35584
36449
  }, [rpc]);
35585
36450
  (0, react.useEffect)(() => {
35586
36451
  const controller = new AbortController();
35587
- loadUpdates(controller.signal);
36452
+ loadUpdates(controller.signal, true);
35588
36453
  return () => controller.abort();
35589
36454
  }, [loadUpdates, refreshKey]);
36455
+ const updateState = updateStatus?.state;
36456
+ (0, react.useEffect)(() => {
36457
+ if (updateLoading || updateState !== "checking" && updateState !== "downloading") return;
36458
+ const controller = new AbortController();
36459
+ let timer;
36460
+ const poll = async () => {
36461
+ try {
36462
+ const status = await callMagpieRpc(rpc, "update/status", {}, controller.signal);
36463
+ if (controller.signal.aborted) return;
36464
+ setUpdateStatus(status);
36465
+ setUpdateError(null);
36466
+ if (status.state !== "checking" && status.state !== "downloading") return;
36467
+ } catch (error) {
36468
+ if (controller.signal.aborted) return;
36469
+ setUpdateError(magpieUpdateIssueForRpcError(error));
36470
+ }
36471
+ timer = setTimeout(() => {
36472
+ poll();
36473
+ }, 1e3);
36474
+ };
36475
+ timer = setTimeout(() => {
36476
+ poll();
36477
+ }, 1e3);
36478
+ return () => {
36479
+ controller.abort();
36480
+ clearTimeout(timer);
36481
+ };
36482
+ }, [
36483
+ rpc,
36484
+ updateLoading,
36485
+ updateState
36486
+ ]);
35590
36487
  const checkForUpdate = (0, react.useCallback)(async () => {
35591
- setUpdateLoading(true);
35592
- setUpdateError(null);
35593
36488
  setUpdateNotice("");
35594
- try {
35595
- const [status, notes] = await Promise.all([callMagpieRpc(rpc, "update/check", {}, void 0), callMagpieRpc(rpc, "update/notes", {}, void 0)]);
35596
- setUpdateStatus(status);
35597
- setUpdateNotes(notes);
35598
- } catch (error) {
35599
- setUpdateError(magpieUpdateIssueForRpcError(error));
35600
- } finally {
35601
- setUpdateLoading(false);
35602
- }
35603
- }, [rpc]);
36489
+ await loadUpdates(new AbortController().signal, true);
36490
+ }, [loadUpdates]);
35604
36491
  const installUpdate = (0, react.useCallback)(async () => {
35605
36492
  setUpdateLoading(true);
35606
36493
  setUpdateError(null);
@@ -35708,6 +36595,11 @@ window.__ModuleLoader__.load({
35708
36595
  const usageReports = pageTab === "usage";
35709
36596
  /** Provider and routing-group settings are not period-scoped, so the period filter is hidden there. */
35710
36597
  const periodScoped = pageTab === "overview" || pageTab === "usage";
36598
+ const updateAvailable = updateStatus?.latest != null && updateStatus.latest !== updateStatus.current;
36599
+ const versionLabel = updateAvailable ? t("magpie.update.openAvailable", {
36600
+ version: updateStatus.current,
36601
+ latest: updateStatus.latest
36602
+ }) : t("magpie.update.open", { version: updateStatus?.current ?? "—" });
35711
36603
  return (0, react.createElement)("div", {
35712
36604
  className: "codingns-magpie-page",
35713
36605
  role: "region",
@@ -35741,13 +36633,16 @@ window.__ModuleLoader__.load({
35741
36633
  "aria-hidden": true
35742
36634
  }, entry.icon), (0, react.createElement)("span", { className: "codingns-magpie-tab-label" }, t(entry.label))))), (0, react.createElement)("div", { className: "codingns-magpie-topbar-right" }, (0, react.createElement)("button", {
35743
36635
  type: "button",
35744
- className: "codingns-magpie-version-button",
36636
+ className: `codingns-magpie-version-button${updateAvailable ? " has-update" : ""}`,
35745
36637
  "aria-haspopup": "dialog",
35746
36638
  "aria-expanded": updateOpen,
35747
36639
  onClick: () => setUpdateOpen((value) => !value),
35748
- "aria-label": t("magpie.update.open", { version: updateStatus?.current ?? "—" }),
35749
- title: t("magpie.update.open", { version: updateStatus?.current ?? "—" })
35750
- }, updateStatus?.current ?? "—"), (0, react.createElement)("button", {
36640
+ "aria-label": versionLabel,
36641
+ title: versionLabel
36642
+ }, updateStatus?.current ?? "—", updateAvailable && (0, react.createElement)("span", {
36643
+ className: "codingns-magpie-update-badge",
36644
+ "aria-hidden": true
36645
+ }, t("magpie.update.badge"))), (0, react.createElement)("button", {
35751
36646
  type: "button",
35752
36647
  className: "codingns-magpie-icon-button",
35753
36648
  disabled: dashboardLoading || managementLoading || managementWriting,
@@ -36111,7 +37006,7 @@ window.__ModuleLoader__.load({
36111
37006
  }
36112
37007
  function RequestsPage({ page, loading, error, selectedSession, offset, onOffsetChange, onClearSession, t, append = false }) {
36113
37008
  const items = page?.items ?? [];
36114
- const aggregate = sumRequests(items);
37009
+ const aggregate = page?.aggregate === void 0 ? sumRequests(items) : requestMetricsToCardAggregate(page.aggregate);
36115
37010
  const stats = [
36116
37011
  {
36117
37012
  label: t("magpie.statTokens"),
@@ -36120,7 +37015,7 @@ window.__ModuleLoader__.load({
36120
37015
  },
36121
37016
  {
36122
37017
  label: t("magpie.statCalls"),
36123
- value: formatInteger$1(page?.total ?? aggregate.calls),
37018
+ value: formatInteger$1(page?.aggregate?.calls ?? page?.total ?? aggregate.calls),
36124
37019
  detail: `${formatInteger$1(aggregate.errors)} ${t("magpie.metricErrors")} · ${formatInteger$1(aggregate.retried)} ${t("magpie.metricRetries")}`
36125
37020
  },
36126
37021
  ...selectedSession === null ? [] : [{
@@ -36151,7 +37046,7 @@ window.__ModuleLoader__.load({
36151
37046
  size: 20,
36152
37047
  className: "codingns-magpie-provider-logo codingns-magpie-provider-logo-compact",
36153
37048
  fallback: "none"
36154
- }), selectedSession.dshSessionName ?? t("magpie.requestFor", {
37049
+ }), selectedSession.dshSessionName ?? page?.sessionName ?? t("magpie.requestFor", {
36155
37050
  agent: selectedSession.agent,
36156
37051
  id: selectedSession.id
36157
37052
  })), onClearSession !== null && (0, react.createElement)("button", {
@@ -36227,6 +37122,32 @@ window.__ModuleLoader__.load({
36227
37122
  decodeCount: speedCount === 0 ? null : speedCount
36228
37123
  };
36229
37124
  }
37125
+ function requestMetricsToCardAggregate(metrics) {
37126
+ if (metrics === null) return {
37127
+ calls: null,
37128
+ errors: null,
37129
+ retried: null,
37130
+ inputTokens: null,
37131
+ outputTokens: null,
37132
+ cost: null,
37133
+ unpriced: null,
37134
+ ttftMs: null,
37135
+ decodeTokens: null,
37136
+ decodeCount: null
37137
+ };
37138
+ return {
37139
+ calls: metrics.calls,
37140
+ errors: metrics.errors,
37141
+ retried: metrics.retried,
37142
+ inputTokens: metrics.inputTokens,
37143
+ outputTokens: metrics.outputTokens,
37144
+ cost: metrics.cost,
37145
+ unpriced: metrics.unpriced,
37146
+ ttftMs: metrics.ttftMs,
37147
+ decodeTokens: metrics.decodeTokens === null || metrics.decodeMs === null || metrics.decodeMs <= 0 ? null : metrics.decodeTokens / (metrics.decodeMs / 1e3),
37148
+ decodeCount: metrics.decodeCount
37149
+ };
37150
+ }
36230
37151
  function NativeRequestRow({ request, t }) {
36231
37152
  const speed = request.durationMs !== null && request.outputTokens !== null && request.durationMs > 0 ? `${formatValue(request.outputTokens / (request.durationMs / 1e3))} token/s` : "—";
36232
37153
  return (0, react.createElement)("tr", void 0, (0, react.createElement)("td", { className: "codingns-magpie-time-cell" }, formatTimestamp(request.time)), (0, react.createElement)("td", void 0, (0, react.createElement)("span", { className: "codingns-magpie-provider-inline" }, (0, react.createElement)(MagpieProviderLogo, {
@@ -36719,6 +37640,7 @@ window.__ModuleLoader__.load({
36719
37640
  .codingns-magpie-topbar-left{display:flex;align-items:center;justify-self:start;min-width:0;max-width:100%}
36720
37641
  .codingns-magpie-topbar-right{display:flex;align-items:center;justify-self:end;gap:8px;min-width:0}
36721
37642
  .codingns-magpie-version-button{display:inline-flex;align-items:center;min-height:30px;padding:0 9px;border:.5px solid var(--mp-line-strong);border-radius:999px;background:var(--mp-card);color:var(--mp-muted);font:inherit;font-size:${require_theme.uiFontSize(12)};font-variant-numeric:tabular-nums;cursor:pointer;transition:background .15s,color .15s,border-color .15s}.codingns-magpie-version-button:hover,.codingns-magpie-version-button[aria-expanded=true]{border-color:color-mix(in srgb,var(--mp-accent) 55%,var(--mp-line-strong));background:color-mix(in srgb,var(--mp-accent) 8%,var(--mp-card));color:var(--mp-ink)}.codingns-magpie-version-button:focus-visible{outline:2px solid color-mix(in srgb,var(--mp-accent) 55%,transparent);outline-offset:1px}
37643
+ .codingns-magpie-version-button.has-update{gap:6px;border-color:color-mix(in srgb,var(--mp-accent) 55%,var(--mp-line-strong));color:var(--mp-ink)}.codingns-magpie-update-badge{display:inline-flex;align-items:center;padding:1px 5px;border-radius:999px;background:var(--mp-accent);color:var(--dsw-alias-label-on-primary,#fff);font-size:${require_theme.uiFontSize(10)};font-weight:600;line-height:1.4}
36722
37644
  .codingns-magpie-icon-button{display:grid;place-items:center;flex:0 0 auto;width:30px;height:30px;border:0;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--mp-muted);cursor:pointer;transition:background .15s,color .15s}
36723
37645
  .codingns-magpie-icon-button:hover{background:var(--mp-hover);color:var(--mp-ink)}
36724
37646
  .codingns-magpie-icon-button:active{background:var(--mp-layer)}
@@ -37037,9 +37959,10 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
37037
37959
  * 使用的是哪个入口/版本、没检测到时该做什么。检测在 Host 执行,面板不直接
37038
37960
  * 访问文件系统,也不显示 Host 异常原文。
37039
37961
  */
37040
- function MagpieInstallPanel({ services, enabled }) {
37962
+ function MagpieInstallPanel({ services, enabled, requirement: cardRequirement }) {
37041
37963
  const t = require_transport.useCodingNsTranslator(services.locale);
37042
- const requirement = useMagpieInstallRequirement(services);
37964
+ const ownRequirement = useMagpieInstallRequirement(cardRequirement == null ? services : null);
37965
+ const requirement = cardRequirement ?? ownRequirement;
37043
37966
  const [showCustom, setShowCustom] = (0, react.useState)(false);
37044
37967
  const [customPath, setCustomPath] = (0, react.useState)("");
37045
37968
  const detection = requirement.detection;
@@ -39374,8 +40297,9 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39374
40297
  if (normalized === "") return Promise.resolve({ adapterId: "dsh" });
39375
40298
  const cache = cacheFor(rpc);
39376
40299
  const existing = cache.get(normalized);
39377
- if (existing instanceof Promise) return existing;
39378
- if (!options.force && existing !== void 0 && Date.now() - existing.loadedAt < SESSION_CONFIG_CACHE_TTL_MS) return Promise.resolve(existing.value);
40300
+ if (existing instanceof Promise) {
40301
+ if (!options.force) return existing;
40302
+ } else if (!options.force && existing !== void 0 && Date.now() - existing.loadedAt < SESSION_CONFIG_CACHE_TTL_MS) return Promise.resolve(existing.value);
39379
40303
  const request = require_magpie_model_tag.callCliRpc(rpc, "session/get", { sessionId: normalized }).then((value) => {
39380
40304
  if (cache.get(normalized) === request) cache.set(normalized, {
39381
40305
  value,
@@ -39512,6 +40436,8 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39512
40436
  const [resetPending, setResetPending] = (0, react.useState)(false);
39513
40437
  const [resetResult, setResetResult] = (0, react.useState)(null);
39514
40438
  const [resetError, setResetError] = (0, react.useState)(null);
40439
+ const sessionRef = (0, react.useRef)(void 0);
40440
+ const routeKeyRef = (0, react.useRef)(null);
39515
40441
  const modelSelectionRevision = props.useSession?.((value) => JSON.stringify([value.modelSelection, value.running]));
39516
40442
  const [adapterRevision, bumpAdapterRevision] = (0, react.useState)(0);
39517
40443
  const openRef = (0, react.useRef)(open);
@@ -39571,6 +40497,8 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39571
40497
  (0, react.useEffect)(() => {
39572
40498
  const sessionId = props.sessionId?.trim();
39573
40499
  if (!sessionId) {
40500
+ sessionRef.current = void 0;
40501
+ routeKeyRef.current = null;
39574
40502
  setEligible(false);
39575
40503
  setSnapshot(null);
39576
40504
  setAdapterId(null);
@@ -39585,18 +40513,23 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39585
40513
  }
39586
40514
  let active = true;
39587
40515
  let upstreamUnresolved = false;
39588
- setEligible(false);
39589
- setSnapshot(null);
39590
- setAdapterId(null);
39591
- setProviderId(null);
39592
- setOpen(false);
39593
- setResetOpen(false);
39594
- setResetPending(false);
39595
- setResetResult(null);
39596
- setResetError(null);
39597
- setMagpieTab("usage");
40516
+ if (sessionRef.current !== sessionId) {
40517
+ sessionRef.current = sessionId;
40518
+ routeKeyRef.current = null;
40519
+ setEligible(false);
40520
+ setSnapshot(null);
40521
+ setAdapterId(null);
40522
+ setProviderId(null);
40523
+ setOpen(false);
40524
+ setResetOpen(false);
40525
+ setResetPending(false);
40526
+ setResetResult(null);
40527
+ setResetError(null);
40528
+ setMagpieTab("usage");
40529
+ }
39598
40530
  const refresh = async (signal) => {
39599
40531
  let routeSignal;
40532
+ let routeChanged = false;
39600
40533
  setLoading(true);
39601
40534
  try {
39602
40535
  const selection = await loadCliSessionConfig(props.rpc, sessionId, { force: true });
@@ -39611,12 +40544,6 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39611
40544
  return;
39612
40545
  }
39613
40546
  if (signal.aborted) return false;
39614
- if (active) {
39615
- setEligible(true);
39616
- setAdapterId(adapterId);
39617
- setProviderId(selection.providerId ?? null);
39618
- }
39619
- const intervalMins = props.getRefreshIntervalMins?.() ?? require_native_workspace_store.DEFAULT_SUBSCRIPTION_USAGE_SETTINGS.refreshIntervalMins;
39620
40547
  const cacheKey = JSON.stringify([
39621
40548
  adapterId,
39622
40549
  selection.providerId ?? "",
@@ -39624,7 +40551,22 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39624
40551
  sessionId,
39625
40552
  selection.providerSessionId ?? ""
39626
40553
  ]);
39627
- const magpieSnapshot = snapshotRef.current?.magpie;
40554
+ routeChanged = routeKeyRef.current !== cacheKey;
40555
+ if (routeChanged) {
40556
+ routeKeyRef.current = cacheKey;
40557
+ if (active) {
40558
+ setSnapshot(null);
40559
+ setOpen(false);
40560
+ setMagpieTab("usage");
40561
+ }
40562
+ }
40563
+ if (active) {
40564
+ setEligible(true);
40565
+ setAdapterId(adapterId);
40566
+ setProviderId(selection.providerId ?? null);
40567
+ }
40568
+ const intervalMins = props.getRefreshIntervalMins?.() ?? require_native_workspace_store.DEFAULT_SUBSCRIPTION_USAGE_SETTINGS.refreshIntervalMins;
40569
+ const magpieSnapshot = routeChanged ? void 0 : snapshotRef.current?.magpie;
39628
40570
  const includeRoute = magpieSnapshot !== null && magpieSnapshot !== void 0 && (openRef.current || shouldResolveMagpieQuota(magpieSnapshot));
39629
40571
  const cached = subscriptionUsageCache.get(cacheKey);
39630
40572
  const canReuseCachedUsage = cached !== void 0 && cached.usage.providerUsage?.provider?.capability !== "new-api";
@@ -39651,8 +40593,10 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39651
40593
  } catch {
39652
40594
  if (signal.aborted || routeSignal?.aborted === true) return false;
39653
40595
  if (active) {
39654
- setEligible(false);
39655
- setSnapshot(null);
40596
+ if (routeChanged || snapshotRef.current === null) {
40597
+ setEligible(false);
40598
+ setSnapshot(null);
40599
+ }
39656
40600
  }
39657
40601
  return false;
39658
40602
  } finally {
@@ -39979,10 +40923,10 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
39979
40923
  })));
39980
40924
  }
39981
40925
  function MagpieUsagePanel({ usage, aggregateRows, sessionRows, t }) {
39982
- return (0, react.createElement)("div", void 0, (0, react.createElement)("section", { style: magpieUsageSectionStyle }, (0, react.createElement)("strong", { style: magpieSectionTitleStyle }, t("usage.magpieAggregateTitle")), usage.usageStatus === "available" ? createMagpieRows(aggregateRows) : (0, react.createElement)("div", { style: magpieMutedTextStyle }, t("usage.magpieUsageUnavailable"))), (0, react.createElement)("section", { style: magpieUsageSectionStyle }, (0, react.createElement)("strong", { style: magpieSectionTitleStyle }, t("usage.magpieSessionTitle")), usage.sessionId !== null && (0, react.createElement)("div", { style: magpieSessionIdentityStyle }, (0, react.createElement)("span", void 0, t("usage.magpieAgent", { agent: usage.agent })), usage.sessionName !== void 0 && (0, react.createElement)("strong", {
40926
+ return (0, react.createElement)("div", void 0, (0, react.createElement)("section", { style: magpieUsageSectionStyle }, (0, react.createElement)("strong", { style: magpieSectionTitleStyle }, t("usage.magpieAggregateTitle")), usage.usageStatus === "available" ? createMagpieRows(aggregateRows) : (0, react.createElement)("div", { style: magpieMutedTextStyle }, t("usage.magpieUsageUnavailable"))), (0, react.createElement)("section", { style: magpieUsageSectionStyle }, (0, react.createElement)("strong", { style: magpieSectionTitleStyle }, t(usage.sessionPeriod === "today" ? "usage.magpieSessionTodayTitle" : "usage.magpieSessionTitle")), usage.sessionId !== null && (0, react.createElement)("div", { style: magpieSessionIdentityStyle }, (0, react.createElement)("div", { style: magpieSessionNameRowStyle }, (0, react.createElement)("span", { style: { flex: "none" } }, t("usage.magpieAgent", { agent: usage.agent })), usage.sessionName !== void 0 && (0, react.createElement)("strong", {
39983
40927
  style: magpieSessionNameStyle,
39984
40928
  title: usage.sessionName
39985
- }, usage.sessionName), (0, react.createElement)("code", { style: magpieSessionIdStyle }, usage.sessionId)), usage.session === null ? (0, react.createElement)("div", { style: magpieMutedTextStyle }, usage.sessionId === null ? t("usage.magpieSessionIdUnavailable") : t("usage.magpieSessionNoUsage")) : createMagpieRows(sessionRows)));
40929
+ }, usage.sessionName)), (0, react.createElement)("code", { style: magpieSessionIdStyle }, usage.sessionId)), usage.session === null ? (0, react.createElement)("div", { style: magpieMutedTextStyle }, usage.sessionId === null ? t("usage.magpieSessionIdUnavailable") : t("usage.magpieSessionNoUsage")) : createMagpieRows(sessionRows)));
39986
40930
  }
39987
40931
  function magpieQuotaUnavailableMessage(usage, quotas, t) {
39988
40932
  return usage.quotaStatus === "unavailable" ? t("usage.magpieQuotaUnavailable") : usage.quotaStatus === "provider-unavailable" ? t("usage.magpieQuotaProviderUnavailable") : quotas.length === 0 ? t("usage.magpieQuotaNoData") : null;
@@ -40206,10 +41150,10 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
40206
41150
  function canReadMagpieSessionRequests(sessionId, agent) {
40207
41151
  return sessionId !== null && sessionId.trim() !== "" && sessionId.length <= 512 && /^[a-z0-9][a-z0-9-]*$/u.test(agent);
40208
41152
  }
40209
- /** 只读取今天的会话请求,与路由卡片和“当前 Agent 会话”用量保持同一时间口径。 */
41153
+ /** Include every date in the selected session's paginated request history. */
40210
41154
  async function readMagpieSessionRequestPage(rpc, sessionId, agent, offset, signal) {
40211
41155
  const result = await callCodingNsRpcResult(rpc, "magpie/usage/requests", {
40212
- period: "today",
41156
+ period: "all",
40213
41157
  offset,
40214
41158
  limit: 50,
40215
41159
  sessionId,
@@ -40226,6 +41170,7 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
40226
41170
  * 不再维护一套重复的请求卡片渲染。
40227
41171
  */
40228
41172
  function MagpieSessionRequestsDialog({ sessionId, sessionName, agent, page, offset, loading, error, t, onClose, dialogRef, onOffsetChange, onRetry }) {
41173
+ const displaySessionName = sessionName ?? page?.sessionName ?? null;
40229
41174
  const dialog = (0, react.createElement)("div", {
40230
41175
  className: "codingns4dsh-magpie-requests-overlay",
40231
41176
  ref: dialogRef,
@@ -40261,7 +41206,7 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
40261
41206
  selectedSession: {
40262
41207
  id: sessionId,
40263
41208
  agent,
40264
- ...sessionName === null ? {} : { dshSessionName: sessionName }
41209
+ ...displaySessionName === null ? {} : { dshSessionName: displaySessionName }
40265
41210
  },
40266
41211
  offset,
40267
41212
  onOffsetChange,
@@ -40831,6 +41776,7 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
40831
41776
  */
40832
41777
  function shouldResolveMagpieQuota(usage) {
40833
41778
  if (usage === null || usage === void 0) return false;
41779
+ if (usage.session === null) return true;
40834
41780
  if (usage.quotaStatus !== "available") return usage.upstreamProvider === null;
40835
41781
  return usage.sessionId !== null && usage.session !== null && (usage.quotas?.length ?? 0) === 0;
40836
41782
  }
@@ -41175,16 +42121,21 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
41175
42121
  overflowWrap: "anywhere"
41176
42122
  };
41177
42123
  const magpieSessionIdentityStyle = {
41178
- display: "flex",
41179
- flexWrap: "wrap",
41180
- alignItems: "baseline",
41181
- gap: "2px 10px",
42124
+ display: "grid",
42125
+ gap: 2,
41182
42126
  minWidth: 0,
41183
42127
  color: require_theme.dshThemeColor.labelSecondary,
41184
42128
  fontSize: require_theme.uiFontSize(12),
41185
42129
  lineHeight: "16px"
41186
42130
  };
42131
+ const magpieSessionNameRowStyle = {
42132
+ display: "flex",
42133
+ alignItems: "baseline",
42134
+ gap: 10,
42135
+ minWidth: 0
42136
+ };
41187
42137
  const magpieSessionNameStyle = {
42138
+ minWidth: 0,
41188
42139
  maxWidth: "100%",
41189
42140
  overflow: "hidden",
41190
42141
  color: require_theme.dshThemeColor.labelPrimary,
@@ -41194,7 +42145,6 @@ html[data-codingns-mobile-sidebar="on"] .codingns-magpie-page{padding-left:0;--m
41194
42145
  whiteSpace: "nowrap"
41195
42146
  };
41196
42147
  const magpieSessionIdStyle = {
41197
- flex: "1 1 120px",
41198
42148
  minWidth: 0,
41199
42149
  color: require_theme.dshThemeColor.labelTertiary,
41200
42150
  fontSize: require_theme.uiFontSize(10),
@@ -48561,7 +49511,7 @@ ${SCOPE} article>div:last-child>button { float:none!important; order:1; min-heig
48561
49511
  }
48562
49512
  //#endregion
48563
49513
  //#region src/client/git-panel-styles.ts
48564
- const STYLE_ID$2 = "codingns4dsh-git-panel";
49514
+ const STYLE_ID$3 = "codingns4dsh-git-panel";
48565
49515
  /**
48566
49516
  * Git 面板的交互态类名。
48567
49517
  *
@@ -48594,15 +49544,15 @@ ${SCOPE} article>div:last-child>button { float:none!important; order:1; min-heig
48594
49544
  /** 安装 Git 面板的交互态样式,重复调用只保留一份。非浏览器环境(单元测试)直接跳过。 */
48595
49545
  function installGitPanelStyles() {
48596
49546
  if (typeof document === "undefined") return () => void 0;
48597
- if (document.querySelector(`style[data-plugin-css="${STYLE_ID$2}"]`) !== null) return () => void 0;
49547
+ if (document.querySelector(`style[data-plugin-css="${STYLE_ID$3}"]`) !== null) return () => void 0;
48598
49548
  const style = document.createElement("style");
48599
49549
  style.dataset.plugin = "codingns4dsh";
48600
- style.dataset.pluginCss = STYLE_ID$2;
49550
+ style.dataset.pluginCss = STYLE_ID$3;
48601
49551
  style.textContent = gitPanelCss;
48602
49552
  document.head.appendChild(style);
48603
49553
  return () => style.remove();
48604
49554
  }
48605
- const focusRing = "outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:2px";
49555
+ const focusRing$1 = "outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:2px";
48606
49556
  const focusRingInset = "outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:-2px";
48607
49557
  const hover = "background:var(--dsw-alias-interactive-bg-hover)";
48608
49558
  const active = "background:var(--dsw-alias-interactive-bg-active)";
@@ -48622,14 +49572,14 @@ ${SCOPE} article>div:last-child>button { float:none!important; order:1; min-heig
48622
49572
  .${gitPanelClass.action}{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;padding:0;border:0;border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-secondary);background:transparent;cursor:pointer;font-size:16px;line-height:1}
48623
49573
  .${gitPanelClass.action}:hover:not(:disabled){${hover};color:var(--dsw-alias-label-primary)}
48624
49574
  .${gitPanelClass.action}:active:not(:disabled){${active}}
48625
- .${gitPanelClass.action}:focus-visible{${focusRing}}
49575
+ .${gitPanelClass.action}:focus-visible{${focusRing$1}}
48626
49576
  .${gitPanelClass.action}:disabled{${disabled}}
48627
49577
  .${gitPanelClass.actionDanger}{color:var(--dsw-alias-state-error-primary)}
48628
49578
  .${gitPanelClass.actionDanger}:hover:not(:disabled){${hover};color:var(--dsw-alias-state-error-primary)}
48629
49579
  .${gitPanelClass.button}{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);cursor:pointer}
48630
49580
  .${gitPanelClass.button}:hover:not(:disabled){${hover}}
48631
49581
  .${gitPanelClass.button}:active:not(:disabled){${active}}
48632
- .${gitPanelClass.button}:focus-visible{${focusRing}}
49582
+ .${gitPanelClass.button}:focus-visible{${focusRing$1}}
48633
49583
  .${gitPanelClass.button}:disabled{${disabled}}
48634
49584
  .${gitPanelClass.buttonPrimary}{border-color:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);background:var(--dsw-alias-button-primary-fill);font-weight:600}
48635
49585
  .${gitPanelClass.buttonPrimary}:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}
@@ -48639,7 +49589,7 @@ ${SCOPE} article>div:last-child>button { float:none!important; order:1; min-heig
48639
49589
  .${gitPanelClass.menuTrigger}{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;padding:0;border:0;border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-secondary);background:transparent;cursor:pointer;font-size:16px;line-height:1}
48640
49590
  .${gitPanelClass.menuTrigger}:hover:not(:disabled){${hover};color:var(--dsw-alias-label-primary)}
48641
49591
  .${gitPanelClass.menuTrigger}:active:not(:disabled){${active}}
48642
- .${gitPanelClass.menuTrigger}:focus-visible{${focusRing}}
49592
+ .${gitPanelClass.menuTrigger}:focus-visible{${focusRing$1}}
48643
49593
  .${gitPanelClass.menuTrigger}:disabled{${disabled}}
48644
49594
  .${gitPanelClass.menu}{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-3);box-shadow:var(--dsw-elevation-prominent)}
48645
49595
  .${gitPanelClass.menuItem}{display:block;width:100%;box-sizing:border-box;border:0;border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-primary);background:transparent;text-align:left;cursor:pointer;font-size:13px;line-height:20px;white-space:nowrap}
@@ -48651,11 +49601,11 @@ ${SCOPE} article>div:last-child>button { float:none!important; order:1; min-heig
48651
49601
  .${gitPanelClass.progress}{display:inline-block;animation:codingns4dsh-git-spin 900ms linear infinite}
48652
49602
  .${gitPanelClass.field}{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-specific-input-major);color:var(--dsw-alias-label-primary)}
48653
49603
  .${gitPanelClass.field}:hover:not(:disabled){border-color:var(--dsw-alias-border-l3)}
48654
- .${gitPanelClass.field}:focus-visible{${focusRing}}
49604
+ .${gitPanelClass.field}:focus-visible{${focusRing$1}}
48655
49605
  .${gitPanelClass.field}:disabled{${disabled}}
48656
49606
  .${gitPanelClass.select}{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-specific-input-major);color:var(--dsw-alias-label-secondary);cursor:pointer}
48657
49607
  .${gitPanelClass.select}:hover:not(:disabled){border-color:var(--dsw-alias-border-l3)}
48658
- .${gitPanelClass.select}:focus-visible{${focusRing}}
49608
+ .${gitPanelClass.select}:focus-visible{${focusRing$1}}
48659
49609
  .${gitPanelClass.select}:disabled{${disabled}}
48660
49610
  .${gitPanelClass.ref}{display:inline-flex;align-items:center;gap:4px;border-radius:999px;white-space:nowrap}
48661
49611
  .${gitPanelClass.segmented}{position:relative;display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:2px;padding:4px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover)}
@@ -73022,7 +73972,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
73022
73972
  button: "var(--dsw-alias-button-elevated-fill, #44474e)",
73023
73973
  shadow: "var(--dsw-elevation-prominent, 0 12px 36px rgba(0, 0, 0, 0.42))"
73024
73974
  };
73025
- const button = {
73975
+ const button$1 = {
73026
73976
  ...require_theme.dshSettingsButtonStyle,
73027
73977
  minHeight: 36,
73028
73978
  touchAction: "manipulation",
@@ -73226,7 +74176,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
73226
74176
  overflowY: "auto"
73227
74177
  };
73228
74178
  const topRowButton = {
73229
- ...button,
74179
+ ...button$1,
73230
74180
  height: 28,
73231
74181
  minHeight: 28,
73232
74182
  padding: "2px 10px",
@@ -73355,7 +74305,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
73355
74305
  flex: "0 0 auto"
73356
74306
  };
73357
74307
  const notificationActionButton = {
73358
- ...button,
74308
+ ...button$1,
73359
74309
  width: 28,
73360
74310
  height: 28,
73361
74311
  minHeight: 28,
@@ -78073,6 +79023,23 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78073
79023
  return value === "en" || value === "fr" || value === "de" || value === "ja" ? value : "zh";
78074
79024
  }
78075
79025
  //#endregion
79026
+ //#region src/client/features/plugin-update.ts
79027
+ const pluginUpdateFeature = {
79028
+ descriptor: {
79029
+ name: "pluginUpdate",
79030
+ version: "1.0.0",
79031
+ enabledByDefault: true,
79032
+ dependencies: [],
79033
+ runtime: "client",
79034
+ requires: [{
79035
+ capability: "plugin.client.reload-status",
79036
+ required: false,
79037
+ fallback: "degrade"
79038
+ }]
79039
+ },
79040
+ start: () => void 0
79041
+ };
79042
+ //#endregion
78076
79043
  //#region src/features/host-router.ts
78077
79044
  /** 统一管理当前 Host/PeerHost 的完整作用域和 generation。 */
78078
79045
  var HostRouter = class {
@@ -78290,6 +79257,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78290
79257
  //#region src/client/features/index.ts
78291
79258
  /** Client 侧功能模块清单:新增模块在这里登记一行,不需要改动设置页和入口。 */
78292
79259
  const CLIENT_FEATURES = [
79260
+ pluginUpdateFeature,
78293
79261
  lanAccessFeature,
78294
79262
  loginProtectionFeature,
78295
79263
  reverseProxyFeature,
@@ -78336,15 +79304,20 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78336
79304
  * DSH 真实存在的令牌(对照 `@deepseek-ai/dsh-client-ui-theme` 的 403 个
78337
79305
  * `--dsw-*`),保证明暗主题下都能跟随宿主。
78338
79306
  */
78339
- const STYLE_ID$1 = "codingns4dsh-settings-promo";
79307
+ const STYLE_ID$2 = "codingns4dsh-settings-promo";
78340
79308
  /** 推广条的元素类名;结构由组件决定,视觉由本模块的样式表决定。 */
78341
79309
  const settingsPromoClass = {
78342
79310
  root: "codingns4dsh-settings-promo",
79311
+ row: "codingns4dsh-settings-promo-row",
78343
79312
  brand: "codingns4dsh-settings-promo-brand",
78344
79313
  headline: "codingns4dsh-settings-promo-headline",
78345
79314
  logo: "codingns4dsh-settings-promo-logo",
78346
79315
  title: "codingns4dsh-settings-promo-title",
78347
79316
  version: "codingns4dsh-settings-promo-version",
79317
+ versionControl: "codingns4dsh-settings-promo-version-control",
79318
+ badgeSlot: "codingns4dsh-settings-promo-badge-slot",
79319
+ badge: "codingns4dsh-settings-promo-update-badge",
79320
+ details: "codingns4dsh-settings-promo-update-details",
78348
79321
  text: "codingns4dsh-settings-promo-text",
78349
79322
  hand: "codingns4dsh-settings-promo-hand",
78350
79323
  action: "codingns4dsh-settings-promo-action"
@@ -78357,28 +79330,37 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78357
79330
  */
78358
79331
  function installSettingsPromoStyles() {
78359
79332
  if (typeof document === "undefined") return () => void 0;
78360
- if (document.querySelector(`style[data-plugin-css="${STYLE_ID$1}"]`) !== null) return () => void 0;
79333
+ if (document.querySelector(`style[data-plugin-css="${STYLE_ID$2}"]`) !== null) return () => void 0;
78361
79334
  const style = document.createElement("style");
78362
79335
  style.dataset.plugin = "codingns4dsh";
78363
- style.dataset.pluginCss = STYLE_ID$1;
79336
+ style.dataset.pluginCss = STYLE_ID$2;
78364
79337
  style.textContent = settingsPromoCss;
78365
79338
  document.head.appendChild(style);
78366
79339
  return () => style.remove();
78367
79340
  }
79341
+ const focusRing = "outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px";
78368
79342
  const settingsPromoCss = `
78369
- .${settingsPromoClass.root}{box-sizing:border-box;display:flex;align-items:center;gap:12px;width:100%;padding:10px 14px;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft)}
79343
+ .${settingsPromoClass.root}{box-sizing:border-box;display:flex;flex-direction:column;align-items:stretch;gap:12px;width:100%;padding:10px 14px;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft)}
79344
+ .${settingsPromoClass.row}{display:flex;flex-wrap:nowrap;align-items:center;gap:12px;min-width:0;width:100%}
78370
79345
  .${settingsPromoClass.brand}{display:flex;flex-direction:column;gap:6px;flex:0 0 auto;min-width:0}
78371
79346
  .${settingsPromoClass.headline}{display:flex;align-items:center;gap:8px;min-width:0}
78372
79347
  .${settingsPromoClass.logo}{flex:0 0 auto;color:var(--dsw-alias-button-info-fill)}
78373
79348
  .${settingsPromoClass.title}{margin:0;color:var(--dsw-alias-label-primary);font-size:16px;line-height:1.25;font-weight:650;white-space:nowrap}
78374
79349
  .${settingsPromoClass.version}{align-self:flex-start;box-sizing:border-box;padding:1px 8px;border:.5px solid var(--dsw-alias-border-l2);border-radius:999px;color:var(--dsw-alias-label-secondary);background:var(--dsw-specific-input-major);font-size:11px;line-height:16px;white-space:nowrap}
79350
+ .${settingsPromoClass.versionControl}{position:relative;display:inline-flex;align-items:center;align-self:flex-start;min-width:0}
79351
+ button.${settingsPromoClass.version}{appearance:none;flex:0 1 auto;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;font-family:inherit;cursor:pointer}
79352
+ button.${settingsPromoClass.version}:hover{color:var(--dsw-alias-button-info-fill);border-color:var(--dsw-alias-button-info-fill)}
79353
+ button.${settingsPromoClass.version}:focus-visible{${focusRing}}
79354
+ .${settingsPromoClass.badgeSlot}{position:absolute;left:calc(100% + 4px);top:50%;display:inline-flex;align-items:center;width:42px;height:16px;transform:translateY(-50%);pointer-events:none}
79355
+ .${settingsPromoClass.badge}{box-sizing:border-box;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 4px;border-radius:999px;color:var(--dsw-alias-button-info-fill);background:color-mix(in srgb,var(--dsw-alias-button-info-fill) 12%,transparent);font-size:10px;line-height:14px;font-weight:600}
79356
+ .${settingsPromoClass.details}{align-self:stretch;box-sizing:border-box;width:100%;min-width:0;padding-top:12px;border-top:.5px solid var(--dsw-alias-border-l2)}
78375
79357
  .${settingsPromoClass.text}{flex:1 1 auto;min-width:0;margin:0;color:var(--dsw-alias-button-info-fill);font-size:12px;line-height:1.5;text-align:right}
78376
79358
  .${settingsPromoClass.hand}{margin-left:4px}
78377
79359
  .${settingsPromoClass.action}{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:6px;flex:0 0 auto;min-height:28px;padding:4px 12px;border:.5px solid var(--dsw-alias-button-info-fill);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-button-info-fill);background:color-mix(in srgb,var(--dsw-alias-button-info-fill) 10%,transparent);font-size:12px;line-height:1.3;font-weight:600;text-decoration:none;cursor:pointer;transition:background 160ms ease,color 160ms ease,border-color 160ms ease}
78378
79360
  .${settingsPromoClass.action}:hover{background:var(--dsw-alias-button-info-hover);border-color:var(--dsw-alias-button-info-hover);color:var(--dsw-alias-label-primary-foreground)}
78379
79361
  .${settingsPromoClass.action}:active{background:var(--dsw-alias-button-info-fill);border-color:var(--dsw-alias-button-info-fill);color:var(--dsw-alias-label-primary-foreground)}
78380
- .${settingsPromoClass.action}:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}
78381
- @media (max-width:640px){.${settingsPromoClass.root}{flex-direction:column;align-items:center;gap:10px;padding:12px}.${settingsPromoClass.brand}{align-items:center}.${settingsPromoClass.version}{align-self:center}}
79362
+ .${settingsPromoClass.action}:focus-visible{${focusRing}}
79363
+ @media (max-width:640px){.${settingsPromoClass.root}{gap:10px;padding:12px}.${settingsPromoClass.row}{flex-direction:column;align-items:center;gap:10px}.${settingsPromoClass.brand}{align-items:center}.${settingsPromoClass.version}{align-self:center}.${settingsPromoClass.versionControl}{align-self:center}.${settingsPromoClass.versionControl} button{flex-shrink:0}}
78382
79364
  @media (prefers-reduced-motion:reduce){.${settingsPromoClass.action}{transition:none}}
78383
79365
  `;
78384
79366
  //#endregion
@@ -78400,13 +79382,13 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78400
79382
  *
78401
79383
  * @param props.locale - DSH 语言服务;文案由 `codingns` 命名空间提供。
78402
79384
  */
78403
- function CodingNsSettingsPromo({ locale }) {
79385
+ function CodingNsSettingsPromo({ locale, versionControl, children }) {
78404
79386
  const t = require_transport.useCodingNsTranslator(locale);
78405
79387
  (0, react.useEffect)(() => installSettingsPromoStyles(), []);
78406
79388
  return (0, react.createElement)("aside", {
78407
79389
  className: settingsPromoClass.root,
78408
79390
  "aria-label": t("settings.promo.sectionLabel")
78409
- }, (0, react.createElement)("div", { className: settingsPromoClass.brand }, (0, react.createElement)("div", { className: settingsPromoClass.headline }, (0, react.createElement)(StarBurstIcon, { className: settingsPromoClass.logo }), (0, react.createElement)("h3", { className: settingsPromoClass.title }, t("common.brand"))), (0, react.createElement)("span", { className: settingsPromoClass.version }, t("settings.promo.version", { version: require_native_workspace_store.CODINGNS_VERSION }))), (0, react.createElement)("p", { className: settingsPromoClass.text }, t("settings.promo.starHint"), (0, react.createElement)("span", {
79391
+ }, (0, react.createElement)("div", { className: settingsPromoClass.row }, (0, react.createElement)("div", { className: settingsPromoClass.brand }, (0, react.createElement)("div", { className: settingsPromoClass.headline }, (0, react.createElement)(StarBurstIcon, { className: settingsPromoClass.logo }), (0, react.createElement)("h3", { className: settingsPromoClass.title }, t("common.brand"))), versionControl ?? (0, react.createElement)("span", { className: settingsPromoClass.version }, t("settings.promo.version", { version: "0.2.1-rc.5" }))), (0, react.createElement)("p", { className: settingsPromoClass.text }, t("settings.promo.starHint"), (0, react.createElement)("span", {
78410
79392
  className: settingsPromoClass.hand,
78411
79393
  "aria-hidden": true
78412
79394
  }, "👉")), (0, react.createElement)("a", {
@@ -78415,7 +79397,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78415
79397
  target: "_blank",
78416
79398
  rel: "noreferrer",
78417
79399
  "aria-label": t("settings.promo.actionLabel")
78418
- }, (0, react.createElement)(GitHubMarkIcon), (0, react.createElement)("span", void 0, t("settings.promo.github")), (0, react.createElement)("span", { "aria-hidden": true }, "⭐")));
79400
+ }, (0, react.createElement)(GitHubMarkIcon), (0, react.createElement)("span", void 0, t("settings.promo.github")), (0, react.createElement)("span", { "aria-hidden": true }, "⭐"))), children);
78419
79401
  }
78420
79402
  /**
78421
79403
  * 品牌标识:八芒星。
@@ -78454,13 +79436,524 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78454
79436
  }, (0, react.createElement)("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.4 7.4 0 0 1 2-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z" }));
78455
79437
  }
78456
79438
  //#endregion
79439
+ //#region src/dsh-capabilities/client/plugin-reload-adapter.ts
79440
+ /** Supported DSH Desktop releases expose no authoritative Client replacement contract. */
79441
+ function pluginClientReloadStatus() {
79442
+ return {
79443
+ state: "unsupported",
79444
+ version: require_native_workspace_store.CODINGNS_VERSION,
79445
+ code: "UPDATE_CLIENT_RELOAD_UNSUPPORTED"
79446
+ };
79447
+ }
79448
+ //#endregion
79449
+ //#region src/client/update-store.ts
79450
+ const DEFAULT_PLUGIN_UPDATE_CHANNEL = "0.2.1-rc.5".includes("-") ? "next" : "latest";
79451
+ var PluginUpdateStore = class {
79452
+ rpc;
79453
+ snapshot = {
79454
+ checking: false,
79455
+ starting: false,
79456
+ current: false,
79457
+ check: null,
79458
+ operation: null,
79459
+ runtime: null,
79460
+ error: null
79461
+ };
79462
+ listeners = /* @__PURE__ */ new Set();
79463
+ lifetime = new AbortController();
79464
+ checkRequest;
79465
+ timer;
79466
+ generation = 0;
79467
+ operationGeneration = 0;
79468
+ recoveryGeneration = 0;
79469
+ runtimeGeneration = 0;
79470
+ pollPending;
79471
+ visible = true;
79472
+ constructor(rpc) {
79473
+ this.rpc = rpc;
79474
+ }
79475
+ getSnapshot = () => this.snapshot;
79476
+ subscribe = (listener) => {
79477
+ this.listeners.add(listener);
79478
+ return () => this.listeners.delete(listener);
79479
+ };
79480
+ async loadRuntime() {
79481
+ const generation = ++this.runtimeGeneration;
79482
+ try {
79483
+ const runtime = await this.call("runtime", {});
79484
+ if (generation === this.runtimeGeneration) this.publish({ runtime });
79485
+ } catch (error) {
79486
+ if (generation === this.runtimeGeneration) this.publish({ error: errorCode(error) });
79487
+ }
79488
+ }
79489
+ invalidate() {
79490
+ this.generation++;
79491
+ this.checkRequest?.controller.abort();
79492
+ this.checkRequest = void 0;
79493
+ this.publish({
79494
+ current: false,
79495
+ checking: false
79496
+ });
79497
+ }
79498
+ check(channel) {
79499
+ const key = JSON.stringify(channel);
79500
+ if (this.checkRequest?.key === key) return this.checkRequest.promise;
79501
+ this.invalidate();
79502
+ const generation = this.generation;
79503
+ const controller = new AbortController();
79504
+ this.publish({
79505
+ checking: true,
79506
+ error: null
79507
+ });
79508
+ const promise = this.call("check", {
79509
+ channel,
79510
+ clientVersion: require_native_workspace_store.CODINGNS_VERSION
79511
+ }, controller.signal).then((check) => {
79512
+ if (generation !== this.generation) return;
79513
+ this.runtimeGeneration++;
79514
+ this.publish({
79515
+ check,
79516
+ runtime: check,
79517
+ current: true
79518
+ });
79519
+ }).catch((error) => {
79520
+ if (generation === this.generation && !controller.signal.aborted) this.publish({ error: errorCode(error) });
79521
+ }).finally(() => {
79522
+ if (generation !== this.generation) return;
79523
+ this.checkRequest = void 0;
79524
+ this.publish({ checking: false });
79525
+ });
79526
+ this.checkRequest = {
79527
+ key,
79528
+ controller,
79529
+ promise
79530
+ };
79531
+ return promise;
79532
+ }
79533
+ async apply(reviewed) {
79534
+ if (this.snapshot.starting || this.snapshot.operation?.state === "applying") return;
79535
+ if (!this.snapshot.current || reviewed !== this.snapshot.check || !reviewed.canApply || reviewed.target === null) {
79536
+ this.publish({ error: "UPDATE_CHECK_REQUIRED" });
79537
+ return;
79538
+ }
79539
+ this.operationGeneration++;
79540
+ this.publish({
79541
+ starting: true,
79542
+ error: null
79543
+ });
79544
+ let recover = false;
79545
+ try {
79546
+ const operation = await this.call("apply", {
79547
+ version: reviewed.target.version,
79548
+ confirmation: true,
79549
+ checkedAt: reviewed.checkedAt
79550
+ });
79551
+ this.publish({
79552
+ operation,
79553
+ current: false
79554
+ });
79555
+ this.schedule();
79556
+ } catch (error) {
79557
+ this.publish({
79558
+ error: errorCode(error),
79559
+ current: false
79560
+ });
79561
+ recover = true;
79562
+ } finally {
79563
+ this.publish({ starting: false });
79564
+ }
79565
+ if (recover) await this.recover();
79566
+ }
79567
+ async recover() {
79568
+ if (this.snapshot.starting) return;
79569
+ const generation = this.operationGeneration;
79570
+ const recovery = ++this.recoveryGeneration;
79571
+ try {
79572
+ const operation = await this.call("status", {});
79573
+ if (generation !== this.operationGeneration || recovery !== this.recoveryGeneration) return;
79574
+ if (this.snapshot.operation?.state === "applying" && operation === null) this.publish({ error: "UPDATE_OPERATION_NOT_FOUND" });
79575
+ else if (operation !== null) this.acceptOperation(operation);
79576
+ this.schedule();
79577
+ } catch (error) {
79578
+ if (generation === this.operationGeneration && recovery === this.recoveryGeneration) this.publish({ error: errorCode(error) });
79579
+ }
79580
+ }
79581
+ async cancel() {
79582
+ const operation = this.snapshot.operation;
79583
+ if (!operation?.cancellationAvailable || operation.state !== "applying") return;
79584
+ this.publish({
79585
+ operation: {
79586
+ ...operation,
79587
+ phase: "cancelling",
79588
+ cancellationAvailable: false
79589
+ },
79590
+ error: null
79591
+ });
79592
+ try {
79593
+ const next = await this.call("cancel", { operationId: operation.operationId });
79594
+ if (this.snapshot.operation?.operationId === operation.operationId) this.acceptOperation(next);
79595
+ } catch (error) {
79596
+ if (this.snapshot.operation?.operationId === operation.operationId && this.snapshot.operation.state !== "completed") this.publish({ error: errorCode(error) });
79597
+ }
79598
+ this.schedule();
79599
+ }
79600
+ setVisible(visible) {
79601
+ this.visible = visible;
79602
+ if (this.timer !== void 0) clearTimeout(this.timer);
79603
+ this.timer = void 0;
79604
+ if (visible) this.schedule();
79605
+ }
79606
+ dispose() {
79607
+ this.lifetime.abort();
79608
+ this.invalidate();
79609
+ if (this.timer !== void 0) clearTimeout(this.timer);
79610
+ this.listeners.clear();
79611
+ }
79612
+ schedule() {
79613
+ if (this.lifetime.signal.aborted || !this.visible || this.snapshot.error !== null || this.timer !== void 0 || this.snapshot.operation?.state !== "applying") return;
79614
+ this.timer = setTimeout(() => {
79615
+ this.timer = void 0;
79616
+ this.poll();
79617
+ }, 1e3);
79618
+ }
79619
+ poll() {
79620
+ if (this.pollPending) return this.pollPending;
79621
+ const operation = this.snapshot.operation;
79622
+ if (operation?.state !== "applying") return Promise.resolve();
79623
+ this.pollPending = this.call("status", { operationId: operation.operationId }).then((next) => {
79624
+ if (this.snapshot.operation?.operationId === next.operationId) this.acceptOperation(next);
79625
+ }).catch((error) => {
79626
+ if (this.snapshot.operation?.operationId === operation.operationId && this.snapshot.operation.state !== "completed") this.publish({ error: errorCode(error) });
79627
+ }).finally(() => {
79628
+ this.pollPending = void 0;
79629
+ this.schedule();
79630
+ });
79631
+ return this.pollPending;
79632
+ }
79633
+ async call(action, payload, signal) {
79634
+ const combined = AbortSignal.any([
79635
+ this.lifetime.signal,
79636
+ AbortSignal.timeout(3e4),
79637
+ ...signal ? [signal] : []
79638
+ ]);
79639
+ combined.throwIfAborted();
79640
+ const response = await this.rpc.call(require_transport.CODINGNS_RPC_CHANNEL, `update/${action}`, payload, combined);
79641
+ combined.throwIfAborted();
79642
+ if (!response.ok) throw updateError(response.error.code);
79643
+ return response.value;
79644
+ }
79645
+ acceptOperation(operation) {
79646
+ const current = this.snapshot.operation;
79647
+ if (current?.operationId === operation.operationId) {
79648
+ if (operation.revision < current.revision || current.state === "completed" && operation.state !== "completed") return;
79649
+ if (operation.revision === current.revision) {
79650
+ if (this.snapshot.error !== null) this.publish({ error: null });
79651
+ return;
79652
+ }
79653
+ }
79654
+ this.publish({
79655
+ operation,
79656
+ error: null
79657
+ });
79658
+ if (operation.state === "completed" && (current?.operationId !== operation.operationId || current.state !== "completed")) this.loadRuntime();
79659
+ }
79660
+ publish(patch) {
79661
+ if (this.lifetime.signal.aborted) return;
79662
+ this.snapshot = {
79663
+ ...this.snapshot,
79664
+ ...patch
79665
+ };
79666
+ for (const listener of this.listeners) listener();
79667
+ }
79668
+ };
79669
+ function errorCode(error) {
79670
+ const code = error?.code;
79671
+ return typeof code === "string" && /^UPDATE_[A-Z_]{1,80}$/u.test(code) ? code : "UPDATE_REQUEST_FAILED";
79672
+ }
79673
+ //#endregion
79674
+ //#region src/client/update-panel-styles.ts
79675
+ const STYLE_ID$1 = "codingns4dsh-update-panel";
79676
+ const updatePanelClass = {
79677
+ root: "codingns4dsh-update-panel",
79678
+ section: "codingns4dsh-update-section",
79679
+ versions: "codingns4dsh-update-versions",
79680
+ version: "codingns4dsh-update-version",
79681
+ versionLabel: "codingns4dsh-update-version-label",
79682
+ versionValue: "codingns4dsh-update-version-value",
79683
+ note: "codingns4dsh-update-note",
79684
+ warning: "codingns4dsh-update-warning",
79685
+ controls: "codingns4dsh-update-controls",
79686
+ fieldLabel: "codingns4dsh-update-field-label",
79687
+ state: "codingns4dsh-update-state",
79688
+ stateGood: "codingns4dsh-update-state-good",
79689
+ stateBad: "codingns4dsh-update-state-bad",
79690
+ target: "codingns4dsh-update-target",
79691
+ targetHeader: "codingns4dsh-update-target-header",
79692
+ targetVersion: "codingns4dsh-update-target-version",
79693
+ metadata: "codingns4dsh-update-metadata",
79694
+ metadataItem: "codingns4dsh-update-metadata-item",
79695
+ metadataLabel: "codingns4dsh-update-metadata-label",
79696
+ metadataValue: "codingns4dsh-update-metadata-value",
79697
+ notes: "codingns4dsh-update-notes",
79698
+ notesBody: "codingns4dsh-update-notes-body",
79699
+ actions: "codingns4dsh-update-actions",
79700
+ confirm: "codingns4dsh-update-confirm",
79701
+ operation: "codingns4dsh-update-operation"
79702
+ };
79703
+ function installUpdatePanelStyles() {
79704
+ if (typeof document === "undefined") return () => void 0;
79705
+ if (document.querySelector(`style[data-plugin-css="${STYLE_ID$1}"]`) !== null) return () => void 0;
79706
+ const style = document.createElement("style");
79707
+ style.dataset.plugin = "codingns4dsh";
79708
+ style.dataset.pluginCss = STYLE_ID$1;
79709
+ style.textContent = `
79710
+ .${updatePanelClass.root}{display:flex;flex-direction:column;gap:14px;color:${require_theme.dshThemeColor.labelPrimary};font-size:13px;line-height:1.45;min-width:0}
79711
+ .${updatePanelClass.section}{display:flex;flex-direction:column;gap:9px;min-width:0}
79712
+ .${updatePanelClass.versions}{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
79713
+ .${updatePanelClass.version}{display:flex;flex-direction:column;gap:3px;min-width:0;padding:8px 10px;border:1px solid ${require_theme.dshThemeColor.border};border-radius:8px;background:${require_theme.dshThemeColor.surfaceSubtle}}
79714
+ .${updatePanelClass.versionLabel},.${updatePanelClass.metadataLabel}{color:${require_theme.dshThemeColor.labelSecondary};font-size:11px;line-height:1.3}
79715
+ .${updatePanelClass.versionValue}{font-size:13px;font-weight:650;overflow-wrap:anywhere;font-family:${require_theme.dshThemeColor.codeFont}}
79716
+ .${updatePanelClass.note}{margin:0;padding:9px 11px;border-left:3px solid ${require_theme.dshThemeColor.accent};border-radius:6px;background:${require_theme.dshThemeColor.surfaceSubtle};color:${require_theme.dshThemeColor.labelSecondary};font-size:12px}
79717
+ .${updatePanelClass.warning}{margin:0;padding:9px 11px;border-left:3px solid ${require_theme.dshThemeColor.warning};border-radius:6px;background:color-mix(in srgb,${require_theme.dshThemeColor.warning} 10%,transparent);font-size:12px}
79718
+ .${updatePanelClass.controls}{display:flex;flex-direction:column;gap:6px}
79719
+ .${updatePanelClass.fieldLabel}{color:${require_theme.dshThemeColor.labelSecondary};font-size:11px;font-weight:650}
79720
+ .${updatePanelClass.state}{margin:0;padding:8px 10px;border-radius:7px;background:${require_theme.dshThemeColor.surfaceSubtle};font-weight:650}
79721
+ .${updatePanelClass.stateGood}{color:${require_theme.dshThemeColor.success};border:1px solid color-mix(in srgb,${require_theme.dshThemeColor.success} 40%,transparent)}
79722
+ .${updatePanelClass.stateBad}{color:${require_theme.dshThemeColor.error};border:1px solid color-mix(in srgb,${require_theme.dshThemeColor.error} 40%,transparent)}
79723
+ .${updatePanelClass.target}{display:flex;flex-direction:column;gap:10px;padding:11px;border:1px solid ${require_theme.dshThemeColor.border};border-radius:9px;background:${require_theme.dshThemeColor.cardBackground};box-shadow:${require_theme.dshThemeColor.subtleShadow}}
79724
+ .${updatePanelClass.targetHeader}{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0}
79725
+ .${updatePanelClass.targetVersion}{color:${require_theme.dshThemeColor.accent};font-size:16px;line-height:1.25;font-weight:750;font-family:${require_theme.dshThemeColor.codeFont};overflow-wrap:anywhere}
79726
+ .${updatePanelClass.metadata}{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 12px}
79727
+ .${updatePanelClass.metadataItem}{display:flex;flex-direction:column;gap:2px;min-width:0}
79728
+ .${updatePanelClass.metadataValue}{font-size:12px;overflow-wrap:anywhere}
79729
+ .${updatePanelClass.notes}{display:flex;flex-direction:column;gap:6px;min-width:0}
79730
+ .${updatePanelClass.notesBody}{box-sizing:border-box;max-height:280px;margin:0;padding:10px 11px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid ${require_theme.dshThemeColor.border};border-radius:7px;background:${require_theme.dshThemeColor.inputBackground};font-family:${require_theme.dshThemeColor.codeFont};font-size:12px;line-height:1.55}
79731
+ .${updatePanelClass.actions}{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
79732
+ .${updatePanelClass.confirm}{padding:11px;border:1px solid color-mix(in srgb,${require_theme.dshThemeColor.warning} 50%,${require_theme.dshThemeColor.border});border-radius:9px;background:color-mix(in srgb,${require_theme.dshThemeColor.warning} 7%,transparent)}
79733
+ .${updatePanelClass.operation}{padding:11px;border:1px solid ${require_theme.dshThemeColor.border};border-radius:9px;background:${require_theme.dshThemeColor.surfaceSubtle}}
79734
+ @media(max-width:640px){.${updatePanelClass.versions}{grid-template-columns:1fr}.${updatePanelClass.metadata}{grid-template-columns:1fr}}
79735
+ @media(prefers-reduced-motion:reduce){.codingns4dsh-update-panel *{scroll-behavior:auto}}
79736
+ `;
79737
+ document.head.appendChild(style);
79738
+ return () => style.remove();
79739
+ }
79740
+ //#endregion
79741
+ //#region src/client/update-panel.ts
79742
+ const column = {
79743
+ display: "flex",
79744
+ flexDirection: "column",
79745
+ gap: 10,
79746
+ minWidth: 0,
79747
+ overflowWrap: "anywhere"
79748
+ };
79749
+ const button = {
79750
+ ...require_theme.dshButtonStyle,
79751
+ padding: "6px 12px",
79752
+ borderRadius: 6,
79753
+ cursor: "pointer",
79754
+ alignSelf: "flex-start"
79755
+ };
79756
+ const field = {
79757
+ ...require_theme.dshFieldStyle,
79758
+ padding: "6px 10px",
79759
+ borderRadius: 6,
79760
+ width: "100%",
79761
+ boxSizing: "border-box"
79762
+ };
79763
+ function PluginUpdatePanel({ services, enabled, store }) {
79764
+ const t = require_transport.useCodingNsTranslator(services.locale);
79765
+ const snapshot = (0, react.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
79766
+ const localeTag = t("update.localeTag");
79767
+ (0, react.useEffect)(() => installUpdatePanelStyles(), []);
79768
+ const [channel, setChannel] = (0, react.useState)(DEFAULT_PLUGIN_UPDATE_CHANNEL);
79769
+ const [exactVersion, setExactVersion] = (0, react.useState)("");
79770
+ const [reviewed, setReviewed] = (0, react.useState)(null);
79771
+ const busy = snapshot.checking || snapshot.starting || snapshot.operation?.state === "applying";
79772
+ const check = snapshot.check;
79773
+ const blockCode = snapshot.runtime === null ? check?.applyBlockCode : snapshot.runtime.applyBlockCode;
79774
+ const target = check?.target;
79775
+ const operation = snapshot.operation;
79776
+ const result = operation?.result;
79777
+ const reset = () => {
79778
+ store.invalidate();
79779
+ setReviewed(null);
79780
+ };
79781
+ const formattedDate = (value) => {
79782
+ if (value === null) return t("update.unknown");
79783
+ const date = new Date(value);
79784
+ return Number.isNaN(date.valueOf()) ? t("update.unknown") : new Intl.DateTimeFormat(localeTag, {
79785
+ dateStyle: "medium",
79786
+ timeStyle: "short",
79787
+ timeZone: "UTC"
79788
+ }).format(date);
79789
+ };
79790
+ const versionCard = (key, value) => (0, react.createElement)("div", {
79791
+ key,
79792
+ className: updatePanelClass.version
79793
+ }, (0, react.createElement)("span", { className: updatePanelClass.versionLabel }, t(key)), (0, react.createElement)("strong", { className: updatePanelClass.versionValue }, value ?? t("update.unknown")));
79794
+ const metadata = (key, value, code = false) => (0, react.createElement)("div", {
79795
+ key,
79796
+ className: updatePanelClass.metadataItem
79797
+ }, (0, react.createElement)("span", { className: updatePanelClass.metadataLabel }, t(key)), (0, react.createElement)("span", {
79798
+ className: updatePanelClass.metadataValue,
79799
+ ...code ? { style: { fontFamily: require_theme.dshThemeColor.codeFont } } : {}
79800
+ }, value ?? t("update.unknown")));
79801
+ return (0, react.createElement)("div", { className: updatePanelClass.root }, (0, react.createElement)("div", { className: updatePanelClass.versions }, versionCard("update.hostVersion", snapshot.runtime?.runningHostVersion ?? check?.runningHostVersion), versionCard("update.clientVersion", require_native_workspace_store.CODINGNS_VERSION), versionCard("update.installedVersion", snapshot.runtime?.installedVersion)), (0, react.createElement)("p", { className: updatePanelClass.note }, t("update.activationHelp")), blockCode ? (0, react.createElement)("p", { className: updatePanelClass.warning }, t("update.nativeFallback"), " ", (0, react.createElement)("code", void 0, blockCode)) : null, (0, react.createElement)("div", { className: updatePanelClass.controls }, (0, react.createElement)("label", { className: updatePanelClass.fieldLabel }, t("update.channel")), (0, react.createElement)("select", {
79802
+ style: field,
79803
+ value: channel,
79804
+ disabled: !enabled || busy,
79805
+ onChange: (event) => {
79806
+ reset();
79807
+ setChannel(event.currentTarget.value);
79808
+ }
79809
+ }, (0, react.createElement)("option", { value: "latest" }, t("update.latest")), (0, react.createElement)("option", { value: "next" }, t("update.next")), (0, react.createElement)("option", { value: "exact" }, t("update.exact")))), channel === "exact" ? (0, react.createElement)("div", { className: updatePanelClass.controls }, (0, react.createElement)("label", { className: updatePanelClass.fieldLabel }, t("update.exactVersion")), (0, react.createElement)("input", {
79810
+ style: field,
79811
+ value: exactVersion,
79812
+ maxLength: 128,
79813
+ disabled: !enabled || busy,
79814
+ onChange: (event) => {
79815
+ reset();
79816
+ setExactVersion(event.currentTarget.value);
79817
+ }
79818
+ })) : null, (0, react.createElement)("div", { className: updatePanelClass.actions }, (0, react.createElement)("button", {
79819
+ type: "button",
79820
+ style: button,
79821
+ disabled: !enabled || busy || channel === "exact" && !isSemver(exactVersion),
79822
+ onClick: () => {
79823
+ setReviewed(null);
79824
+ store.check(channel === "exact" ? {
79825
+ kind: "exact",
79826
+ version: exactVersion
79827
+ } : { kind: channel });
79828
+ }
79829
+ }, t(snapshot.checking ? "update.checking" : "update.check"))), snapshot.error ? (0, react.createElement)("div", {
79830
+ role: "alert",
79831
+ className: updatePanelClass.warning
79832
+ }, t("update.requestError"), " ", snapshot.error) : null, check ? (0, react.createElement)("div", { style: column }, (0, react.createElement)("div", {
79833
+ role: "status",
79834
+ className: `${updatePanelClass.state} ${check.state === "update-available" ? updatePanelClass.stateGood : check.state === "incompatible" || check.state === "compatibility-unknown" ? updatePanelClass.stateBad : ""}`
79835
+ }, t(`update.checkState.${check.state}`)), !snapshot.current ? (0, react.createElement)("p", { className: updatePanelClass.note }, t("update.previousResult")) : null, target ? (0, react.createElement)("div", { className: updatePanelClass.target }, (0, react.createElement)("div", { className: updatePanelClass.targetHeader }, (0, react.createElement)("strong", { className: updatePanelClass.targetVersion }, `v${target.version}`), (0, react.createElement)("a", {
79836
+ href: target.release.url,
79837
+ target: "_blank",
79838
+ rel: "noreferrer",
79839
+ style: {
79840
+ ...button,
79841
+ color: require_theme.dshThemeColor.accent,
79842
+ textDecoration: "none"
79843
+ }
79844
+ }, t("update.openRelease"))), (0, react.createElement)("div", { className: updatePanelClass.metadata }, metadata("update.publishedAt", formattedDate(target.publishedAt)), metadata("update.releasePublishedAt", formattedDate(target.release.publishedAt)), metadata("update.commit", target.release.commit ?? target.gitHead, true), metadata("update.compatibility", `${t(`update.compatibilityState.${target.compatibility.state}`)}${target.compatibility.required ? ` · ${target.compatibility.required}` : ""}`)), (0, react.createElement)("div", { className: updatePanelClass.notes }, (0, react.createElement)("strong", void 0, target.release.title || target.release.tag), target.release.state === "available" ? (0, react.createElement)("pre", { className: updatePanelClass.notesBody }, target.release.body || t("update.noNotes")) : (0, react.createElement)("p", { className: updatePanelClass.note }, t("update.noNotes"), " ", target.release.reason ?? ""))) : null, (0, react.createElement)("div", { className: updatePanelClass.actions }, (0, react.createElement)("button", {
79845
+ type: "button",
79846
+ style: button,
79847
+ disabled: !enabled || busy || !snapshot.current || !check.canApply,
79848
+ onClick: () => setReviewed(check)
79849
+ }, t("update.review")))) : null, reviewed && reviewed === check && snapshot.current ? (0, react.createElement)("div", {
79850
+ role: "group",
79851
+ "aria-label": t("update.confirmTitle"),
79852
+ className: `${updatePanelClass.section} ${updatePanelClass.confirm}`
79853
+ }, (0, react.createElement)("strong", void 0, t("update.confirmTitle")), (0, react.createElement)("p", { style: { margin: 0 } }, t("update.confirmHelp", { version: reviewed.target.version })), (0, react.createElement)("div", { className: updatePanelClass.actions }, (0, react.createElement)("button", {
79854
+ type: "button",
79855
+ style: button,
79856
+ disabled: busy,
79857
+ onClick: () => {
79858
+ setReviewed(null);
79859
+ store.apply(reviewed);
79860
+ }
79861
+ }, t("update.confirm")), (0, react.createElement)("button", {
79862
+ type: "button",
79863
+ style: button,
79864
+ disabled: busy,
79865
+ onClick: () => setReviewed(null)
79866
+ }, t("update.back")))) : null, operation ? (0, react.createElement)("div", {
79867
+ role: "status",
79868
+ "aria-live": "polite",
79869
+ className: `${updatePanelClass.section} ${updatePanelClass.operation}`
79870
+ }, metadata("update.targetVersion", operation.targetVersion, true), (0, react.createElement)("div", void 0, t(`update.phase.${operation.phase}`)), operation.cancellationAvailable ? (0, react.createElement)("div", { className: updatePanelClass.actions }, (0, react.createElement)("button", {
79871
+ type: "button",
79872
+ style: button,
79873
+ onClick: () => {
79874
+ store.cancel();
79875
+ }
79876
+ }, t("update.cancel"))) : null, result ? (0, react.createElement)("div", { style: column }, (0, react.createElement)("strong", void 0, t(`update.application.${result.application}`)), metadata("update.packageState", t(`update.package.${result.packageState}`)), metadata("update.hostActivation", `${result.hostActivation.state} · ${result.hostActivation.version ?? t("update.unknown")}`), metadata("update.clientActivation", `${result.clientReload.state} · ${pluginClientReloadStatus().version}`), (0, react.createElement)("p", { style: { margin: 0 } }, t("update.nativeFallback")), result.errorCode ? (0, react.createElement)("div", void 0, result.errorCode) : null) : (0, react.createElement)("p", { style: { margin: 0 } }, t("update.operationHelp")), (0, react.createElement)("div", { className: updatePanelClass.actions }, (0, react.createElement)("button", {
79877
+ type: "button",
79878
+ style: button,
79879
+ onClick: () => {
79880
+ store.recover();
79881
+ }
79882
+ }, t("update.refreshStatus")))) : null);
79883
+ }
79884
+ //#endregion
79885
+ //#region src/client/settings-update.ts
79886
+ function hasNewerPluginVersion(snapshot) {
79887
+ const target = snapshot.check?.target;
79888
+ if (!target) return false;
79889
+ return [
79890
+ require_native_workspace_store.CODINGNS_VERSION,
79891
+ snapshot.runtime?.runningHostVersion,
79892
+ snapshot.runtime?.installedVersion
79893
+ ].filter((version) => typeof version === "string" && isSemver(version)).every((version) => compareSemver(target.version, version) > 0);
79894
+ }
79895
+ function CodingNsSettingsUpdate({ services }) {
79896
+ const t = require_transport.useCodingNsTranslator(services.locale);
79897
+ const store = (0, react.useMemo)(() => new PluginUpdateStore(services.rpc), [services.rpc]);
79898
+ const snapshot = (0, react.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
79899
+ const [open, setOpen] = (0, react.useState)(false);
79900
+ const [hasOpened, setHasOpened] = (0, react.useState)(false);
79901
+ const detailsId = (0, react.useId)();
79902
+ (0, react.useEffect)(() => {
79903
+ store.loadRuntime();
79904
+ store.recover();
79905
+ let checked = false;
79906
+ const visibility = () => {
79907
+ const visible = typeof document === "undefined" || document.visibilityState !== "hidden";
79908
+ store.setVisible(visible);
79909
+ if (visible && !checked) {
79910
+ checked = true;
79911
+ store.check({ kind: DEFAULT_PLUGIN_UPDATE_CHANNEL });
79912
+ }
79913
+ };
79914
+ visibility();
79915
+ if (typeof document !== "undefined") document.addEventListener("visibilitychange", visibility);
79916
+ return () => {
79917
+ if (typeof document !== "undefined") document.removeEventListener("visibilitychange", visibility);
79918
+ store.dispose();
79919
+ };
79920
+ }, [store]);
79921
+ const versionControl = (0, react.createElement)("div", { className: settingsPromoClass.versionControl }, (0, react.createElement)("button", {
79922
+ type: "button",
79923
+ className: settingsPromoClass.version,
79924
+ "aria-expanded": open,
79925
+ "aria-controls": detailsId,
79926
+ title: t("update.toggleDetails"),
79927
+ onClick: () => {
79928
+ setOpen(!open);
79929
+ setHasOpened(true);
79930
+ }
79931
+ }, t("settings.promo.version", { version: require_native_workspace_store.CODINGNS_VERSION })), (0, react.createElement)("span", { className: settingsPromoClass.badgeSlot }, hasNewerPluginVersion(snapshot) ? (0, react.createElement)("span", {
79932
+ className: settingsPromoClass.badge,
79933
+ role: "status",
79934
+ title: t("update.newVersion", { version: snapshot.check.target.version }),
79935
+ "aria-label": t("update.newVersion", { version: snapshot.check.target.version })
79936
+ }, t("update.newVersionBadge")) : null));
79937
+ return (0, react.createElement)(CodingNsSettingsPromo, {
79938
+ locale: services.locale,
79939
+ versionControl
79940
+ }, (0, react.createElement)("div", {
79941
+ id: detailsId,
79942
+ hidden: !open,
79943
+ className: settingsPromoClass.details
79944
+ }, hasOpened ? (0, react.createElement)(PluginUpdatePanel, {
79945
+ services,
79946
+ enabled: true,
79947
+ store
79948
+ }) : null));
79949
+ }
79950
+ //#endregion
78457
79951
  //#region src/client/settings-section.ts
78458
79952
  /**
78459
79953
  * DSH 设置页中的 Codingns4DSH 区块。
78460
79954
  *
78461
- * 它只做一件事:遍历注册表中带界面描述的模块并渲染卡片。卡片内容来自模块
78462
- * 自己的 settingsPanel,所以新增模块不会在这里产生分支。页面最上方是
78463
- * GitHub Star 推广条({@link CodingNsSettingsPromo}),属于纯展示内容。
79955
+ * Module cards come from the registry. The header combines the existing brand
79956
+ * banner with a version disclosure for update details.
78464
79957
  */
78465
79958
  function CodingNsSettingsSection({ settings, registry, services, restartStates = {} }) {
78466
79959
  const store = (0, react.useMemo)(() => settingsSnapshotHandle(settings), [settings]);
@@ -78480,7 +79973,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78480
79973
  ...require_theme.dshSettingsToastStyle,
78481
79974
  borderColor: toast.kind === "error" ? require_theme.dshThemeColor.error : toast.kind === "success" ? require_theme.dshThemeColor.success : require_theme.dshThemeColor.border
78482
79975
  }
78483
- }, toast.message), (0, react.createElement)(CodingNsSettingsPromo, { locale: services.locale }), (0, react.createElement)("header", { style: require_theme.dshSettingsHeaderStyle }, (0, react.createElement)("p", { style: require_theme.dshSettingsSubtitleStyle }, t("settings.subtitle"))), (0, react.createElement)("div", { style: {
79976
+ }, toast.message), (0, react.createElement)(CodingNsSettingsUpdate, { services }), (0, react.createElement)("header", { style: require_theme.dshSettingsHeaderStyle }, (0, react.createElement)("p", { style: require_theme.dshSettingsSubtitleStyle }, t("settings.subtitle"))), (0, react.createElement)("div", { style: {
78484
79977
  display: "flex",
78485
79978
  flexDirection: "column",
78486
79979
  gap: 12
@@ -78547,7 +80040,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78547
80040
  const needsRequirement = ui.requirementKey !== void 0;
78548
80041
  const installedRequirement = useMagpieInstallRequirement(needsRequirement ? services : null);
78549
80042
  const requirement = needsRequirement ? installedRequirement : null;
78550
- const requirementBlocked = requirement !== null && requirement.state === "missing";
80043
+ const requirementBlocked = !enabled && requirement !== null && requirement.state !== "ready";
78551
80044
  const switchDisabled = temporarilyDisabled || ui.alwaysEnabled === true || !versionCompatible || snapshot.status === "loading" || !snapshot.writable || requirementBlocked;
78552
80045
  const toggle = (next) => {
78553
80046
  if (requirementBlocked) {
@@ -78651,7 +80144,8 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
78651
80144
  services,
78652
80145
  enabled,
78653
80146
  snapshot,
78654
- notify
80147
+ notify,
80148
+ requirement
78655
80149
  })));
78656
80150
  }
78657
80151
  /** 标题栏开关:真实 checkbox 语义,点击不会连带折叠卡片。 */
@@ -84361,7 +85855,7 @@ button[${ACCOUNT_ATTRIBUTE}]:focus-visible{outline:2px solid ${require_theme.dsh
84361
85855
  function isInjectedStage0Runtime(scope = globalThis) {
84362
85856
  return scope[CODINGNS_STAGE0_GLOBAL] === true;
84363
85857
  }
84364
- route("session.external-performance", "session-performance-projection-021", "host", ">=0.2.1-alpha.3 <=0.2.1-rc.3", "supported", ["dsh-capabilities/host/session-performance-adapter.ts", "host/cli-adapters/feature.ts"]), route("session.external-performance", "session-performance-presentation-021", "client", ">=0.2.1-alpha.3 <=0.2.1-rc.3", "supported", ["dsh-capabilities/client/session-performance-adapter.ts", "client/features/cli-adapters.ts"]), route("quick-app.proxy", "quick-app-host-proxy-021", "host", require_native_workspace_store.DSH_COMPATIBILITY, "supported", [
85858
+ route("plugin.update.inspect", "plugin-manager-inspect-021", "host", ">=0.2.1-rc.2 <=0.2.1-rc.2", "supported", ["dsh-capabilities/host/plugin-update-adapter.ts", "host/features/plugin-update.ts"]), route("plugin.update.apply", "plugin-manager-install-021", "host", ">=0.2.1-rc.2 <=0.2.1-rc.2", "supported", ["dsh-capabilities/host/plugin-update-adapter.ts", "host/update/service.ts"]), route("plugin.host.activation-status", "plugin-host-version-020", "host", require_native_workspace_store.DSH_COMPATIBILITY, "supported", ["host/update/service.ts"]), route("plugin.client.reload-status", "plugin-client-reload-unavailable-020", "client", require_native_workspace_store.DSH_COMPATIBILITY, "supported", ["dsh-capabilities/client/plugin-reload-adapter.ts", "client/update-panel.ts"]), route("session.external-performance", "session-performance-projection-021", "host", ">=0.2.1-alpha.3 <=0.2.1-rc.3", "supported", ["dsh-capabilities/host/session-performance-adapter.ts", "host/cli-adapters/feature.ts"]), route("session.external-performance", "session-performance-presentation-021", "client", ">=0.2.1-alpha.3 <=0.2.1-rc.3", "supported", ["dsh-capabilities/client/session-performance-adapter.ts", "client/features/cli-adapters.ts"]), route("quick-app.proxy", "quick-app-host-proxy-021", "host", require_native_workspace_store.DSH_COMPATIBILITY, "supported", [
84365
85859
  "dsh-capabilities/host/quick-app-proxy-adapter.ts",
84366
85860
  "dsh-capabilities/host/quick-app-proxy-provider.ts",
84367
85861
  "host/features/quick-apps.ts",
@@ -90413,5 +91907,5 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
90413
91907
  });
90414
91908
 
90415
91909
  })();
90416
- // codingns-client-revision: 35886f7c011dbf3b1b8887fda4f4d0801ce70892fbbcbc56eb0a5b58cea97891
91910
+ // codingns-client-revision: cdc65a7993088d3811defac6055cbb865cf55f0c7e8f63cba0776f815335e082
90417
91911
  //# sourceMappingURL=bundle.js.map