dsh-plugin-dev-kb 1.8.0 → 1.8.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 (229) hide show
  1. package/CHANGELOG.md +186 -178
  2. package/README.en.md +172 -172
  3. package/README.md +183 -183
  4. package/kb/INDEX.md +236 -234
  5. package/kb/README.md +88 -88
  6. package/kb/extra/AGENTS.md +77 -77
  7. package/kb/extra/deepseek-llm-api-wire-extensions.md +162 -162
  8. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +162 -162
  9. package/kb/extra/defensive-patterns/package-surface.md +233 -232
  10. package/kb/extra/defensive-patterns/package-surface.zh.md +233 -232
  11. package/kb/extra/defensive-patterns/remote-and-api.md +117 -117
  12. package/kb/extra/defensive-patterns/remote-and-api.zh.md +117 -117
  13. package/kb/extra/development.md +221 -221
  14. package/kb/extra/development.zh.md +228 -228
  15. package/kb/extra/event-producer-consumer.md +133 -123
  16. package/kb/extra/event-producer-consumer.zh.md +135 -125
  17. package/kb/extra/module-graph.md +1961 -1888
  18. package/kb/extra/module-graph.zh.md +1963 -1890
  19. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.md +60 -0
  20. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.zh.md +60 -0
  21. package/kb/extra/persistence-changes/README.md +92 -92
  22. package/kb/extra/persistence-changes/README.zh.md +92 -92
  23. package/kb/extra/persistence-changes/historical-formats/README.md +75 -75
  24. package/kb/extra/persistence-changes/historical-formats/README.zh.md +75 -75
  25. package/kb/extra/persistence-changes/releases/README.md +103 -103
  26. package/kb/extra/persistence-changes/releases/README.zh.md +103 -103
  27. package/kb/extra/rescope.md +55 -55
  28. package/kb/extra/rescope.zh.md +55 -55
  29. package/kb/extra/subsystems/boot.md +631 -621
  30. package/kb/extra/subsystems/boot.zh.md +631 -621
  31. package/kb/extra/subsystems/computer-use.md +179 -137
  32. package/kb/extra/subsystems/computer-use.zh.md +179 -137
  33. package/kb/extra/subsystems/extensions.md +387 -384
  34. package/kb/extra/subsystems/extensions.zh.md +387 -384
  35. package/kb/extra/subsystems/feedback.md +418 -400
  36. package/kb/extra/subsystems/feedback.zh.md +418 -400
  37. package/kb/extra/subsystems/forge.md +2169 -1226
  38. package/kb/extra/subsystems/forge.zh.md +2171 -1226
  39. package/kb/extra/subsystems/liveshare.md +167 -158
  40. package/kb/extra/subsystems/liveshare.zh.md +167 -158
  41. package/kb/extra/subsystems/mcp.md +237 -234
  42. package/kb/extra/subsystems/mcp.zh.md +237 -234
  43. package/kb/extra/subsystems/office-kit.md +122 -0
  44. package/kb/extra/subsystems/office-kit.zh.md +122 -0
  45. package/kb/extra/subsystems/working-directory.md +95 -64
  46. package/kb/extra/subsystems/working-directory.zh.md +95 -64
  47. package/kb/extra/subsystems/worktrees.md +187 -127
  48. package/kb/extra/subsystems/worktrees.zh.md +187 -127
  49. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.md +21 -21
  50. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.zh.md +21 -21
  51. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.md +18 -0
  52. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.zh.md +18 -0
  53. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.md +18 -0
  54. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.zh.md +18 -0
  55. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.md +34 -0
  56. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.zh.md +34 -0
  57. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.md +49 -0
  58. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.zh.md +49 -0
  59. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.md +36 -0
  60. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.zh.md +36 -0
  61. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.md +26 -0
  62. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.zh.md +26 -0
  63. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.md +22 -0
  64. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.zh.md +22 -0
  65. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.md +21 -0
  66. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.zh.md +21 -0
  67. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.md +23 -0
  68. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.zh.md +23 -0
  69. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.md +20 -0
  70. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.zh.md +20 -0
  71. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.md +18 -0
  72. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.zh.md +18 -0
  73. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md +23 -0
  74. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md +23 -0
  75. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.md +35 -0
  76. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.zh.md +35 -0
  77. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.md +26 -0
  78. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.zh.md +26 -0
  79. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.md +26 -0
  80. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.zh.md +26 -0
  81. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.md +19 -0
  82. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.zh.md +19 -0
  83. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.md +26 -0
  84. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.zh.md +26 -0
  85. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.md +22 -0
  86. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.zh.md +22 -0
  87. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.md +25 -0
  88. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.zh.md +25 -0
  89. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.md +48 -0
  90. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.zh.md +48 -0
  91. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.md +45 -0
  92. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.zh.md +45 -0
  93. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.md +19 -0
  94. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.zh.md +19 -0
  95. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.md +17 -0
  96. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.zh.md +17 -0
  97. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.md +27 -0
  98. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.zh.md +27 -0
  99. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.md +20 -0
  100. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.zh.md +20 -0
  101. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.md +19 -0
  102. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.zh.md +19 -0
  103. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.md +18 -0
  104. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.zh.md +18 -0
  105. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.md +41 -0
  106. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.zh.md +41 -0
  107. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.md +21 -0
  108. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.zh.md +21 -0
  109. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.md +29 -0
  110. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.zh.md +29 -0
  111. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.md +25 -0
  112. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.zh.md +25 -0
  113. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.md +31 -0
  114. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.zh.md +31 -0
  115. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.md +24 -0
  116. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.zh.md +24 -0
  117. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.md +24 -0
  118. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.zh.md +24 -0
  119. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.md +19 -0
  120. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.zh.md +19 -0
  121. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.md +15 -0
  122. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.zh.md +15 -0
  123. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.md +28 -0
  124. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.zh.md +28 -0
  125. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.md +36 -0
  126. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.zh.md +36 -0
  127. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.md +22 -0
  128. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.zh.md +22 -0
  129. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.md +31 -0
  130. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.zh.md +31 -0
  131. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.md +18 -0
  132. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.zh.md +18 -0
  133. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.md +30 -0
  134. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.zh.md +30 -0
  135. package/kb/extra/web-styling.md +57 -57
  136. package/kb/extra/web-styling.zh.md +57 -57
  137. package/kb/meta/search-index.json +4508 -3980
  138. package/kb/meta/source.json +18 -18
  139. package/kb/site/develop/practice/llm-adapter.md +192 -192
  140. package/kb/site/en/develop/practice/llm-adapter.md +192 -192
  141. package/kb/site/en/guide/desktop-uninstall-cleanup.md +63 -0
  142. package/kb/site/en/guide/plugin-market.md +153 -151
  143. package/kb/site/en/guide/providers.md +234 -234
  144. package/kb/site/en/guide/quickstart.md +35 -34
  145. package/kb/site/en/reference/capability-seams.md +789 -767
  146. package/kb/site/en/reference/config-catalog.md +5432 -5128
  147. package/kb/site/en/reference/cookbook/adding-a-package.md +175 -175
  148. package/kb/site/en/reference/cookbook/adding-a-tool.md +105 -104
  149. package/kb/site/en/reference/cookbook/extension-cookbook.md +178 -135
  150. package/kb/site/en/reference/cordis-api/context.md +373 -369
  151. package/kb/site/en/reference/cordis-api/fiber.md +457 -433
  152. package/kb/site/en/reference/cordis-api/inherited.md +44 -44
  153. package/kb/site/en/reference/cordis-api/service.md +118 -107
  154. package/kb/site/en/reference/experimental-persistence-catalog.md +36 -23
  155. package/kb/site/en/reference/index.md +174 -174
  156. package/kb/site/en/reference/persistence-catalog.md +9453 -9432
  157. package/kb/site/en/reference/subsystems/compaction.md +288 -288
  158. package/kb/site/en/reference/subsystems/core.md +1172 -1171
  159. package/kb/site/en/reference/subsystems/credentials.md +526 -497
  160. package/kb/site/en/reference/subsystems/filesystem.md +708 -708
  161. package/kb/site/en/reference/subsystems/index.md +82 -82
  162. package/kb/site/en/reference/subsystems/llm-streaming.md +1290 -1288
  163. package/kb/site/en/reference/subsystems/lsp.md +230 -206
  164. package/kb/site/en/reference/subsystems/persistence.md +451 -432
  165. package/kb/site/en/reference/subsystems/plan.md +91 -91
  166. package/kb/site/en/reference/subsystems/ptc-runtime.md +295 -261
  167. package/kb/site/en/reference/subsystems/sandbox.md +250 -232
  168. package/kb/site/en/reference/subsystems/session-query.md +525 -515
  169. package/kb/site/en/reference/subsystems/session-reference.md +231 -229
  170. package/kb/site/en/reference/subsystems/session.md +1478 -1431
  171. package/kb/site/en/reference/subsystems/sidebar-right.md +165 -165
  172. package/kb/site/en/reference/subsystems/skills.md +356 -356
  173. package/kb/site/en/reference/subsystems/slots.md +235 -231
  174. package/kb/site/en/reference/subsystems/terminal.md +188 -188
  175. package/kb/site/en/reference/subsystems/tools.md +902 -891
  176. package/kb/site/en/reference/subsystems/user-questions.md +330 -327
  177. package/kb/site/en/reference/subsystems/web-client.md +161 -104
  178. package/kb/site/en/reference/subsystems/web-server.md +434 -351
  179. package/kb/site/en/reference/subsystems/web.md +268 -268
  180. package/kb/site/en/reference/subsystems/workflow.md +287 -282
  181. package/kb/site/en/reference/subsystems/workspace.md +743 -651
  182. package/kb/site/en/reference/tool-catalog.md +2867 -2704
  183. package/kb/site/guide/desktop-uninstall-cleanup.md +63 -0
  184. package/kb/site/guide/plugin-market.md +153 -151
  185. package/kb/site/guide/providers.md +234 -234
  186. package/kb/site/guide/quickstart.md +35 -34
  187. package/kb/site/reference/capability-seams.md +789 -767
  188. package/kb/site/reference/config-catalog.md +5432 -5128
  189. package/kb/site/reference/cookbook/adding-a-package.md +175 -175
  190. package/kb/site/reference/cookbook/adding-a-tool.md +107 -106
  191. package/kb/site/reference/cookbook/extension-cookbook.md +182 -139
  192. package/kb/site/reference/cordis-api/context.md +373 -369
  193. package/kb/site/reference/cordis-api/fiber.md +459 -435
  194. package/kb/site/reference/cordis-api/inherited.md +44 -44
  195. package/kb/site/reference/cordis-api/service.md +118 -107
  196. package/kb/site/reference/experimental-persistence-catalog.md +36 -23
  197. package/kb/site/reference/index.md +178 -178
  198. package/kb/site/reference/persistence-catalog.md +9453 -9432
  199. package/kb/site/reference/subsystems/compaction.md +288 -288
  200. package/kb/site/reference/subsystems/core.md +1184 -1183
  201. package/kb/site/reference/subsystems/credentials.md +526 -497
  202. package/kb/site/reference/subsystems/filesystem.md +708 -708
  203. package/kb/site/reference/subsystems/index.md +82 -82
  204. package/kb/site/reference/subsystems/llm-streaming.md +1296 -1294
  205. package/kb/site/reference/subsystems/lsp.md +230 -206
  206. package/kb/site/reference/subsystems/persistence.md +451 -432
  207. package/kb/site/reference/subsystems/plan.md +91 -91
  208. package/kb/site/reference/subsystems/ptc-runtime.md +295 -261
  209. package/kb/site/reference/subsystems/sandbox.md +250 -232
  210. package/kb/site/reference/subsystems/session-query.md +525 -515
  211. package/kb/site/reference/subsystems/session-reference.md +231 -229
  212. package/kb/site/reference/subsystems/session.md +1482 -1435
  213. package/kb/site/reference/subsystems/sidebar-right.md +165 -165
  214. package/kb/site/reference/subsystems/skills.md +356 -356
  215. package/kb/site/reference/subsystems/slots.md +239 -235
  216. package/kb/site/reference/subsystems/terminal.md +188 -188
  217. package/kb/site/reference/subsystems/tools.md +902 -891
  218. package/kb/site/reference/subsystems/user-questions.md +330 -327
  219. package/kb/site/reference/subsystems/web-client.md +161 -104
  220. package/kb/site/reference/subsystems/web-server.md +434 -351
  221. package/kb/site/reference/subsystems/web.md +268 -268
  222. package/kb/site/reference/subsystems/workflow.md +287 -282
  223. package/kb/site/reference/subsystems/workspace.md +743 -651
  224. package/kb/site/reference/tool-catalog.md +2872 -2709
  225. package/lib/index.js +359 -359
  226. package/package.json +68 -68
  227. package/skills/dsh-plugin-dev-kb.md +71 -70
  228. package/kb/extra/subsystems/office-to-pdf.md +0 -87
  229. package/kb/extra/subsystems/office-to-pdf.zh.md +0 -87
@@ -1,231 +1,235 @@
1
- ---
2
- editSource: "docs/subsystems/slots.md"
3
- rawMarkdownPath: "en/reference/subsystems/slots.md"
4
- outline: [2,3]
5
- ---
6
-
7
- # Web Client Slots
8
-
9
- Slots are the Web Client's typed React composition system. [`dsh-client-ui-slots`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-slots/README.md) defines the React-free registry and type algebra; [`dsh-client-ui-renderer`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-renderer/README.md) binds observable sources to hooks, renders the tree, and owns React contexts internally. A feature plugin contributes UI through `ctx.slots.register()` and never imports another feature plugin's component.
10
-
11
- This page documents slot ownership, component inputs, extension APIs, and the shipped hierarchy. The surrounding boot, Remote, Client model, and Conversation paths are in [Web Client architecture](./web-client.md).
12
-
13
- `plugins.bundle.config` supplies bundle detail configuration, keyed by npm package name. `plugins.bundle.activation` renders optional guidance after user-requested enablement, with owner callbacks to dismiss or open that bundle’s details. `conversation.input.activity` supplies one action between the model selector and Send, with toolbar expansion released on unmount.
14
-
15
- The plugin catalog declares `plugins.add.actions`, a root-scoped list for `MenuItemButton` rows after installation in the Add plugin menu. Its owner supplies `onDismiss()` to close the menu before starting an action. The slot follows the owning Plugins page declaration lifetime.
16
-
17
- The root-scoped lists `sidebar.panellist.actions`, `conversation.session.header.views.actions`, and `sidebar.right.tab.guide.actions` supply the rows of the More menus after the panel rows, the View tabs, and the right-sidebar guide cards. A region draws its More button and menu only while its list has registrations, and passes the customizable entries with their pin state, `onOpen`, `onPinnedChange`, and `onDismiss`. Panel and View entries also carry optional `active` state for the current selection, independently of pin state. The `sidebar.panel.icon` root-scoped factory owns the `sidebar.panellist` list and renders its registered icon by `id`, `size`, and `active` for both sidebar rows and More entries. Each region keeps its own unpinned entry ids in memory; [`ui-entry-customization`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-entry-customization/README.md) registers the shipped rows.
18
-
19
- [ui-workspace](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-workspace/README.md#understand-the-implementation) documents Session-row extension positions, visibility, and keyboard behavior.
20
-
21
- [ui-settings](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-settings/README.md#filling-the-settings-slots) documents the settings page and navigation-icon extension points.
22
-
23
- ## Declaration and lifecycle
24
-
25
- `SlotMap` is the compile-time registry. A package declaration-merges the key, cardinality, scope, owner props, keyed props, and optional slot-level inject face. The runtime declaration is the matching `children` entry on the component that owns the render location.
26
-
27
- Declaring a child has three effects: it makes the child key live, authorizes that parent entry's `renderSlot` or `renderSlotChain` call, and records the runtime dispatch specification. One live entry owns each declaration. Registering into an undeclared slot or declaring a child already owned elsewhere fails during plugin activation.
28
-
29
- `root` is the only built-in declaration and the only key rendered through the Cordis service itself. `ui-renderer` calls `ctx.slots.renderSlot('root', {})`; every descendant is rendered through the `renderSlot` or `renderSlotChain` prop of the entry that declared it.
30
-
31
- Registrations and declarations follow Cordis effect lifetimes. Disposing an entry removes its contribution and recursively collapses the child slots it declared. A feature that contributes into another package's slot therefore uses `ctx.slots.inject(key, callback)`: the callback runs for each declaration lifetime, its effects are removed when the owner collapses, and it runs again if the owner is mounted again.
32
-
33
- ```tsx ignore-check
34
- import type { Context } from '@deepseek-ai/cordis'
35
- import type {} from '@deepseek-ai/dsh-client-ui-conversation/client'
36
- import type {} from '@deepseek-ai/dsh-client-ui-session/client'
37
- import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
38
-
39
- type HeaderActionProps = PropsRuntime<'conversation.session.header.actions'>
40
-
41
- function HeaderAction({ useSession }: HeaderActionProps) {
42
- const running = useSession(snapshot => snapshot.running)
43
- return <button disabled={running}>Review</button>
44
- }
45
-
46
- export const inject = ['slots']
47
-
48
- export function apply(ctx: Context): void {
49
- ctx.slots.inject('conversation.session.header.actions', () =>
50
- ctx.slots.register({
51
- name: 'conversation.session.header.actions',
52
- id: 'review',
53
- order: 100,
54
- }, HeaderAction))
55
- }
56
- ```
57
-
58
- ## Cardinality and scope
59
-
60
- The slot declaration fixes two independent axes.
61
-
62
- | Axis | Value | Meaning |
63
- |---|---|---|
64
- | cardinality | `single` | One cell. The active priority winner renders. Use a child slot instead of treating this as an additive list. |
65
- | cardinality | `list` | Cells are addressed by required `id` and ordered by `order`, then registration order. |
66
- | cardinality | `keyed` | The owner dispatches an `entryKey`; the matching cell renders with any key-specific props. |
67
- | cardinality | `chain` | Each entry supplies a pure `select(owner)` function. The first non-null result in priority order renders and receives that result as `matched`; otherwise the owner fallback renders. |
68
- | cardinality | `hoc` | Entries nest around the owner's `renderSlot(key, owner, { children })` content, lowest outermost; see [Hoc layers](#hoc-layers). |
69
- | scope | `root` | One root-scoped component and store instance. |
70
- | scope | `session-maybe` | Inherits the surrounding Provider binding but stays renderable without one; Session values are optional. |
71
- | scope | `session` | Requires a resolved surrounding Provider binding and receives definite Session values. |
72
-
73
- `priority` is a shadowing rank for `single`, `list`, `keyed`, and `hoc` cells and an election order for `chain`. Lower values run or render first. Ordinary additive contributions should choose a fresh list or hoc `id`, or keyed `key`; intentionally reusing a shipped cell replaces its presentation.
74
-
75
- <a id="hoc-layers"></a>
76
-
77
- ### Hoc layers
78
-
79
- A hoc entry is a layer addressed by its required `id`. Layers nest by ascending `order`, then `priority`, then registration order, lowest outermost. Each layer receives the same owner props plus the next inner layer as `children`, the owner's content at the innermost, and renders it exactly once; owner props must not use the name `children`. Omitted `children` renders the layers around nothing, and with no live layer the content renders unchanged.
80
-
81
- - Remounting: adding or removing a layer remounts the content inside it, including a crashed layer leaving the slot; a `session` or `session-maybe` layer also remounts it when its Session binding changes.
82
- - Errors: a crashed layer renders its `children` and leaves the slot. An error thrown by the wrapped content passes every layer and is reported against none; a layer that wraps its `children` in its own error boundary catches it as an internal wrapper error rather than the original.
83
- - Layout: the outlet inserts a `display: contents` `[data-slot]` element between the owner and its content, so owner selectors cannot rely on the content being a direct child. A layer must not create a box of its own — for example, use `display: contents` — or the content leaves its parent's layout.
84
-
85
- The [context-menu plugin](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-context-menu/README.md) contributes `useContextMenu` through `provideRoot`; every scope receives the same plugin-owned trigger factory. Its prop and retained handlers retire when the provider unloads. Its root-scoped keyed `contextMenu.icon` Slot renders business-owned icons from action metadata.
86
-
87
- ## Component inputs
88
-
89
- A registered component receives inputs assembled at its binding site. Components derive these types rather than copying their members.
90
-
91
- | Input | Declared by | Component type |
92
- |---|---|---|
93
- | owner values and standard scope values | the `SlotMap` row and installed scope adapters | `PropsRuntime<K>` |
94
- | authorized child renderers | the registration's `children` keys | `PropsRenderSlots<S>` |
95
- | selector hook and mutation callbacks for shared view state | the registration's `store` | `PropsStore<H>` |
96
- | private data, callbacks, and observable hooks | the registration's `inject` factory | `InjectFace<I>` |
97
- | localized `t` function | the registration's `locale` namespace | `PropsLocale<N>` |
98
- | selected chain value | the registration's `select` result | `matched` through `ComposedProps` |
99
- | wrapped owner content | the `SlotMap` row's `hoc` kind | `children` through `ComposedProps` |
100
-
101
- `SessionProvider` is also present in `PropsRenderSlots` when an entry declares a `session` or `session-maybe` child. With no `session` prop it inherits the surrounding binding; an explicit `SessionReference` or `undefined` overrides only that subtree. The Provider does not key its whole body. A strict `session` entry remounts when its binding generation changes. A blank `session-maybe` entry adopts its first binding without remounting, then remounts for a later generation or a return to absence.
102
-
103
- Components never receive `ctx`. Parent-owned point-in-time values enter through the owner argument to `renderSlot`; shared view state uses a declared store; services and model objects stay in the `apply` closure and are projected into callbacks or observable sources.
104
-
105
- ## Framework-provided hooks
106
-
107
- The shipped adapters add these standard props. They are available according to the target slot's scope, independent of which package registered the component.
108
-
109
- | Availability | Props | Owner |
110
- |---|---|---|
111
- | every scope | `useSessions`, `useSessionStatus`, `useSessionRetainInfo`, `useSessionAccess` | `ui-session` |
112
- | every scope | `useWorkspaces`, `useWorkspaceAccess` | `ui-workspace` |
113
- | every scope | `useRemoteAccess` (the `global` resource) | `api-remote-access` |
114
- | every scope | `usePanelInfo` | `ui-layout` |
115
- | `session` | `sessionId`, `useSession`, `useProjection`, `useAccess` (the bound Session's answer) | `ui-session` |
116
- | `session-maybe` | optional `sessionId`, `useSession`, `useProjection`, `useAccess` results | `ui-session` |
117
- | `session` | `useConversation`, `useInput`, `inputActions` | `ui-conversation` |
118
- | `session-maybe` | optional `useConversation`, `useInput`, `inputActions` results | `ui-conversation` |
119
- | `session` | `useChat` | `ui-chat` |
120
- | `session` | `useTrajectory` | `ui-trajectory` |
121
-
122
- The renderer also creates `useStore` from a declared store and `t` from a declared locale namespace. These are registration-derived props rather than global standard props.
123
-
124
- Framework and domain-adapter owners may extend the standard set through `ctx.slots.provideRoot()` or `ctx.uiSession.provide()` together with the corresponding `GlobalStandardProps`, `SessionStandardProps`, or `SessionMaybeStandardProps` declaration merge. A feature component should not create a React hook prop itself or add a global standard prop for entry-private data.
125
-
126
- ## Developer-provided injection
127
-
128
- The `inject` option on a registration is the ordinary feature-owned injection point. Its factory runs in the plugin's `apply` world, may close over injected Cordis services, and returns only the data and callbacks that the component needs. For a `session` slot it receives `sessionId`; for `session-maybe` it receives `sessionId | undefined`; when a store is declared it also receives the store's bound actions.
129
-
130
- A reserved `hooks` object in that return value accepts bare `getSnapshot`/`subscribe` sources. The renderer converts `hooks: { status }` into a `useStatus(selector)` component prop and caches the binding by source identity. Components do not receive the source itself and do not call `useSyncExternalStore` directly.
131
-
132
- The owner of a slot may put an `inject` face in the child declaration when every occupant needs the same capability. Plain members reach all occupants unchanged. Function-valued members inside its `hooks` object are hook factories; they receive the slot's standard props and optional per-render `hookContext`, then return the constrained hook exposed to the occupant. `conversation.chat.node` uses this mechanism to provide `useTurnData(key)` for the node currently being rendered.
133
-
134
- Use owner props for values already known at one render occurrence, registration `inject` for one entry's callbacks and private observables, slot-level `inject` for a capability controlled by the slot owner, and a declared store for mutable view state shared across entries or preserved across remounts. React nodes compose through child slots, not through injected values.
135
-
136
- <a id="current-hierarchy"></a>
137
-
138
- ## Conversation hierarchy
139
-
140
- The following Conversation paths distinguish declaration owners from reusable Factory roots; unrelated shell positions are omitted. An entry owns its declared children, while a Factory owns its child declarations for the lifetime of its registered definition. Bracketed names identify the default React components; a plain React descendant can render its owner's Slot. Factory calls are references to independent reusable definitions, not new Slot declarations.
141
-
142
- ```text
143
- root [AppFrame]
144
- └─ main[key=conversation] [ConversationPanel]
145
- └─ main.conversation [ConversationRoot / ConversationMainPanel]
146
- ├─ conversation.header [ConversationHeader]
147
- │ ├─ conversation.header.leading
148
- │ └─ conversation.session.header [ConversationSessionHeader]
149
- │ ├─ conversation.session.header.lineage
150
- │ ├─ conversation.session.header.actions
151
- │ ├─ conversation.session.header.utilities
152
- │ ├─ conversation.session.header.views.actions
153
- │ └─ conversation.session.header.corner
154
- └─ calls Factory: conversation.content
155
-
156
- Factory: conversation.content [ConversationContent]
157
- ├─ conversation.session [ConversationSession / DefaultConversationViews]
158
- │ └─ conversation.view
159
- │ ├─ id=chat [ChatView]
160
- │ │ ├─ conversation.chat.text-interaction [list]
161
- │ │ └─ conversation.chat.flow [ChatFlow]
162
- │ │ └─ conversation.chat.node [ChatNodeSeat dispatch]
163
- │ │ ├─ key=user [UserMessageNodeView]
164
- │ │ │ ├─ conversation.chat.user.before [chain]
165
- │ │ │ └─ calls Factory: conversation.chat.user.content
166
- │ │ ├─ key=steering [UserMessageNodeView]
167
- │ │ │ └─ calls Factory: conversation.chat.user.content
168
- │ │ ├─ key=assistant-step [AssistantNodeView / AssistantMarkdown]
169
- │ │ │ ├─ conversation.chat.message.images [MessageImages]
170
- │ │ │ └─ conversation.chat.reasoning.body [DefaultReasoningBody]
171
- │ │ │ └─ calls Factory: conversation.chat.reasoning.content
172
- │ │ ├─ key=tool-call [ToolCallTree]
173
- │ │ │ └─ tool.call.toolview
174
- │ │ │ └─ key=read_image [ReadImageRow / ToolRow]
175
- │ │ │ └─ tool.call.images [MessageImages]
176
- │ │ ├─ key=command-input [GoalCommandInputView]
177
- │ │ │ └─ calls Factory: conversation.user.text
178
- │ │ ├─ key=command [CommandNodeView]
179
- │ │ │ └─ conversation.chat.commandview
180
- │ │ └─ key=turn-tail [TurnTailNodeView]
181
- │ │ ├─ conversation.chat.turnTail
182
- │ │ └─ conversation.chat.assistant-actions
183
- │ └─ id=trajectory [TrajectoryView / TrajectoryTable]
184
- │ └─ conversation.trajectory.images [MessageImages]
185
- ├─ conversation.composer
186
- │ ├─ conversation.approval.detail
187
- │ └─ conversation.plan-review.actions
188
- ├─ conversation.composer.bar [InputBar]
189
- │ ├─ conversation.input.attachments
190
- │ ├─ conversation.input.permission
191
- │ ├─ conversation.input.plan
192
- │ ├─ conversation.input.model
193
- │ │ └─ conversation.input.model.label
194
- │ ├─ conversation.input.overlay
195
- │ ├─ conversation.composer.dock
196
- │ ├─ conversation.input.left
197
- │ └─ conversation.input.right
198
- ├─ conversation.input.dock
199
- │ └─ id=queue [QueueDock]
200
- │ └─ calls Factory: conversation.user.text
201
- ├─ conversation.hero.frame [hoc]
202
- │ └─ id=pixel-whale [PixelWhale]
203
- ├─ conversation.hero.brand.mark
204
- ├─ conversation.hero.workspace
205
- │ └─ conversation.hero.workspace.directoryFlow
206
- ├─ conversation.hero.agentPreset
207
- └─ conversation.hero.options
208
-
209
- Factory: conversation.chat.user.content [UserContent]
210
- ├─ conversation.chat.user.images [MessageImages]
211
- └─ calls Factory: conversation.user.text
212
-
213
- Factory: conversation.user.text [UserText]
214
- └─ conversation.user.text.node [keyed, inline]
215
-
216
- Factory: conversation.images.content [MessageImagesContent / ImageGallery]
217
- Factory: conversation.chat.reasoning.content [ReasoningContent / MarkdownText]
218
- ```
219
-
220
- All four image Slots default to `MessageImages`, which calls `conversation.images.content` with the caller's image references and authorized loader. User and output image replacements are independent. The `conversation.user.text` Factory is shared by user content, Queue, and Goal; its `inline: true` keyed Slot renders span anchors and inline error placeholders rather than block wrappers.
221
-
222
- The generated [Client inspect catalog](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/extensions/cordis-client-runner/src/client/slot-catalog.ts) covers all shell branches and is the exhaustive contract for each key: cardinality, scope, owner props, standard props, current occupants, declaration owner, and replacement risk. A running dynamic package can query the live tree and an exact key with `cordis_inspect what:"client"`; the source catalog is generated from `SlotMap` declarations and `slots.register()` call sites by `pnpm run gen-client-catalog`.
223
-
224
- ## Extension rules
225
-
226
- - Import another feature package only for declarations with `import type`; never import or re-export its runtime values.
227
- - Declare a new child slot only in the component that owns and renders that location. Other packages wait with `ctx.slots.inject()` and contribute through `ctx.slots.register()`.
228
- - Keep business and transport state in their owning Cordis services or Client models. Slot stores hold shared viewing and interaction state only.
229
- - Keep observable source and snapshot identities stable between changes. Republish through the same source whenever its value changes.
230
- - Pass JSON-compatible data and callbacks between UI domains. The `hooks` compartment is the sole exception for bare observables; React content travels through slots.
231
- - Treat `single` and an occupied keyed cell as replacement points. Use fresh list or hoc ids, or an unoccupied key, for additive extensions.
1
+ ---
2
+ editSource: "docs/subsystems/slots.md"
3
+ rawMarkdownPath: "en/reference/subsystems/slots.md"
4
+ outline: [2,3]
5
+ ---
6
+
7
+ # Web Client Slots
8
+
9
+ Slots are the Web Client's typed React composition system. [`dsh-client-ui-slots`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-slots/README.md) defines the React-free registry and type algebra; [`dsh-client-ui-renderer`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-renderer/README.md) binds observable sources to hooks, renders the tree, and owns React contexts internally. A feature plugin contributes UI through `ctx.slots.register()` and never imports another feature plugin's component.
10
+
11
+ This page documents slot ownership, component inputs, extension APIs, and the shipped hierarchy. The surrounding boot, Remote, Client model, and Conversation paths are in [Web Client architecture](./web-client.md).
12
+
13
+ `plugins.bundle.config` supplies bundle detail configuration, keyed by npm package name. `plugins.bundle.activation` renders optional guidance after user-requested enablement, with owner callbacks to dismiss or open that bundle’s details. `conversation.input.activity` supplies one action between the model selector and Send, with toolbar expansion released on unmount.
14
+
15
+ The plugin catalog declares `plugins.add.actions`, a root-scoped list for `MenuItemButton` rows after installation in the Add plugin menu. Its owner supplies `onDismiss()` to close the menu before starting an action. The slot follows the owning Plugins page declaration lifetime.
16
+
17
+ The root-scoped lists `sidebar.panellist.actions`, `conversation.session.header.views.actions`, and `sidebar.right.tab.guide.actions` supply the rows of the More menus after the panel rows, the View tabs, and the right-sidebar guide cards. A region draws its More button and menu only while its list has registrations, and passes the customizable entries with their pin state, `onOpen`, `onPinnedChange`, and `onDismiss`. Panel and View entries also carry optional `active` state for the current selection, independently of pin state. The `sidebar.panel.icon` root-scoped factory owns the `sidebar.panellist` list and renders its registered icon by `id`, `size`, and `active` for both sidebar rows and More entries. Each region keeps its own unpinned entry ids in memory; [`ui-entry-customization`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-entry-customization/README.md) registers the shipped rows.
18
+
19
+ [ui-workspace](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-workspace/README.md#understand-the-implementation) documents Session-row extension positions, visibility, and keyboard behavior.
20
+
21
+ [ui-settings](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-settings/README.md#filling-the-settings-slots) documents the settings page and navigation-icon extension points.
22
+
23
+ ## Declaration and lifecycle
24
+
25
+ `SlotMap` is the compile-time registry. A package declaration-merges the key, cardinality, scope, owner props, keyed props, and optional slot-level inject face. The runtime declaration is the matching `children` entry on the component that owns the render location.
26
+
27
+ Declaring a child has three effects: it makes the child key live, authorizes that parent entry's `renderSlot` or `renderSlotChain` call, and records the runtime dispatch specification. One live entry owns each declaration. Registering into an undeclared slot or declaring a child already owned elsewhere fails during plugin activation.
28
+
29
+ `root` is the only built-in declaration and the only key rendered through the Cordis service itself. `ui-renderer` calls `ctx.slots.renderSlot('root', {})`; every descendant is rendered through the `renderSlot` or `renderSlotChain` prop of the entry that declared it.
30
+
31
+ Registrations and declarations follow Cordis effect lifetimes. Disposing an entry removes its contribution and recursively collapses the child slots it declared. A feature that contributes into another package's slot therefore uses `ctx.slots.inject(key, callback)`: the callback runs for each declaration lifetime, its effects are removed when the owner collapses, and it runs again if the owner is mounted again.
32
+
33
+ ```tsx ignore-check
34
+ import type { Context } from '@deepseek-ai/cordis'
35
+ import type {} from '@deepseek-ai/dsh-client-ui-conversation/client'
36
+ import type {} from '@deepseek-ai/dsh-client-ui-session/client'
37
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
38
+
39
+ type HeaderActionProps = PropsRuntime<'conversation.session.header.actions'>
40
+
41
+ function HeaderAction({ useSession }: HeaderActionProps) {
42
+ const running = useSession(snapshot => snapshot.running)
43
+ return <button disabled={running}>Review</button>
44
+ }
45
+
46
+ export const inject = ['slots']
47
+
48
+ export function apply(ctx: Context): void {
49
+ ctx.slots.inject('conversation.session.header.actions', () =>
50
+ ctx.slots.register({
51
+ name: 'conversation.session.header.actions',
52
+ id: 'review',
53
+ order: 100,
54
+ }, HeaderAction))
55
+ }
56
+ ```
57
+
58
+ ## Cardinality and scope
59
+
60
+ The slot declaration fixes two independent axes.
61
+
62
+ | Axis | Value | Meaning |
63
+ |---|---|---|
64
+ | cardinality | `single` | One cell. The active priority winner renders. Use a child slot instead of treating this as an additive list. |
65
+ | cardinality | `list` | Cells are addressed by required `id` and ordered by `order`, then registration order. |
66
+ | cardinality | `keyed` | The owner dispatches an `entryKey`; the matching cell renders with any key-specific props. |
67
+ | cardinality | `chain` | Each entry supplies a pure `select(owner)` function. The first non-null result in priority order renders and receives that result as `matched`; otherwise the owner fallback renders. |
68
+ | cardinality | `hoc` | Entries nest around the owner's `renderSlot(key, owner, { children })` content, lowest outermost; an optional `key` selects layers by the owner's `entryKey`. See [Hoc layers](#hoc-layers). |
69
+ | scope | `root` | One root-scoped component and store instance. |
70
+ | scope | `session-maybe` | Inherits the surrounding Provider binding but stays renderable without one; Session values are optional. |
71
+ | scope | `session` | Requires a resolved surrounding Provider binding and receives definite Session values. |
72
+
73
+ `priority` is a shadowing rank for `single`, `list`, `keyed`, and `hoc` cells and an election order for `chain`. Lower values run or render first. Ordinary additive contributions should choose a fresh list or hoc `id`, or keyed `key`; intentionally reusing a shipped cell replaces its presentation.
74
+
75
+ <a id="hoc-layers"></a>
76
+
77
+ ### Hoc layers
78
+
79
+ A hoc entry is a layer addressed by its required `id` and optional `key`. A layer without `key` is a wildcard that applies to every dispatch; a layer with `key` applies only when the owner passes the same `entryKey` to `renderSlot`, and an owner that omits `entryKey` gets only wildcard layers. Each `(key, id)` pair, with the wildcard as its own key, is one shadowing cell; within one `id`, an exact-key layer replaces the wildcard layer for that key.
80
+
81
+ Layers nest by ascending `order`, then `priority`, then registration order, lowest outermost. Each layer receives the same owner props plus the next inner layer as `children`, the owner's content at the innermost, and renders it at most once; a layer that omits it replaces everything inside it. Owner props must not use the name `children`. Omitted `children` renders the layers around nothing, and with no applicable layer the content renders unchanged.
82
+
83
+ - Remounting: adding or removing a layer that applies to a dispatch remounts the content inside it; a `session` or `session-maybe` layer also remounts it when its Session binding changes. Outlets that dispatch the same key share one compiled layer chain, so a registration for another key does not remount their content; an outlet that switches its `entryKey` switches chains and remounts its content even when the same layers apply.
84
+ - Errors: a crashed layer reports its error and renders its `children` at the occurrence that failed, for the rest of that occurrence's mount even when its owner props change. The layer stays registered, so other occurrences, including those dispatching the same key, keep it, and a remounted occurrence renders it again. An error thrown by the wrapped content passes every layer and is reported against none; a layer that wraps its `children` in its own error boundary catches it as an internal wrapper error rather than the original.
85
+ - Layout: the outlet inserts a `display: contents` `[data-slot]` element between the owner and its content, so owner selectors cannot rely on the content being a direct child. A layer that wraps its `children` must not create a box of its own unless its slot documents otherwise — for example, use `display: contents` — or the content leaves its parent's layout.
86
+
87
+ The [context-menu plugin](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-context-menu/README.md) contributes `useContextMenu` through `provideRoot`; every scope receives the same plugin-owned trigger factory. Its prop and retained handlers retire when the provider unloads. Its root-scoped keyed `contextMenu.icon` Slot renders business-owned icons from action metadata.
88
+
89
+ ## Component inputs
90
+
91
+ A registered component receives inputs assembled at its binding site. Components derive these types rather than copying their members.
92
+
93
+ | Input | Declared by | Component type |
94
+ |---|---|---|
95
+ | owner values and standard scope values | the `SlotMap` row and installed scope adapters | `PropsRuntime<K>` |
96
+ | authorized child renderers | the registration's `children` keys | `PropsRenderSlots<S>` |
97
+ | selector hook and mutation callbacks for shared view state | the registration's `store` | `PropsStore<H>` |
98
+ | private data, callbacks, and observable hooks | the registration's `inject` factory | `InjectFace<I>` |
99
+ | localized `t` function | the registration's `locale` namespace | `PropsLocale<N>` |
100
+ | selected chain value | the registration's `select` result | `matched` through `ComposedProps` |
101
+ | wrapped owner content | the `SlotMap` row's `hoc` kind | `children` through `ComposedProps` |
102
+
103
+ `SessionProvider` is also present in `PropsRenderSlots` when an entry declares a `session` or `session-maybe` child. With no `session` prop it inherits the surrounding binding; an explicit `SessionReference` or `undefined` overrides only that subtree. The Provider does not key its whole body. A strict `session` entry remounts when its binding generation changes. A blank `session-maybe` entry adopts its first binding without remounting, then remounts for a later generation or a return to absence.
104
+
105
+ Components never receive `ctx`. Parent-owned point-in-time values enter through the owner argument to `renderSlot`; shared view state uses a declared store; services and model objects stay in the `apply` closure and are projected into callbacks or observable sources.
106
+
107
+ ## Framework-provided hooks
108
+
109
+ The shipped adapters add these standard props. They are available according to the target slot's scope, independent of which package registered the component.
110
+
111
+ | Availability | Props | Owner |
112
+ |---|---|---|
113
+ | every scope | `useSessions`, `useSessionRetainInfo`, `useSessionAccess` | `ui-session` |
114
+ | every scope | `useSessionStatus` | `ui-session-status` |
115
+ | every scope | `useWorkspaces`, `useWorkspaceAccess` | `ui-workspace` |
116
+ | every scope | `useRemoteAccess` (the `global` resource) | `api-remote-access` |
117
+ | every scope | `usePanelInfo` | `ui-layout` |
118
+ | `session` | `sessionId`, `useSession`, `useProjection`, `useAccess` (the bound Session's answer) | `ui-session` |
119
+ | `session-maybe` | optional `sessionId`, `useSession`, `useProjection`, `useAccess` results | `ui-session` |
120
+ | `session` | `useConversation`, `useInput`, `inputActions` | `ui-conversation` |
121
+ | `session-maybe` | optional `useConversation`, `useInput`, `inputActions` results | `ui-conversation` |
122
+ | `session` | `useChat` | `ui-chat` |
123
+ | `session` | `useTrajectory` | `ui-trajectory` |
124
+
125
+ The renderer also creates `useStore` from a declared store and `t` from a declared locale namespace. These are registration-derived props rather than global standard props.
126
+
127
+ Framework and domain-adapter owners may extend the standard set through `ctx.slots.provideRoot()` or `ctx.uiSession.provide()` together with the corresponding `GlobalStandardProps`, `SessionStandardProps`, or `SessionMaybeStandardProps` declaration merge. A feature component should not create a React hook prop itself or add a global standard prop for entry-private data.
128
+
129
+ ## Developer-provided injection
130
+
131
+ The `inject` option on a registration is the ordinary feature-owned injection point. Its factory runs in the plugin's `apply` world, may close over injected Cordis services, and returns only the data and callbacks that the component needs. For a `session` slot it receives `sessionId`; for `session-maybe` it receives `sessionId | undefined`; when a store is declared it also receives the store's bound actions.
132
+
133
+ A reserved `hooks` object in that return value accepts bare `getSnapshot`/`subscribe` sources. The renderer converts `hooks: { status }` into a `useStatus(selector)` component prop and caches the binding by source identity. Components do not receive the source itself and do not call `useSyncExternalStore` directly.
134
+
135
+ The owner of a slot may put an `inject` face in the child declaration when every occupant needs the same capability. Plain members reach all occupants unchanged. Function-valued members inside its `hooks` object are hook factories; they receive the slot's standard props and optional per-render `hookContext`, then return the constrained hook exposed to the occupant. `conversation.chat.node` uses this mechanism to provide `useTurnData(key)` for the node currently being rendered.
136
+
137
+ Use owner props for values already known at one render occurrence, registration `inject` for one entry's callbacks and private observables, slot-level `inject` for a capability controlled by the slot owner, and a declared store for mutable view state shared across entries or preserved across remounts. React nodes compose through child slots, not through injected values.
138
+
139
+ <a id="current-hierarchy"></a>
140
+
141
+ ## Conversation hierarchy
142
+
143
+ The following Conversation paths distinguish declaration owners from reusable Factory roots; unrelated shell positions are omitted. An entry owns its declared children, while a Factory owns its child declarations for the lifetime of its registered definition. Bracketed names identify the default React components; a plain React descendant can render its owner's Slot. Factory calls are references to independent reusable definitions, not new Slot declarations.
144
+
145
+ ```text
146
+ root [AppFrame]
147
+ └─ main[key=conversation] [ConversationPanel]
148
+ └─ main.conversation [ConversationRoot / ConversationMainPanel]
149
+ ├─ conversation.header [ConversationHeader]
150
+ │ ├─ conversation.header.leading
151
+ │ └─ conversation.session.header [ConversationSessionHeader]
152
+ │ ├─ conversation.session.header.lineage
153
+ │ ├─ conversation.session.header.actions
154
+ │ ├─ conversation.session.header.utilities
155
+ │ ├─ conversation.session.header.views.actions
156
+ │ └─ conversation.session.header.corner
157
+ └─ calls Factory: conversation.content
158
+
159
+ Factory: conversation.content [ConversationContent]
160
+ ├─ conversation.session [ConversationSession / DefaultConversationViews]
161
+ │ └─ conversation.view
162
+ │ ├─ id=chat [ChatView]
163
+ │ │ ├─ conversation.chat.text-interaction [list]
164
+ │ │ ├─ conversation.chat.markdown.fence [hoc, keyed by fence language]
165
+ │ │ └─ conversation.chat.flow [ChatFlow]
166
+ │ │ └─ conversation.chat.node [ChatNodeSeat dispatch]
167
+ │ │ ├─ key=user [UserMessageNodeView]
168
+ │ │ │ ├─ conversation.chat.user.before [chain]
169
+ │ │ │ └─ calls Factory: conversation.chat.user.content
170
+ │ │ ├─ key=steering [UserMessageNodeView]
171
+ │ │ │ └─ calls Factory: conversation.chat.user.content
172
+ │ │ ├─ key=assistant-step [AssistantNodeView / AssistantMarkdown]
173
+ │ │ │ ├─ conversation.chat.message.images [MessageImages]
174
+ │ │ │ └─ conversation.chat.reasoning.body [DefaultReasoningBody]
175
+ │ │ │ └─ calls Factory: conversation.chat.reasoning.content
176
+ │ │ ├─ key=tool-call [ToolCallTree]
177
+ │ │ │ └─ tool.call.toolview
178
+ │ │ │ └─ key=read_image [ReadImageRow / ToolRow]
179
+ │ │ │ └─ tool.call.images [MessageImages]
180
+ │ │ ├─ key=command-input [GoalCommandInputView]
181
+ │ │ │ └─ calls Factory: conversation.user.text
182
+ │ │ ├─ key=command [CommandNodeView]
183
+ │ │ │ └─ conversation.chat.commandview
184
+ │ │ └─ key=turn-tail [TurnTailNodeView]
185
+ │ │ ├─ conversation.chat.turnTail
186
+ │ │ └─ conversation.chat.assistant-actions
187
+ │ └─ id=trajectory [TrajectoryView / TrajectoryTable]
188
+ │ └─ conversation.trajectory.images [MessageImages]
189
+ ├─ conversation.composer
190
+ │ ├─ conversation.approval.detail
191
+ │ └─ conversation.plan-review.actions
192
+ ├─ conversation.composer.bar [InputBar]
193
+ │ ├─ conversation.input.attachments
194
+ │ ├─ conversation.input.permission
195
+ │ ├─ conversation.input.plan
196
+ │ ├─ conversation.input.model
197
+ │ │ └─ conversation.input.model.label
198
+ │ ├─ conversation.input.overlay
199
+ │ ├─ conversation.composer.dock
200
+ │ ├─ conversation.input.left
201
+ │ └─ conversation.input.right
202
+ ├─ conversation.input.dock
203
+ │ └─ id=queue [QueueDock]
204
+ │ └─ calls Factory: conversation.user.text
205
+ ├─ conversation.hero.frame [hoc]
206
+ │ └─ id=pixel-whale [PixelWhale]
207
+ ├─ conversation.hero.brand.mark
208
+ ├─ conversation.hero.workspace
209
+ │ └─ conversation.hero.workspace.directoryFlow
210
+ ├─ conversation.hero.agentPreset
211
+ └─ conversation.hero.options
212
+
213
+ Factory: conversation.chat.user.content [UserContent]
214
+ ├─ conversation.chat.user.images [MessageImages]
215
+ └─ calls Factory: conversation.user.text
216
+
217
+ Factory: conversation.user.text [UserText]
218
+ └─ conversation.user.text.node [keyed, inline]
219
+
220
+ Factory: conversation.images.content [MessageImagesContent / ImageGallery]
221
+ Factory: conversation.chat.reasoning.content [ReasoningContent / MarkdownText]
222
+ ```
223
+
224
+ All four image Slots default to `MessageImages`, which calls `conversation.images.content` with the caller's image references and authorized loader. User and output image replacements are independent. The `conversation.user.text` Factory is shared by user content, Queue, and Goal; its `inline: true` keyed Slot renders span anchors and inline error placeholders rather than block wrappers.
225
+
226
+ The generated [Client inspect catalog](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/extensions/cordis-client-runner/src/client/slot-catalog.ts) covers all shell branches and is the exhaustive contract for each key: cardinality, scope, owner props, standard props, current occupants, declaration owner, and replacement risk. A running dynamic package can query the live tree and an exact key with `cordis_inspect what:"client"`; the source catalog is generated from `SlotMap` declarations and `slots.register()` call sites by `pnpm run gen-client-catalog`.
227
+
228
+ ## Extension rules
229
+
230
+ - Import another feature package only for declarations with `import type`; never import or re-export its runtime values.
231
+ - Declare a new child slot only in the component that owns and renders that location. Other packages wait with `ctx.slots.inject()` and contribute through `ctx.slots.register()`.
232
+ - Keep business and transport state in their owning Cordis services or Client models. Slot stores hold shared viewing and interaction state only.
233
+ - Keep observable source and snapshot identities stable between changes. Republish through the same source whenever its value changes.
234
+ - Pass JSON-compatible data and callbacks between UI domains. The `hooks` compartment is the sole exception for bare observables; React content travels through slots.
235
+ - Treat `single` and an occupied keyed cell as replacement points. Use fresh list or hoc ids, or an unoccupied key, for additive extensions.