@chatcode/chatcode-cli 3.0.3 → 3.0.4-rc.1

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 (174) hide show
  1. package/README.i18n.yaml +10 -10
  2. package/README.md +16 -1
  3. package/README.zh.md +16 -1
  4. package/lib/bin.js +62 -11
  5. package/lib/{command-errors-CBJRI2gy.js → command-errors-BkCHTQHj.js} +12 -12
  6. package/lib/{command-trees-Dvq4C7a4.js → command-trees-5HFyC5sI.js} +2 -2
  7. package/lib/{component-identity-DPdJglJO.js → component-identity-De91VHwW.js} +3 -3
  8. package/lib/{dist-w_sIm4VD.js → dist-CsDWUvQ4.js} +231 -231
  9. package/lib/{dump-config-CauO75nE.js → dump-config-BcH-VYuv.js} +5 -5
  10. package/lib/dump-config-CyopmD85.js +2 -0
  11. package/lib/{dump-config-schema-CObLWWaW.js → dump-config-schema-DM0fb6Ns.js} +2 -2
  12. package/lib/{extension-events-Be9LWvHD.js → extension-events-CdYCRP0o.js} +26 -26
  13. package/lib/{frames-7PAg0Q9b.js → frames-DOX-Jgk8.js} +4 -4
  14. package/lib/headless-compat.js +2 -2
  15. package/lib/{host-access-DeCjoRQP.js → host-access-Bk4xps5E.js} +1 -1
  16. package/lib/{keymap-CRUxM_qn.js → keymap-CJ1kvLR2.js} +17 -16
  17. package/lib/{plugin-CDFSDE_y.js → plugin-XR7ncbnW.js} +2928 -2240
  18. package/lib/{plugin-Cn-hyYY8.js → plugin-eJjD6r12.js} +1 -1
  19. package/lib/{profile-boot-SJGbpLgN.js → profile-boot-BNQry1NM.js} +97 -14
  20. package/lib/profile-boot.js +2 -2
  21. package/lib/{scenes-D6jV1EEi.js → scenes-CAmWncZD.js} +3 -3
  22. package/lib/{settings-sections-DJQRNBo9.js → settings-sections-CakcvBv9.js} +7 -3
  23. package/lib/statusBarSettings-BPPS_Usm.js +382 -0
  24. package/lib/{supports-color-CcW-FGjr.js → supports-color-DyChQwlI.js} +2 -2
  25. package/lib/{themes-BCly4_y9.js → themes-OjcUpZzw.js} +13 -13
  26. package/lib/tui-compat-command-trees.js +1 -1
  27. package/lib/tui-compat-extensions.js +3 -3
  28. package/lib/tui-compat-plugin-host.js +5 -5
  29. package/lib/tui-compat-scenes.js +1 -1
  30. package/lib/tui-compat-settings-sections.js +1 -1
  31. package/lib/tui-compat-working-activity.js +4 -4
  32. package/lib/tui-compat-workspaces.js +1 -1
  33. package/lib/tui-compat.js +9 -26
  34. package/lib/types/args.d.ts +2 -0
  35. package/lib/types/permission-bypass.d.ts +16 -0
  36. package/lib/types/profile-boot.d.ts +12 -0
  37. package/lib/types/tui-compat.d.ts +4 -0
  38. package/lib/types/web-browser.d.ts +6 -0
  39. package/lib/types/web-instance.d.ts +42 -0
  40. package/lib/web-browser-Vcgfdsv_.js +46 -0
  41. package/lib/web-instance-B0jec7cq.js +2 -0
  42. package/lib/web-instance-DbP7IHPv.js +280 -0
  43. package/lib/{workspaces-Bb3kCAFb.js → workspaces-XY7UdfXp.js} +2 -2
  44. package/package.json +34 -32
  45. package/runtime/manifest.json +4 -2
  46. package/runtime/node_modules/@deepseek-ai/dsh-agent-default-model/lib/index.js +34 -4
  47. package/runtime/node_modules/@deepseek-ai/dsh-agent-default-model/lib/types/index.d.ts +9 -0
  48. package/runtime/node_modules/@deepseek-ai/dsh-agent-preset/skills/cordis-composition-reference/references/packages.md +2 -1
  49. package/runtime/node_modules/@deepseek-ai/dsh-api-gateway/lib/client.js +2 -0
  50. package/runtime/node_modules/@deepseek-ai/dsh-api-gateway/lib/types/client/remote-stream.js +4 -0
  51. package/runtime/node_modules/@deepseek-ai/dsh-api-remotes/lib/client.js +39 -0
  52. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/index.js +6 -1
  53. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/typert.host.js +10 -3
  54. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/typert.remote-client.js +7 -0
  55. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/catalog.js +8 -1
  56. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/types.d.ts +10 -0
  57. package/runtime/node_modules/@deepseek-ai/dsh-api-settings-controller/lib/index.js +28 -1
  58. package/runtime/node_modules/@deepseek-ai/dsh-api-settings-controller/lib/typert.host.js +39 -0
  59. package/runtime/node_modules/@deepseek-ai/dsh-api-settings-controller/lib/typert.remote-client.d.ts +2 -0
  60. package/runtime/node_modules/@deepseek-ai/dsh-api-settings-controller/lib/typert.remote-client.js +32 -0
  61. package/runtime/node_modules/@deepseek-ai/dsh-api-settings-controller/lib/types/index.d.ts +8 -0
  62. package/runtime/node_modules/@deepseek-ai/dsh-api-settings-controller/lib/types/index.js +19 -1
  63. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/index.js +28 -0
  64. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/feed.js +17 -0
  65. package/runtime/node_modules/@deepseek-ai/dsh-app-boot/lib/index.js +67 -19
  66. package/runtime/node_modules/@deepseek-ai/dsh-app-boot/lib/types/index.d.ts +1 -1
  67. package/runtime/node_modules/@deepseek-ai/dsh-app-boot/lib/types/profile-context.d.ts +11 -1
  68. package/runtime/node_modules/@deepseek-ai/dsh-app-boot/lib/worker/profile-resolution-bootstrap.js +22 -3
  69. package/runtime/node_modules/@deepseek-ai/dsh-base/cordis.patch.yml +9 -3
  70. package/runtime/node_modules/@deepseek-ai/dsh-base/package.json +2 -1
  71. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-chat/lib/client.js +3 -2
  72. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-chat/lib/types/index.d.ts +2 -2
  73. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-conversation/lib/client.js +1 -1
  74. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-goal/lib/client.js +1 -1
  75. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-model-selection/lib/client.js +60 -12
  76. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-model-selection/lib/types/client/directory.d.ts +3 -1
  77. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-model-selection/lib/types/client/locales.d.ts +6 -0
  78. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/markdown/CodeBlock.module.css +3 -5
  79. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/markdown/MarkdownText.module.css +23 -27
  80. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings/lib/types/client/contract/slots.d.ts +3 -1
  81. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-account/lib/client.js +2 -2
  82. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-account/lib/types/index.d.ts +2 -2
  83. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-general/lib/client.js +8 -7
  84. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-general/lib/types/client/SettingsDocumentAction.d.ts +1 -1
  85. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-general/lib/types/client/settings-document-store.d.ts +2 -1
  86. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-models/lib/client.js +33 -12
  87. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-models/lib/types/client/locales.d.ts +2 -0
  88. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-plugin-inventory/lib/client.js +1 -1
  89. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-sidebar/lib/client.js +1 -1
  90. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-theme/lib/client.js +1 -1
  91. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/client.js +8 -1
  92. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/locales.d.ts +2 -0
  93. package/runtime/node_modules/@deepseek-ai/dsh-computer-use/lib/index.js +35 -0
  94. package/runtime/node_modules/@deepseek-ai/dsh-computer-use/lib/types/brand.d.ts +11 -0
  95. package/runtime/node_modules/@deepseek-ai/dsh-computer-use/lib/types/brand.js +10 -0
  96. package/runtime/node_modules/@deepseek-ai/dsh-computer-use/lib/types/index.d.ts +28 -0
  97. package/runtime/node_modules/@deepseek-ai/dsh-computer-use/lib/types/index.js +36 -0
  98. package/runtime/node_modules/@deepseek-ai/dsh-computer-use/package.json +42 -0
  99. package/runtime/node_modules/@deepseek-ai/dsh-config-editor/lib/index.js +102 -14
  100. package/runtime/node_modules/@deepseek-ai/dsh-config-editor/lib/types/index.d.ts +34 -4
  101. package/runtime/node_modules/@deepseek-ai/dsh-config-editor/package.json +1 -0
  102. package/runtime/node_modules/@deepseek-ai/dsh-host-webserver/lib/index.js +2 -1
  103. package/runtime/node_modules/@deepseek-ai/dsh-native-command/lib/index.js +21 -8
  104. package/runtime/node_modules/@deepseek-ai/dsh-native-command/lib/types/path-opener.d.ts +4 -6
  105. package/runtime/node_modules/@deepseek-ai/dsh-native-command/lib/types/path-opener.js +18 -7
  106. package/runtime/node_modules/@deepseek-ai/dsh-settings/lib/index.js +5 -4
  107. package/runtime/node_modules/@deepseek-ai/dsh-settings/lib/types/index.d.ts +4 -3
  108. package/runtime/node_modules/@deepseek-ai/dsh-settings/lib/types/index.js +4 -3
  109. package/runtime/node_modules/@deepseek-ai/dsh-storage/lib/types/backend.d.ts +4 -0
  110. package/runtime/node_modules/@deepseek-ai/dsh-storage-domain/lib/index.js +60 -0
  111. package/runtime/node_modules/@deepseek-ai/dsh-storage-domain/lib/types/domain.d.ts +15 -0
  112. package/runtime/node_modules/@deepseek-ai/dsh-storage-json/lib/index.js +25 -0
  113. package/runtime/node_modules/@deepseek-ai/dsh-storage-json/package.json +1 -0
  114. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/index.js +5472 -0
  115. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/command-args.d.ts +17 -0
  116. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/commands/tianti/cicd.d.ts +8 -0
  117. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/commands/tianti/tianti.d.ts +7 -0
  118. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/commands/tianti-deliver/tianti-deliver.d.ts +8 -0
  119. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/config.d.ts +27 -0
  120. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/index.d.ts +12 -0
  121. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/memory-config.d.ts +10 -0
  122. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/runtime.d.ts +105 -0
  123. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/aliases.d.ts +11 -0
  124. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/auth.d.ts +20 -0
  125. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/client.d.ts +206 -0
  126. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/config.d.ts +20 -0
  127. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/index.d.ts +6 -0
  128. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/log.d.ts +16 -0
  129. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/types.d.ts +136 -0
  130. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/codebase.d.ts +19 -0
  131. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/dynamicWorkflow.d.ts +10 -0
  132. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/engine.d.ts +8 -0
  133. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/executor.d.ts +11 -0
  134. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/executors.d.ts +15 -0
  135. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/index.d.ts +23 -0
  136. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/memorySuggestions.d.ts +12 -0
  137. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/openspec.d.ts +31 -0
  138. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/recommend.d.ts +8 -0
  139. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/render.d.ts +8 -0
  140. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/requirementContext.d.ts +12 -0
  141. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/scenarioUpgrade.d.ts +24 -0
  142. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/state.d.ts +16 -0
  143. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/store.d.ts +33 -0
  144. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/templates.d.ts +8 -0
  145. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/types.d.ts +385 -0
  146. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/wanmaDevelopmentWorkflow/writeReviewSync.d.ts +6 -0
  147. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/writeReview/index.d.ts +29 -0
  148. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/writeReview/store.d.ts +20 -0
  149. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/writeReview/types.d.ts +49 -0
  150. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/tools.d.ts +12 -0
  151. package/runtime/node_modules/@deepseek-ai/dsh-tianti/package.json +55 -0
  152. package/runtime/node_modules/@deepseek-ai/dsh-tool-cordis/lib/types/api-catalog.js +57 -13
  153. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/assets/index-D5kpKf--.css +1 -0
  154. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/assets/index-Dz_cDcce.js +133 -0
  155. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/assets/index-Dz_cDcce.js.map +1 -0
  156. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/chatcode-apple-touch-icon.png +0 -0
  157. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/chatcode-icon-32.png +0 -0
  158. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/chatcode-mask-icon.svg +1 -0
  159. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/favicon-dark.svg +1 -3
  160. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/favicon.ico +0 -0
  161. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/favicon.svg +1 -3
  162. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/index.html +8 -4
  163. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/preview.html +8 -4
  164. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/package.json +2 -1
  165. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/index.js +110 -33
  166. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/entity.d.ts +6 -0
  167. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/entity.js +23 -17
  168. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/index.d.ts +10 -0
  169. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/index.js +95 -21
  170. package/lib/dump-config-CijLv_kn.js +0 -2
  171. package/lib/tuiDisplayPrefs-Dm_fULiR.js +0 -204
  172. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/assets/index-DUvMhLle.css +0 -1
  173. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/assets/index-Q6zc2uHV.js +0 -127
  174. package/runtime/node_modules/@deepseek-ai/dsh-web-frontend/dist/assets/index-Q6zc2uHV.js.map +0 -1
@@ -499,6 +499,7 @@ function agentModelSelection(selection) {
499
499
  */
500
500
  async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefaultModel.currentSelection()) {
501
501
  const providers = ctx.llm.listProviders();
502
+ const customProviders = new Set(ctx.llm.listConfigurableProviders().filter((provider) => provider.settingsNs === "llm-pi-ai" && provider.declared === true).map((provider) => provider.provider));
502
503
  const catalog = await Promise.all(providers.map(async (provider) => {
503
504
  try {
504
505
  const models = await ctx.llm.listModels(provider.id);
@@ -515,6 +516,7 @@ async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefaultModel.c
515
516
  return {
516
517
  id: model.id,
517
518
  name: model.name,
519
+ ...resolved.inputModalities === void 0 ? {} : { inputModalities: [...resolved.inputModalities] },
518
520
  ...model.description === void 0 ? {} : { description: model.description },
519
521
  ...reasoning === void 0 ? {} : { reasoning }
520
522
  };
@@ -524,7 +526,8 @@ async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefaultModel.c
524
526
  group: {
525
527
  id: provider.id,
526
528
  name: provider.name,
527
- models: entries
529
+ models: entries,
530
+ ...customProviders.has(provider.id) ? { custom: true } : {}
528
531
  }
529
532
  };
530
533
  } catch (error) {
@@ -539,8 +542,10 @@ async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefaultModel.c
539
542
  }
540
543
  }));
541
544
  const groups = catalog.flatMap((item) => item.kind === "group" ? [item.group] : []).filter((group) => group.models.length > 0);
545
+ const savedDisplayName = ctx.agentDefaultModel.sharedDisplayName();
542
546
  return {
543
547
  default: { ...defaultSelection },
548
+ ...savedDisplayName === void 0 ? {} : { savedDisplayName },
544
549
  routableProviders: groups.map((group) => group.id),
545
550
  groups,
546
551
  failures: catalog.flatMap((item) => item.kind === "failure" ? [item.failure] : [])
@@ -492,13 +492,20 @@ const _deepseek_ai_dsh_api_session_controller_session_modelCatalog_result$schema
492
492
  'model': z.string().readonly(),
493
493
  'reasoningEffort': z.string().readonly().optional(),
494
494
  }).readonly(),
495
+ 'savedDisplayName': z.object({
496
+ 'provider': z.string().readonly(),
497
+ 'model': z.string().readonly(),
498
+ 'name': z.string().readonly(),
499
+ }).readonly().optional(),
495
500
  'routableProviders': z.array(z.string()).readonly(),
496
501
  'groups': z.array(z.object({
497
502
  'id': z.string().readonly(),
498
503
  'name': z.string().readonly(),
504
+ 'custom': z.boolean().readonly().optional(),
499
505
  'models': z.array(z.object({
500
506
  'id': z.string().readonly(),
501
507
  'name': z.string().readonly(),
508
+ 'inputModalities': z.array(z.union([z.literal("text"), z.literal("image")])).readonly().optional(),
502
509
  'description': z.string().readonly().optional(),
503
510
  'reasoning': z.object({
504
511
  'efforts': z.array(z.object({
@@ -1778,7 +1785,7 @@ export const TYPERT = {
1778
1785
  },
1779
1786
  {
1780
1787
  "name": "ModelCatalog",
1781
- "declaration": "export interface ModelCatalog {\n readonly default: ModelSelection;\n readonly routableProviders: readonly string[];\n readonly groups: readonly ModelProviderGroup[];\n readonly failures: readonly ModelCatalogFailure[];\n}"
1788
+ "declaration": "export interface ModelCatalog {\n readonly default: ModelSelection;\n readonly savedDisplayName?: { readonly provider: string; readonly model: string; readonly name: string; };\n readonly routableProviders: readonly string[];\n readonly groups: readonly ModelProviderGroup[];\n readonly failures: readonly ModelCatalogFailure[];\n}"
1782
1789
  },
1783
1790
  {
1784
1791
  "name": "ModelCatalogFailure",
@@ -1786,7 +1793,7 @@ export const TYPERT = {
1786
1793
  },
1787
1794
  {
1788
1795
  "name": "ModelCatalogModel",
1789
- "declaration": "export interface ModelCatalogModel {\n readonly id: string;\n readonly name: string;\n readonly description?: string;\n readonly reasoning?: ModelReasoning;\n}"
1796
+ "declaration": "export interface ModelCatalogModel {\n readonly id: string;\n readonly name: string;\n readonly inputModalities?: readonly ('text' | 'image')[];\n readonly description?: string;\n readonly reasoning?: ModelReasoning;\n}"
1790
1797
  },
1791
1798
  {
1792
1799
  "name": "ModelMessageSource",
@@ -1794,7 +1801,7 @@ export const TYPERT = {
1794
1801
  },
1795
1802
  {
1796
1803
  "name": "ModelProviderGroup",
1797
- "declaration": "export interface ModelProviderGroup {\n readonly id: string;\n readonly name: string;\n readonly models: readonly ModelCatalogModel[];\n}"
1804
+ "declaration": "export interface ModelProviderGroup {\n readonly id: string;\n readonly name: string;\n readonly custom?: boolean;\n readonly models: readonly ModelCatalogModel[];\n}"
1798
1805
  },
1799
1806
  {
1800
1807
  "name": "ModelReasoning",
@@ -492,13 +492,20 @@ const _deepseek_ai_dsh_api_session_controller_session_modelCatalog_result$schema
492
492
  'model': z.string().readonly(),
493
493
  'reasoningEffort': z.string().readonly().optional(),
494
494
  }).readonly(),
495
+ 'savedDisplayName': z.object({
496
+ 'provider': z.string().readonly(),
497
+ 'model': z.string().readonly(),
498
+ 'name': z.string().readonly(),
499
+ }).readonly().optional(),
495
500
  'routableProviders': z.array(z.string()).readonly(),
496
501
  'groups': z.array(z.object({
497
502
  'id': z.string().readonly(),
498
503
  'name': z.string().readonly(),
504
+ 'custom': z.boolean().readonly().optional(),
499
505
  'models': z.array(z.object({
500
506
  'id': z.string().readonly(),
501
507
  'name': z.string().readonly(),
508
+ 'inputModalities': z.array(z.union([z.literal("text"), z.literal("image")])).readonly().optional(),
502
509
  'description': z.string().readonly().optional(),
503
510
  'reasoning': z.object({
504
511
  'efforts': z.array(z.object({
@@ -9,6 +9,9 @@ import { credentialRef } from '@deepseek-ai/dsh-credentials';
9
9
  */
10
10
  export async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefaultModel.currentSelection()) {
11
11
  const providers = ctx.llm.listProviders();
12
+ const customProviders = new Set(ctx.llm.listConfigurableProviders()
13
+ .filter(provider => provider.settingsNs === 'llm-pi-ai' && provider.declared === true)
14
+ .map(provider => provider.provider));
12
15
  const catalog = await Promise.all(providers.map(async (provider) => {
13
16
  try {
14
17
  const models = await ctx.llm.listModels(provider.id);
@@ -29,13 +32,15 @@ export async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefault
29
32
  return {
30
33
  id: model.id,
31
34
  name: model.name,
35
+ ...(resolved.inputModalities === undefined ? {} : { inputModalities: [...resolved.inputModalities] }),
32
36
  ...(model.description === undefined ? {} : { description: model.description }),
33
37
  ...(reasoning === undefined ? {} : { reasoning }),
34
38
  };
35
39
  }));
36
40
  return {
37
41
  kind: 'group',
38
- group: { id: provider.id, name: provider.name, models: entries },
42
+ group: { id: provider.id, name: provider.name, models: entries,
43
+ ...(customProviders.has(provider.id) ? { custom: true } : {}) },
39
44
  };
40
45
  }
41
46
  catch (error) {
@@ -51,8 +56,10 @@ export async function buildModelCatalog(ctx, defaultSelection = ctx.agentDefault
51
56
  }));
52
57
  const groups = catalog.flatMap(item => item.kind === 'group' ? [item.group] : [])
53
58
  .filter(group => group.models.length > 0);
59
+ const savedDisplayName = ctx.agentDefaultModel.sharedDisplayName();
54
60
  return {
55
61
  default: { ...defaultSelection },
62
+ ...savedDisplayName === undefined ? {} : { savedDisplayName },
56
63
  routableProviders: groups.map(group => group.id),
57
64
  groups,
58
65
  failures: catalog.flatMap(item => item.kind === 'failure' ? [item.failure] : []),
@@ -122,6 +122,8 @@ export interface ModelReasoning {
122
122
  export interface ModelCatalogModel {
123
123
  readonly id: string;
124
124
  readonly name: string;
125
+ /** Input types accepted by the exact model route; omission leaves capability unspecified. */
126
+ readonly inputModalities?: readonly ('text' | 'image')[];
125
127
  readonly description?: string;
126
128
  readonly reasoning?: ModelReasoning;
127
129
  }
@@ -129,6 +131,8 @@ export interface ModelCatalogModel {
129
131
  export interface ModelProviderGroup {
130
132
  readonly id: string;
131
133
  readonly name: string;
134
+ /** User-declared route; presentation groups these without changing provider identities. */
135
+ readonly custom?: boolean;
132
136
  readonly models: readonly ModelCatalogModel[];
133
137
  }
134
138
  /** One provider whose model catalog lookup failed. */
@@ -140,6 +144,12 @@ export interface ModelCatalogFailure {
140
144
  /** Host-generation model catalog and the default used by unconfigured Sessions. */
141
145
  export interface ModelCatalog {
142
146
  readonly default: ModelSelection;
147
+ /** Latest shared display name; presentation may use it only for the exact provider/model pair. */
148
+ readonly savedDisplayName?: {
149
+ readonly provider: string;
150
+ readonly model: string;
151
+ readonly name: string;
152
+ };
143
153
  /** Provider routes with at least one currently available catalog model. */
144
154
  readonly routableProviders: readonly string[];
145
155
  readonly groups: readonly ModelProviderGroup[];
@@ -301,6 +301,7 @@ let SettingsController = (() => {
301
301
  let _replace_decorators;
302
302
  let _mutate_decorators;
303
303
  let _openSettingsDocument_decorators;
304
+ let _openNamespaceDocument_decorators;
304
305
  return class SettingsController extends _classSuper {
305
306
  static {
306
307
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
@@ -309,6 +310,7 @@ let SettingsController = (() => {
309
310
  _replace_decorators = [Remote];
310
311
  _mutate_decorators = [Remote];
311
312
  _openSettingsDocument_decorators = [Remote];
313
+ _openNamespaceDocument_decorators = [Remote];
312
314
  __esDecorate(this, null, _describe_decorators, {
313
315
  kind: "method",
314
316
  name: "describe",
@@ -364,6 +366,17 @@ let SettingsController = (() => {
364
366
  },
365
367
  metadata: _metadata
366
368
  }, null, _instanceExtraInitializers);
369
+ __esDecorate(this, null, _openNamespaceDocument_decorators, {
370
+ kind: "method",
371
+ name: "openNamespaceDocument",
372
+ static: false,
373
+ private: false,
374
+ access: {
375
+ has: (obj) => "openNamespaceDocument" in obj,
376
+ get: (obj) => obj.openNamespaceDocument
377
+ },
378
+ metadata: _metadata
379
+ }, null, _instanceExtraInitializers);
367
380
  if (_metadata) Object.defineProperty(this, Symbol.metadata, {
368
381
  enumerable: true,
369
382
  configurable: true,
@@ -439,11 +452,25 @@ let SettingsController = (() => {
439
452
  * @throws RemoteError when no document exists, preparation fails, or opening fails.
440
453
  */
441
454
  async openSettingsDocument(signal) {
455
+ return this.openDocument(void 0, signal);
456
+ }
457
+ /** Open the document owning a registered namespace, including shared home-level model configuration.
458
+ * @param ns Registered settings namespace; the Host resolves its owning path.
459
+ * @param signal Caller lifetime before native handoff.
460
+ * @returns Confirmation once the native editor accepts the document.
461
+ * @throws RemoteError for invalid namespaces, preparation failure or rejected native handoff.
462
+ */
463
+ async openNamespaceDocument(ns, signal) {
464
+ const parsed = settingsNamespaceRequestSchema.safeParse({ ns });
465
+ if (!parsed.success) throw new RemoteError("gateway/bad-request", "invalid settings namespace", {});
466
+ return this.openDocument(parsed.data.ns, signal);
467
+ }
468
+ async openDocument(namespace, signal) {
442
469
  const settings = this.provider();
443
470
  if (isAborted(signal)) throw new RemoteError("gateway/cancelled", "settings document open was aborted", {});
444
471
  let path;
445
472
  try {
446
- path = await settings.prepareDocument();
473
+ path = await settings.prepareDocument(namespace);
447
474
  } catch (error) {
448
475
  if (isAborted(signal)) throw new RemoteError("gateway/cancelled", "settings document preparation was aborted", {});
449
476
  throw new RemoteError("gateway/internal", `settings document preparation failed: ${messageOf(error)}`, {}, { cause: error });
@@ -80,6 +80,12 @@ const _deepseek_ai_dsh_api_settings_controller_settings_mutate_result$schema = (
80
80
  })),
81
81
  'revision': z.number(),
82
82
  }))
83
+ let _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema$value
84
+ const _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema = () => (_deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema$value ??= z.string())
85
+ let _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema$value
86
+ const _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema = () => (_deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema$value ??= z.object({
87
+ 'opened': z.literal(true).readonly(),
88
+ }))
83
89
  let _deepseek_ai_dsh_api_settings_controller_settings_openSettingsDocument_result$schema$value
84
90
  const _deepseek_ai_dsh_api_settings_controller_settings_openSettingsDocument_result$schema = () => (_deepseek_ai_dsh_api_settings_controller_settings_openSettingsDocument_result$schema$value ??= z.object({
85
91
  'opened': z.literal(true).readonly(),
@@ -279,6 +285,32 @@ export const TYPERT = {
279
285
  },
280
286
  sourceLocation: {"file":"packages/api/settings-controller/src/index.ts","line":152,"column":9},
281
287
  },
288
+ {
289
+ id: '@deepseek-ai/dsh-api-settings-controller#settings/openNamespaceDocument',
290
+ service: 'settingsController',
291
+ namespace: 'settings',
292
+ method: 'openNamespaceDocument',
293
+ invocation: { kind: 'direct' },
294
+ parameters: [
295
+ {
296
+ name: 'ns',
297
+ wire: 'ns',
298
+ source: 'json',
299
+ codec: {
300
+ mode: 'strict',
301
+ typeSymbol: '@deepseek-ai/dsh-api-settings-controller#settings/openNamespaceDocument:ns',
302
+ create: _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema,
303
+ },
304
+ },
305
+ ],
306
+ cancellation: { parameter: 'signal' },
307
+ result: {
308
+ mode: 'strict',
309
+ typeSymbol: '@deepseek-ai/dsh-api-settings-controller/types#SettingsDocumentOpenValue',
310
+ create: _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema,
311
+ },
312
+ sourceLocation: {"file":"packages/api/settings-controller/src/index.ts","line":178,"column":9},
313
+ },
282
314
  {
283
315
  id: '@deepseek-ai/dsh-api-settings-controller#settings/openSettingsDocument',
284
316
  service: 'settingsController',
@@ -469,6 +501,13 @@ export const TYPERT = {
469
501
  "signature": "@Remote async openSettingsDocument(signal: AbortSignal): Promise<SettingsDocumentOpenValue>",
470
502
  "summary": "Materialize the provider-owned settings document and open it in a native text editor.",
471
503
  "jsDoc": "/**\n * Materialize the provider-owned settings document and open it in a native text editor.\n * @param signal - caller lifetime; abort terminates preparation or the native command.\n * @returns confirmation after the native opener accepts the document.\n * @throws RemoteError when no document exists, preparation fails, or opening fails.\n */"
504
+ },
505
+ {
506
+ "kind": "method",
507
+ "name": "openNamespaceDocument",
508
+ "signature": "@Remote async openNamespaceDocument(ns: string, signal: AbortSignal): Promise<SettingsDocumentOpenValue>",
509
+ "summary": "Open the document owning a registered namespace, including shared home-level model configuration.",
510
+ "jsDoc": "/** Open the document owning a registered namespace, including shared home-level model configuration.\n * @param ns Registered settings namespace; the Host resolves its owning path.\n * @param signal Caller lifetime before native handoff.\n * @returns Confirmation once the native editor accepts the document.\n * @throws RemoteError for invalid namespaces, preparation failure or rejected native handoff.\n */"
472
511
  }
473
512
  ],
474
513
  "types": [
@@ -17,6 +17,7 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
17
17
  interface TypertRemoteNamespace$73657474696e6773 {
18
18
  describe: () => Promise<RemoteResult<SettingsDescribeValue>>
19
19
  mutate: (ns: string, ops: SettingsPathOpView[], expectedRevision: number | undefined) => Promise<RemoteResult<SettingsNamespaceView>>
20
+ openNamespaceDocument: (ns: string, signal?: AbortSignal) => Promise<RemoteResult<SettingsDocumentOpenValue>>
20
21
  openSettingsDocument: (signal?: AbortSignal) => Promise<RemoteResult<SettingsDocumentOpenValue>>
21
22
  replace: (ns: string, section: Record<string, JsonValue>, expectedRevision: number | undefined) => Promise<RemoteResult<SettingsNamespaceView>>
22
23
  update: (ns: string, patch: Record<string, JsonValue>, expectedRevision: number | undefined) => Promise<RemoteResult<SettingsNamespaceView>>
@@ -27,6 +28,7 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
27
28
  'credentials/unset': (ref: string) => Promise<RemoteResult<void>>
28
29
  'settings/describe': () => Promise<RemoteResult<SettingsDescribeValue>>
29
30
  'settings/mutate': (ns: string, ops: SettingsPathOpView[], expectedRevision: number | undefined) => Promise<RemoteResult<SettingsNamespaceView>>
31
+ 'settings/openNamespaceDocument': (ns: string, signal?: AbortSignal) => Promise<RemoteResult<SettingsDocumentOpenValue>>
30
32
  'settings/openSettingsDocument': (signal?: AbortSignal) => Promise<RemoteResult<SettingsDocumentOpenValue>>
31
33
  'settings/replace': (ns: string, section: Record<string, JsonValue>, expectedRevision: number | undefined) => Promise<RemoteResult<SettingsNamespaceView>>
32
34
  'settings/update': (ns: string, patch: Record<string, JsonValue>, expectedRevision: number | undefined) => Promise<RemoteResult<SettingsNamespaceView>>
@@ -80,6 +80,12 @@ const _deepseek_ai_dsh_api_settings_controller_settings_mutate_result$schema = (
80
80
  })),
81
81
  'revision': z.number(),
82
82
  }))
83
+ let _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema$value
84
+ const _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema = () => (_deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema$value ??= z.string())
85
+ let _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema$value
86
+ const _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema = () => (_deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema$value ??= z.object({
87
+ 'opened': z.literal(true).readonly(),
88
+ }))
83
89
  let _deepseek_ai_dsh_api_settings_controller_settings_openSettingsDocument_result$schema$value
84
90
  const _deepseek_ai_dsh_api_settings_controller_settings_openSettingsDocument_result$schema = () => (_deepseek_ai_dsh_api_settings_controller_settings_openSettingsDocument_result$schema$value ??= z.object({
85
91
  'opened': z.literal(true).readonly(),
@@ -276,6 +282,32 @@ export const TYPERT_REMOTE = {
276
282
  },
277
283
  sourceLocation: {"file":"packages/api/settings-controller/src/index.ts","line":152,"column":9},
278
284
  },
285
+ {
286
+ id: '@deepseek-ai/dsh-api-settings-controller#settings/openNamespaceDocument',
287
+ service: 'settingsController',
288
+ namespace: 'settings',
289
+ method: 'openNamespaceDocument',
290
+ invocation: { kind: 'direct' },
291
+ parameters: [
292
+ {
293
+ name: 'ns',
294
+ wire: 'ns',
295
+ source: 'json',
296
+ codec: {
297
+ mode: 'strict',
298
+ typeSymbol: '@deepseek-ai/dsh-api-settings-controller#settings/openNamespaceDocument:ns',
299
+ create: _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_parameter_0$schema,
300
+ },
301
+ },
302
+ ],
303
+ cancellation: { parameter: 'signal' },
304
+ result: {
305
+ mode: 'strict',
306
+ typeSymbol: '@deepseek-ai/dsh-api-settings-controller/types#SettingsDocumentOpenValue',
307
+ create: _deepseek_ai_dsh_api_settings_controller_settings_openNamespaceDocument_result$schema,
308
+ },
309
+ sourceLocation: {"file":"packages/api/settings-controller/src/index.ts","line":178,"column":9},
310
+ },
279
311
  {
280
312
  id: '@deepseek-ai/dsh-api-settings-controller#settings/openSettingsDocument',
281
313
  service: 'settingsController',
@@ -83,6 +83,14 @@ export declare class SettingsController extends TypertRemoteService {
83
83
  * @throws RemoteError when no document exists, preparation fails, or opening fails.
84
84
  */
85
85
  openSettingsDocument(signal: AbortSignal): Promise<SettingsDocumentOpenValue>;
86
+ /** Open the document owning a registered namespace, including shared home-level model configuration.
87
+ * @param ns Registered settings namespace; the Host resolves its owning path.
88
+ * @param signal Caller lifetime before native handoff.
89
+ * @returns Confirmation once the native editor accepts the document.
90
+ * @throws RemoteError for invalid namespaces, preparation failure or rejected native handoff.
91
+ */
92
+ openNamespaceDocument(ns: string, signal: AbortSignal): Promise<SettingsDocumentOpenValue>;
93
+ private openDocument;
86
94
  private write;
87
95
  /** Resolve the optional provider or report how to supply it. */
88
96
  private provider;
@@ -86,6 +86,7 @@ let SettingsController = (() => {
86
86
  let _replace_decorators;
87
87
  let _mutate_decorators;
88
88
  let _openSettingsDocument_decorators;
89
+ let _openNamespaceDocument_decorators;
89
90
  return class SettingsController extends _classSuper {
90
91
  static {
91
92
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
@@ -94,11 +95,13 @@ let SettingsController = (() => {
94
95
  _replace_decorators = [Remote];
95
96
  _mutate_decorators = [Remote];
96
97
  _openSettingsDocument_decorators = [Remote];
98
+ _openNamespaceDocument_decorators = [Remote];
97
99
  __esDecorate(this, null, _describe_decorators, { kind: "method", name: "describe", static: false, private: false, access: { has: obj => "describe" in obj, get: obj => obj.describe }, metadata: _metadata }, null, _instanceExtraInitializers);
98
100
  __esDecorate(this, null, _update_decorators, { kind: "method", name: "update", static: false, private: false, access: { has: obj => "update" in obj, get: obj => obj.update }, metadata: _metadata }, null, _instanceExtraInitializers);
99
101
  __esDecorate(this, null, _replace_decorators, { kind: "method", name: "replace", static: false, private: false, access: { has: obj => "replace" in obj, get: obj => obj.replace }, metadata: _metadata }, null, _instanceExtraInitializers);
100
102
  __esDecorate(this, null, _mutate_decorators, { kind: "method", name: "mutate", static: false, private: false, access: { has: obj => "mutate" in obj, get: obj => obj.mutate }, metadata: _metadata }, null, _instanceExtraInitializers);
101
103
  __esDecorate(this, null, _openSettingsDocument_decorators, { kind: "method", name: "openSettingsDocument", static: false, private: false, access: { has: obj => "openSettingsDocument" in obj, get: obj => obj.openSettingsDocument }, metadata: _metadata }, null, _instanceExtraInitializers);
104
+ __esDecorate(this, null, _openNamespaceDocument_decorators, { kind: "method", name: "openNamespaceDocument", static: false, private: false, access: { has: obj => "openNamespaceDocument" in obj, get: obj => obj.openNamespaceDocument }, metadata: _metadata }, null, _instanceExtraInitializers);
102
105
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
103
106
  }
104
107
  openTextFile = __runInitializers(this, _instanceExtraInitializers);
@@ -169,12 +172,27 @@ let SettingsController = (() => {
169
172
  * @throws RemoteError when no document exists, preparation fails, or opening fails.
170
173
  */
171
174
  async openSettingsDocument(signal) {
175
+ return this.openDocument(undefined, signal);
176
+ }
177
+ /** Open the document owning a registered namespace, including shared home-level model configuration.
178
+ * @param ns Registered settings namespace; the Host resolves its owning path.
179
+ * @param signal Caller lifetime before native handoff.
180
+ * @returns Confirmation once the native editor accepts the document.
181
+ * @throws RemoteError for invalid namespaces, preparation failure or rejected native handoff.
182
+ */
183
+ async openNamespaceDocument(ns, signal) {
184
+ const parsed = settingsNamespaceRequestSchema.safeParse({ ns });
185
+ if (!parsed.success)
186
+ throw new RemoteError('gateway/bad-request', 'invalid settings namespace', {});
187
+ return this.openDocument(parsed.data.ns, signal);
188
+ }
189
+ async openDocument(namespace, signal) {
172
190
  const settings = this.provider();
173
191
  if (isAborted(signal))
174
192
  throw new RemoteError('gateway/cancelled', 'settings document open was aborted', {});
175
193
  let path;
176
194
  try {
177
- path = await settings.prepareDocument();
195
+ path = await settings.prepareDocument(namespace);
178
196
  }
179
197
  catch (error) {
180
198
  if (isAborted(signal))
@@ -54,6 +54,34 @@ var WorkspaceFeed = class {
54
54
  ctx.on("domain/changed", (change) => {
55
55
  this.changed(change);
56
56
  });
57
+ ctx.on("workspace/refreshed", () => {
58
+ const baseline = this.baseline();
59
+ const ids = new Set(baseline.items.map((item) => String(item.workspaceId)));
60
+ for (const id of this.knownIds) if (!ids.has(id)) this.publish({
61
+ type: "remove",
62
+ workspaceId: WorkspaceId(id)
63
+ });
64
+ this.knownIds = ids;
65
+ for (const workspace of baseline.items) this.publish({
66
+ type: "upsert",
67
+ workspace
68
+ });
69
+ this.order = baseline.items.map((item) => String(item.workspaceId));
70
+ this.archived = baseline.archivedSessionIds.map(String);
71
+ this.pinned = baseline.pinnedSessionIds.map(String);
72
+ this.publish({
73
+ type: "order",
74
+ workspaceIds: baseline.items.map((item) => item.workspaceId)
75
+ });
76
+ this.publish({
77
+ type: "archived",
78
+ archivedSessionIds: baseline.archivedSessionIds
79
+ });
80
+ this.publish({
81
+ type: "pinned",
82
+ pinnedSessionIds: baseline.pinnedSessionIds
83
+ });
84
+ });
57
85
  ctx.effect(() => () => {
58
86
  for (const follower of this.followers) follower.close();
59
87
  this.followers.clear();
@@ -44,6 +44,23 @@ export class WorkspaceFeed {
44
44
  this.archived = ctx.workspaceRegistry.archivedSessionIds.map(String);
45
45
  this.pinned = ctx.workspaceRegistry.pinnedSessionIds.map(String);
46
46
  ctx.on('domain/changed', (change) => { this.changed(change); });
47
+ ctx.on('workspace/refreshed', () => {
48
+ const baseline = this.baseline();
49
+ const ids = new Set(baseline.items.map(item => String(item.workspaceId)));
50
+ for (const id of this.knownIds) {
51
+ if (!ids.has(id))
52
+ this.publish({ type: 'remove', workspaceId: WorkspaceId(id) });
53
+ }
54
+ this.knownIds = ids;
55
+ for (const workspace of baseline.items)
56
+ this.publish({ type: 'upsert', workspace });
57
+ this.order = baseline.items.map(item => String(item.workspaceId));
58
+ this.archived = baseline.archivedSessionIds.map(String);
59
+ this.pinned = baseline.pinnedSessionIds.map(String);
60
+ this.publish({ type: 'order', workspaceIds: baseline.items.map(item => item.workspaceId) });
61
+ this.publish({ type: 'archived', archivedSessionIds: baseline.archivedSessionIds });
62
+ this.publish({ type: 'pinned', pinnedSessionIds: baseline.pinnedSessionIds });
63
+ });
47
64
  ctx.effect(() => () => {
48
65
  for (const follower of this.followers)
49
66
  follower.close();