dsh-plugin-dev-kb 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.en.md +6 -6
- package/README.md +6 -6
- package/kb/INDEX.md +21 -5
- package/kb/README.md +11 -10
- package/kb/extra/AGENTS.md +4 -4
- package/kb/extra/cookbook/adding-a-remote-api.md +197 -0
- package/kb/extra/cookbook/adding-a-remote-api.zh.md +197 -0
- package/kb/extra/cookbook/adding-a-vendored-package.md +2 -2
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +2 -2
- package/kb/extra/deepseek-llm-api-wire-extensions.md +163 -0
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +163 -0
- package/kb/extra/development.md +8 -14
- package/kb/extra/development.zh.md +8 -14
- package/kb/extra/event-producer-consumer.md +55 -48
- package/kb/extra/event-producer-consumer.zh.md +58 -51
- package/kb/extra/glossary.md +1 -1
- package/kb/extra/glossary.zh.md +1 -1
- package/kb/extra/graph-atlas.md +0 -2
- package/kb/extra/graph-atlas.zh.md +0 -2
- package/kb/extra/i18n/README.md +4 -4
- package/kb/extra/i18n/README.zh.md +4 -4
- package/kb/extra/i18n/style-samples.md +2 -2
- package/kb/extra/module-graph.md +646 -926
- package/kb/extra/module-graph.zh.md +648 -928
- package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +2 -2
- package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +2 -2
- package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
- package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
- package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
- package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
- package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
- package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +1 -1
- package/kb/extra/rescope.md +2 -2
- package/kb/extra/rescope.zh.md +2 -2
- package/kb/extra/subsystems/agent-team.md +28 -4
- package/kb/extra/subsystems/agent-team.zh.md +28 -4
- package/kb/extra/subsystems/attachment.md +168 -7
- package/kb/extra/subsystems/attachment.zh.md +168 -7
- package/kb/extra/subsystems/extensions.md +18 -0
- package/kb/extra/subsystems/extensions.zh.md +18 -0
- package/kb/extra/subsystems/feedback.md +4 -4
- package/kb/extra/subsystems/feedback.zh.md +4 -4
- package/kb/extra/subsystems/todo.md +32 -0
- package/kb/extra/subsystems/todo.zh.md +32 -0
- package/kb/extra/subsystems/webhook.md +70 -0
- package/kb/extra/subsystems/webhook.zh.md +70 -0
- package/kb/extra/testing.md +15 -10
- package/kb/extra/testing.zh.md +13 -8
- package/kb/extra/web-styling.md +4 -0
- package/kb/extra/web-styling.zh.md +4 -0
- package/kb/meta/search-index.json +309 -177
- package/kb/meta/site-pages.txt +183 -167
- package/kb/meta/source.json +5 -5
- package/kb/meta/topics.md +14 -6
- package/kb/site/develop/basic/publish.md +2 -2
- package/kb/site/develop/basic/tool.md +1 -1
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +5 -4
- package/kb/site/develop/framework/events.md +1 -1
- package/kb/site/develop/practice/dynamic-cordis.md +17 -0
- package/kb/site/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/develop/basic/publish.md +2 -2
- package/kb/site/en/develop/basic/tool.md +1 -1
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +5 -4
- package/kb/site/en/develop/framework/events.md +1 -1
- package/kb/site/en/develop/practice/dynamic-cordis.md +17 -0
- package/kb/site/en/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/guide/github-review.md +104 -0
- package/kb/site/en/guide/mcp-memory.md +103 -0
- package/kb/site/en/guide/network-proxy.md +87 -0
- package/kb/site/en/guide/providers.md +70 -17
- package/kb/site/en/guide/python-sdk.md +80 -34
- package/kb/site/en/guide/schedule.md +23 -0
- package/kb/site/en/reference/agent-lifecycle.md +6 -4
- package/kb/{extra → site/en/reference}/api-gateway.md +12 -10
- package/kb/site/en/reference/capability-seams.md +128 -73
- package/kb/site/en/reference/config-catalog.md +481 -360
- package/kb/site/en/reference/cookbook/adding-a-package.md +3 -4
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +12 -10
- package/kb/site/en/reference/cookbook/adding-a-tool.md +11 -4
- package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +1 -1
- package/kb/site/en/reference/cookbook/extension-cookbook.md +20 -17
- package/kb/site/en/reference/cordis-api/inherited.md +1 -1
- package/kb/site/en/reference/cordis-primer.md +2 -1
- package/kb/site/en/reference/index.md +30 -11
- package/kb/site/en/reference/persistence-catalog.md +148 -80
- package/kb/site/en/reference/subsystems/approval.md +10 -10
- package/kb/site/en/reference/subsystems/client-modules.md +58 -16
- package/kb/site/en/reference/subsystems/code-runtime.md +10 -6
- package/kb/site/en/reference/subsystems/commands.md +25 -16
- package/kb/site/en/reference/subsystems/compaction.md +11 -11
- package/kb/site/en/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
- package/kb/site/en/reference/subsystems/core.md +156 -17
- package/kb/site/en/reference/subsystems/credentials.md +44 -3
- package/kb/site/en/reference/subsystems/filesystem.md +12 -2
- package/kb/site/en/reference/subsystems/goal.md +1 -1
- package/kb/site/en/reference/subsystems/index.md +7 -2
- package/kb/site/en/reference/subsystems/jobs.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +154 -12
- package/kb/site/en/reference/subsystems/permission-presets.md +6 -6
- package/kb/site/en/reference/subsystems/persistence.md +185 -175
- package/kb/site/en/reference/subsystems/plan.md +2 -2
- package/kb/site/en/reference/subsystems/sandbox.md +2 -0
- package/kb/site/en/reference/subsystems/schedule.md +9 -3
- package/kb/site/en/reference/subsystems/session-projection.md +115 -48
- package/kb/site/en/reference/subsystems/session-query.md +28 -14
- package/kb/site/en/reference/subsystems/session-reference.md +53 -8
- package/kb/site/en/reference/subsystems/session-telemetry.md +8 -8
- package/kb/site/en/reference/subsystems/session-title.md +6 -6
- package/kb/site/en/reference/subsystems/session.md +401 -99
- package/kb/site/en/reference/subsystems/settings.md +101 -6
- package/kb/site/en/reference/subsystems/skills.md +23 -0
- package/kb/site/en/reference/subsystems/slots.md +178 -0
- package/kb/site/en/reference/subsystems/spill.md +2 -2
- package/kb/site/en/reference/subsystems/storage.md +34 -3
- package/kb/site/en/reference/subsystems/subagent.md +122 -109
- package/kb/site/en/reference/subsystems/system-prompt.md +17 -4
- package/kb/site/en/reference/subsystems/token-meter.md +27 -12
- package/kb/site/en/reference/subsystems/tools.md +39 -39
- package/kb/site/en/reference/subsystems/typert.md +62 -55
- package/kb/site/en/reference/subsystems/user-questions.md +33 -33
- package/kb/site/en/reference/subsystems/web-client.md +98 -0
- package/kb/site/en/reference/subsystems/web-server.md +11 -5
- package/kb/site/en/reference/subsystems/web.md +7 -1
- package/kb/site/en/reference/subsystems/workspace.md +102 -9
- package/kb/site/en/reference/tool-catalog.md +86 -82
- package/kb/site/en/reference/tool-execution-pipeline.md +1 -1
- package/kb/site/guide/github-review.md +104 -0
- package/kb/site/guide/mcp-memory.md +103 -0
- package/kb/site/guide/network-proxy.md +87 -0
- package/kb/site/guide/providers.md +70 -17
- package/kb/site/guide/python-sdk.md +87 -41
- package/kb/site/guide/schedule.md +23 -0
- package/kb/site/reference/agent-lifecycle.md +6 -4
- package/kb/{extra/api-gateway.zh.md → site/reference/api-gateway.md} +12 -10
- package/kb/site/reference/capability-seams.md +128 -73
- package/kb/site/reference/config-catalog.md +481 -360
- package/kb/site/reference/cookbook/adding-a-package.md +3 -4
- package/kb/site/reference/cookbook/adding-a-settings-card.md +12 -10
- package/kb/site/reference/cookbook/adding-a-tool.md +11 -4
- package/kb/site/reference/cookbook/adding-an-llm-adapter.md +1 -1
- package/kb/site/reference/cookbook/extension-cookbook.md +20 -17
- package/kb/site/reference/cordis-api/inherited.md +1 -1
- package/kb/site/reference/cordis-primer.md +2 -1
- package/kb/site/reference/index.md +30 -11
- package/kb/site/reference/persistence-catalog.md +148 -80
- package/kb/site/reference/subsystems/approval.md +10 -10
- package/kb/site/reference/subsystems/client-modules.md +58 -16
- package/kb/site/reference/subsystems/code-runtime.md +10 -6
- package/kb/site/reference/subsystems/commands.md +25 -16
- package/kb/site/reference/subsystems/compaction.md +11 -11
- package/kb/site/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
- package/kb/site/reference/subsystems/core.md +156 -17
- package/kb/site/reference/subsystems/credentials.md +44 -3
- package/kb/site/reference/subsystems/filesystem.md +12 -2
- package/kb/site/reference/subsystems/goal.md +1 -1
- package/kb/site/reference/subsystems/index.md +7 -2
- package/kb/site/reference/subsystems/jobs.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +154 -12
- package/kb/site/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/reference/subsystems/persistence.md +184 -174
- package/kb/site/reference/subsystems/plan.md +2 -2
- package/kb/site/reference/subsystems/schedule.md +9 -3
- package/kb/site/reference/subsystems/session-projection.md +115 -48
- package/kb/site/reference/subsystems/session-query.md +28 -14
- package/kb/site/reference/subsystems/session-reference.md +53 -8
- package/kb/site/reference/subsystems/session-telemetry.md +8 -8
- package/kb/site/reference/subsystems/session-title.md +6 -6
- package/kb/site/reference/subsystems/session.md +401 -99
- package/kb/site/reference/subsystems/settings.md +101 -6
- package/kb/site/reference/subsystems/skills.md +23 -0
- package/kb/site/reference/subsystems/slots.md +178 -0
- package/kb/site/reference/subsystems/spill.md +2 -2
- package/kb/site/reference/subsystems/storage.md +34 -3
- package/kb/site/reference/subsystems/subagent.md +122 -109
- package/kb/site/reference/subsystems/system-prompt.md +17 -4
- package/kb/site/reference/subsystems/token-meter.md +27 -12
- package/kb/site/reference/subsystems/tools.md +39 -39
- package/kb/site/reference/subsystems/typert.md +62 -55
- package/kb/site/reference/subsystems/user-questions.md +33 -33
- package/kb/site/reference/subsystems/web-client.md +98 -0
- package/kb/site/reference/subsystems/web-server.md +11 -5
- package/kb/site/reference/subsystems/web.md +7 -1
- package/kb/site/reference/subsystems/workspace.md +102 -9
- package/kb/site/reference/tool-catalog.md +85 -81
- package/kb/site/reference/tool-execution-pipeline.md +1 -1
- package/package.json +2 -2
- package/skills/dsh-plugin-dev-kb.md +8 -6
|
@@ -54,7 +54,7 @@ interface SettingsRegisterOptions<T> {
|
|
|
54
54
|
|
|
55
55
|
`validate` runs after the schema admits a value, so it sees defaults and the composition base exactly as the owner will. `dsh-llm-pi-ai` uses it to refuse a provider profile it could not serve at the write that produced it, rather than storing one that would disable every route in its namespace.
|
|
56
56
|
|
|
57
|
-
`applies` is a UI hint, not a mechanism: a `restart` owner
|
|
57
|
+
`applies` is a UI hint, not a mechanism: a `restart` owner never watches, so its value is read once at construction and configuration surfaces can badge the pending change.
|
|
58
58
|
|
|
59
59
|
```ts type-equiv
|
|
60
60
|
/** When a namespace's changes take effect for its owner. */
|
|
@@ -164,6 +164,10 @@ Every committed change — an in-process write or an externally observed provide
|
|
|
164
164
|
type SettingsUpdateSource = 'update' | 'provider'
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
## Native document operations
|
|
168
|
+
|
|
169
|
+
`SettingsDocumentOpenValue` confirms that `settings/openSettingsDocument` prepared the provider-owned document and handed it to the native text editor. `AgentPresetDirectoryOpenValue` reports either a completed native handoff or the resolved user-preset directory when desktop opening is unavailable. Neither operation accepts a browser-selected Host path.
|
|
170
|
+
|
|
167
171
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
168
172
|
|
|
169
173
|
<a id="cordis-surface"></a>
|
|
@@ -196,8 +200,22 @@ prepareDocument(): Promise<string | undefined>
|
|
|
196
200
|
* @param schema - schemastery schema resolving this namespace's value.
|
|
197
201
|
* @param options - composition `base` layer and effect timing.
|
|
198
202
|
* @returns the owner scope for reads, observation, and updates.
|
|
203
|
+
* @throws {TypeError} when `ns` is not a lowercase hyphenated identifier.
|
|
204
|
+
*/
|
|
205
|
+
register<const Namespace extends string, T>( ns: Namespace & SettingsNamespaceInput<Namespace>, schema: z<T>, options?: SettingsRegisterOptions<T>, ): SettingsScope<T>
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Attach one optional-settings consumer to this provider. The consumer
|
|
209
|
+
* registers its composition entry as the base layer while this provider is
|
|
210
|
+
* present, then falls back to that entry if the provider detaches.
|
|
211
|
+
* @param owner - consumer context whose unload suppresses fallback work.
|
|
212
|
+
* @param ns - consumer-owned settings namespace.
|
|
213
|
+
* @param schema - schema resolving the namespace.
|
|
214
|
+
* @param entry - composition entry used as the base and fallback value.
|
|
215
|
+
* @param hooks - source sink, change notification, and optional validation.
|
|
216
|
+
* @throws {TypeError} when `ns` is not a lowercase hyphenated identifier.
|
|
199
217
|
*/
|
|
200
|
-
|
|
218
|
+
installSection<const Namespace extends string, T>( owner: Context, ns: Namespace & SettingsNamespaceInput<Namespace>, schema: z<T>, entry: T, hooks: SettingsSectionHooks<T>, ): void
|
|
201
219
|
|
|
202
220
|
/**
|
|
203
221
|
* Describe every registered namespace for configuration surfaces, including
|
|
@@ -212,8 +230,9 @@ describe(options?: SettingsDescribeOptions): SettingsDescriptor[]
|
|
|
212
230
|
* Read one registered namespace's resolved value.
|
|
213
231
|
* @param ns - the namespace to read.
|
|
214
232
|
* @returns the resolved value, or `undefined` while unregistered.
|
|
233
|
+
* @throws {TypeError} when `ns` is not a lowercase hyphenated identifier.
|
|
215
234
|
*/
|
|
216
|
-
get(ns:
|
|
235
|
+
get<const Namespace extends string>(ns: Namespace & SettingsNamespaceInput<Namespace>): unknown
|
|
217
236
|
|
|
218
237
|
/**
|
|
219
238
|
* Merge a patch into one registered namespace's user layer, validate the
|
|
@@ -225,8 +244,9 @@ get(ns: SettingsNamespace): unknown
|
|
|
225
244
|
* @param patch - plain-object patch over the user section.
|
|
226
245
|
* @param expectedRevision - the descriptor `revision` the caller read; a
|
|
227
246
|
* namespace that moved past it rejects with {@link SettingsConflictError}.
|
|
247
|
+
* @throws {TypeError} when `ns` is not a lowercase hyphenated identifier.
|
|
228
248
|
*/
|
|
229
|
-
async update(ns:
|
|
249
|
+
async update<const Namespace extends string>( ns: Namespace & SettingsNamespaceInput<Namespace>, patch: object, expectedRevision?: number, ): Promise<void>
|
|
230
250
|
|
|
231
251
|
/**
|
|
232
252
|
* Replace one registered namespace's user section wholesale, validate,
|
|
@@ -237,8 +257,9 @@ async update(ns: SettingsNamespace, patch: object, expectedRevision?: number): P
|
|
|
237
257
|
* @param section - the complete next user section.
|
|
238
258
|
* @param expectedRevision - the descriptor `revision` the caller read; a
|
|
239
259
|
* namespace that moved past it rejects with {@link SettingsConflictError}.
|
|
260
|
+
* @throws {TypeError} when `ns` is not a lowercase hyphenated identifier.
|
|
240
261
|
*/
|
|
241
|
-
async replace(ns:
|
|
262
|
+
async replace<const Namespace extends string>( ns: Namespace & SettingsNamespaceInput<Namespace>, section: object, expectedRevision?: number, ): Promise<void>
|
|
242
263
|
|
|
243
264
|
/**
|
|
244
265
|
* Apply path-addressed edits to one registered namespace's user section,
|
|
@@ -251,12 +272,86 @@ async replace(ns: SettingsNamespace, section: object, expectedRevision?: number)
|
|
|
251
272
|
* @param ops - ordered path edits; later ops observe earlier ones.
|
|
252
273
|
* @param expectedRevision - the descriptor `revision` the caller read; a
|
|
253
274
|
* namespace that moved past it rejects with {@link SettingsConflictError}.
|
|
275
|
+
* @throws {TypeError} when `ns` is not a lowercase hyphenated identifier.
|
|
254
276
|
*/
|
|
255
|
-
async mutate(ns:
|
|
277
|
+
async mutate<const Namespace extends string>( ns: Namespace & SettingsNamespaceInput<Namespace>, ops: readonly SettingsPathOp[], expectedRevision?: number, ): Promise<void>
|
|
256
278
|
```
|
|
257
279
|
|
|
258
280
|
Source: [`packages/settings/settings/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/settings/settings/src/index.ts)
|
|
259
281
|
|
|
282
|
+
<a id="ctxsettingscontroller--settingscontroller"></a>
|
|
283
|
+
|
|
284
|
+
### `ctx.settingsController` — `SettingsController`
|
|
285
|
+
|
|
286
|
+
Host service backing the generated `ctx.remote.settings` namespace. Every remote read uses `redactSecrets: true`, so a `role('secret')` field cannot ride a response. Writes expose the settings service's merge, replacement, and path-addressed operations, and classify every provider refusal as `settings/conflict` or `settings/rejected` with the service's message.
|
|
287
|
+
|
|
288
|
+
```ts cordis-catalog
|
|
289
|
+
/**
|
|
290
|
+
* Describe every registered namespace for a configuration page: redacted
|
|
291
|
+
* layered values plus the serialized schema the page renders its form from.
|
|
292
|
+
* @returns provider writability, local-document presence, and one view per namespace.
|
|
293
|
+
* @throws RemoteError when no settings provider is mounted.
|
|
294
|
+
*/
|
|
295
|
+
@Remote describe(): SettingsDescribeValue
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Report whether this deployment can open an authored Agent preset directory natively.
|
|
299
|
+
* @returns true when the matching open operation is available.
|
|
300
|
+
*/
|
|
301
|
+
@Remote canOpenAgentPresetDirectory(): boolean
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Merge a patch into one namespace's stored user section.
|
|
305
|
+
* @param ns - namespace key to write.
|
|
306
|
+
* @param patch - fields to merge into the user section.
|
|
307
|
+
* @param expectedRevision - revision the caller read; `undefined` writes unconditionally.
|
|
308
|
+
* @returns the namespace's redacted view after the write.
|
|
309
|
+
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
|
310
|
+
*/
|
|
311
|
+
@Remote update( ns: string, patch: Record<string, JsonValue>, expectedRevision: number | undefined, ): Promise<SettingsNamespaceView>
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Replace one namespace's stored user section wholesale.
|
|
315
|
+
* @param ns - namespace key to write.
|
|
316
|
+
* @param section - complete replacement user section.
|
|
317
|
+
* @param expectedRevision - revision the caller read; `undefined` writes unconditionally.
|
|
318
|
+
* @returns the namespace's redacted view after the write.
|
|
319
|
+
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
|
320
|
+
*/
|
|
321
|
+
@Remote replace( ns: string, section: Record<string, JsonValue>, expectedRevision: number | undefined, ): Promise<SettingsNamespaceView>
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Apply path-addressed edits to one namespace's user section, resolved against
|
|
325
|
+
* the section as stored rather than against whatever the caller last read,
|
|
326
|
+
* then answer with that namespace's new redacted view.
|
|
327
|
+
* @param ns - namespace key to write.
|
|
328
|
+
* @param ops - the edits to apply, in order.
|
|
329
|
+
* @param expectedRevision - revision the caller read; `undefined` writes unconditionally.
|
|
330
|
+
* @returns the namespace's redacted view after the write.
|
|
331
|
+
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
|
332
|
+
*/
|
|
333
|
+
@Remote async mutate( ns: string, ops: SettingsPathOpView[], expectedRevision: number | undefined, ): Promise<SettingsNamespaceView>
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Materialize the provider-owned settings document and open it in a native text editor.
|
|
337
|
+
* @param signal - caller lifetime; abort terminates preparation or the native command.
|
|
338
|
+
* @returns confirmation after the native opener accepts the document.
|
|
339
|
+
* @throws RemoteError when no document exists, preparation fails, or opening fails.
|
|
340
|
+
*/
|
|
341
|
+
@Remote async openSettingsDocument(signal: AbortSignal): Promise<SettingsDocumentOpenValue>
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Open one user-authored Agent preset directory or return its path when no native opener exists.
|
|
345
|
+
* @param agentPreset - preset id resolved against Host-owned roots.
|
|
346
|
+
* @param signal - caller lifetime; abort terminates the native command.
|
|
347
|
+
* @returns an opened confirmation or the resolved directory for text display.
|
|
348
|
+
* @throws RemoteError when the preset is missing, read-only, invalid, or cannot be opened.
|
|
349
|
+
*/
|
|
350
|
+
@Remote async openAgentPresetDirectory( agentPreset: string, signal: AbortSignal, ): Promise<AgentPresetDirectoryOpenValue>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Source: [`packages/api/settings-controller/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/settings-controller/src/index.ts)
|
|
354
|
+
|
|
260
355
|
<a id="settings-events"></a>
|
|
261
356
|
|
|
262
357
|
### `settings/*` events
|
|
@@ -237,6 +237,10 @@ Before each later model step, the consumer applies exact tool visibility and dig
|
|
|
237
237
|
|
|
238
238
|
The model-facing `skill({ name })` tool validates the kebab-case name, finds the summary in the invocation-neutral catalog, rejects it before loading unless `isModelInvocable` permits access, then rereads the complete definition for the calling agent cwd and rechecks the policy before returning content. It reports an unresolved skill as unknown or no longer available and returns a tool result containing `<skill_content name="...">`, `<skill_resources>`, and `<skill_instructions>`. `resourceBase` resolves explicitly referenced scripts, references, and assets only as needed; the loaded result does not enumerate a skill directory. Body-only edits therefore change later tool calls without producing catalog messages or rewriting earlier tool results.
|
|
239
239
|
|
|
240
|
+
## Browser Session catalog
|
|
241
|
+
|
|
242
|
+
`SkillListRequest` addresses one Session by `sessionId`; `SkillListValue` returns the user-invocable entries with name, description, optional usage guidance, and model-invocation availability. `SessionSkillCatalog` reads the Session cwd and recorded preset without activating an Agent. A live Agent may supply its scoped registry, while a cold Session uses the preset's standing scope.
|
|
243
|
+
|
|
240
244
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
241
245
|
|
|
242
246
|
<a id="cordis-surface"></a>
|
|
@@ -245,6 +249,25 @@ The model-facing `skill({ name })` tool validates the kebab-case name, finds the
|
|
|
245
249
|
|
|
246
250
|
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
|
247
251
|
|
|
252
|
+
<a id="ctxsessionskillcatalog--sessionskillcatalog"></a>
|
|
253
|
+
|
|
254
|
+
### `ctx.sessionSkillCatalog` — `SessionSkillCatalog`
|
|
255
|
+
|
|
256
|
+
Host service backing `ctx.remote.skills` without activating a cold Agent.
|
|
257
|
+
|
|
258
|
+
```ts cordis-catalog
|
|
259
|
+
/**
|
|
260
|
+
* List the user-invocable skills visible to one Session composition.
|
|
261
|
+
* @param request - Session identity whose cwd and preset select the catalog view.
|
|
262
|
+
* @param signal - caller lifetime carried by the Remote transport; admitted catalog reads retain their existing completion semantics.
|
|
263
|
+
* @returns user-invocable skill metadata without loading skill bodies.
|
|
264
|
+
* @throws RemoteError when the Session cannot be inspected or no registry can serve it.
|
|
265
|
+
*/
|
|
266
|
+
@Remote async list(request: SkillListRequest, signal: AbortSignal): Promise<SkillListValue>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Source: [`packages/api/session-controller/src/skill-catalog.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/session-controller/src/skill-catalog.ts)
|
|
270
|
+
|
|
248
271
|
<a id="ctxskills--skillregistry"></a>
|
|
249
272
|
|
|
250
273
|
### `ctx.skills` — `SkillRegistry`
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
editSource: "docs/subsystems/slots.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Client Slots
|
|
7
|
+
|
|
8
|
+
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.
|
|
9
|
+
|
|
10
|
+
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).
|
|
11
|
+
|
|
12
|
+
## Declaration and lifecycle
|
|
13
|
+
|
|
14
|
+
`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.
|
|
15
|
+
|
|
16
|
+
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.
|
|
17
|
+
|
|
18
|
+
`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.
|
|
19
|
+
|
|
20
|
+
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.
|
|
21
|
+
|
|
22
|
+
```tsx ignore-check
|
|
23
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
24
|
+
import type {} from '@deepseek-ai/dsh-client-ui-conversation/client'
|
|
25
|
+
import type {} from '@deepseek-ai/dsh-client-ui-session/client'
|
|
26
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
|
|
27
|
+
|
|
28
|
+
type HeaderActionProps = PropsRuntime<'conversation.session.header.actions'>
|
|
29
|
+
|
|
30
|
+
function HeaderAction({ useSession }: HeaderActionProps) {
|
|
31
|
+
const running = useSession(snapshot => snapshot.running)
|
|
32
|
+
return <button disabled={running}>Review</button>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const inject = ['slots']
|
|
36
|
+
|
|
37
|
+
export function apply(ctx: Context): void {
|
|
38
|
+
ctx.slots.inject('conversation.session.header.actions', () =>
|
|
39
|
+
ctx.slots.register({
|
|
40
|
+
name: 'conversation.session.header.actions',
|
|
41
|
+
id: 'review',
|
|
42
|
+
order: 100,
|
|
43
|
+
}, HeaderAction))
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Cardinality and scope
|
|
48
|
+
|
|
49
|
+
The slot declaration fixes two independent axes.
|
|
50
|
+
|
|
51
|
+
| Axis | Value | Meaning |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| cardinality | `single` | One cell. The active priority winner renders. Use a child slot instead of treating this as an additive list. |
|
|
54
|
+
| cardinality | `list` | Cells are addressed by required `id` and ordered by `order`, then registration order. |
|
|
55
|
+
| cardinality | `keyed` | The owner dispatches an `entryKey`; the matching cell renders with any key-specific props. |
|
|
56
|
+
| 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. |
|
|
57
|
+
| scope | `root` | One root-scoped component and store instance. |
|
|
58
|
+
| scope | `session-maybe` | Follows current selection but stays renderable without a Session; Session values are optional. |
|
|
59
|
+
| scope | `session` | Requires a resolved Session binding and receives definite Session values. |
|
|
60
|
+
|
|
61
|
+
`priority` is a shadowing rank for `single`, `list`, and `keyed` cells and an election order for `chain`. Lower values run or render first. Ordinary additive contributions should choose a fresh list `id` or keyed `key`; intentionally reusing a shipped cell replaces its presentation.
|
|
62
|
+
|
|
63
|
+
## Component inputs
|
|
64
|
+
|
|
65
|
+
A registered component receives inputs assembled at its binding site. Components derive these types rather than copying their members.
|
|
66
|
+
|
|
67
|
+
| Input | Declared by | Component type |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| owner values and standard scope values | the `SlotMap` row and installed scope adapters | `PropsRuntime<K>` |
|
|
70
|
+
| authorized child renderers | the registration's `children` keys | `PropsRenderSlots<S>` |
|
|
71
|
+
| selector hook and mutation callbacks for shared view state | the registration's `store` | `PropsStore<H>` |
|
|
72
|
+
| private data, callbacks, and observable hooks | the registration's `inject` factory | `InjectFace<I>` |
|
|
73
|
+
| localized `t` function | the registration's `locale` namespace | `PropsLocale<N>` |
|
|
74
|
+
| selected chain value | the registration's `select` result | `matched` through `ComposedProps` |
|
|
75
|
+
|
|
76
|
+
`SessionProvider` is also present in `PropsRenderSlots` when an entry declares a strict Session child. It binds that subtree to the current Session identity and remounts the body when the identity changes.
|
|
77
|
+
|
|
78
|
+
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.
|
|
79
|
+
|
|
80
|
+
## Framework-provided hooks
|
|
81
|
+
|
|
82
|
+
The shipped adapters add these standard props. They are available according to the target slot's scope, independent of which package registered the component.
|
|
83
|
+
|
|
84
|
+
| Availability | Props | Owner |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| every scope | `useSessions`, `useSessionPendingInteraction` | `ui-session` |
|
|
87
|
+
| every scope | `useWorkspaces` | `ui-workspace` |
|
|
88
|
+
| `session` | `sessionId`, `useSession`, `useProjection` | `ui-session` |
|
|
89
|
+
| `session-maybe` | optional `sessionId`, `useSession`, `useProjection` results | `ui-session` |
|
|
90
|
+
| `session` | `useConversation`, `useInput`, `inputActions` | `ui-conversation` |
|
|
91
|
+
| `session-maybe` | optional `useConversation`, `useInput`, `inputActions` results | `ui-conversation` |
|
|
92
|
+
| `session` | `useChat` | `ui-chat` |
|
|
93
|
+
| `session` | `useTrajectory` | `ui-trajectory` |
|
|
94
|
+
|
|
95
|
+
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.
|
|
96
|
+
|
|
97
|
+
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.
|
|
98
|
+
|
|
99
|
+
## Developer-provided injection
|
|
100
|
+
|
|
101
|
+
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.
|
|
102
|
+
|
|
103
|
+
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.
|
|
104
|
+
|
|
105
|
+
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.
|
|
106
|
+
|
|
107
|
+
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.
|
|
108
|
+
|
|
109
|
+
## Current hierarchy
|
|
110
|
+
|
|
111
|
+
The hierarchy below is the shipped declaration tree. A child exists only while the named parent entry is mounted; optional feature entries can therefore make a subtree appear or disappear as one lifecycle unit.
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
root
|
|
115
|
+
├─ sidebar
|
|
116
|
+
│ ├─ sidebar.brand.mark
|
|
117
|
+
│ ├─ sidebar.brand.name
|
|
118
|
+
│ ├─ sidebar.footer.action
|
|
119
|
+
│ ├─ sidebar.workspaces
|
|
120
|
+
│ │ └─ sidebar.workspaces.directoryFlow
|
|
121
|
+
│ └─ sidebar.settings
|
|
122
|
+
│ ├─ settings.trigger
|
|
123
|
+
│ ├─ settings.header
|
|
124
|
+
│ ├─ settings.action
|
|
125
|
+
│ ├─ settings.close
|
|
126
|
+
│ ├─ settings.onboarding
|
|
127
|
+
│ └─ settings.section
|
|
128
|
+
│ ├─ settings.general.item
|
|
129
|
+
│ ├─ settings.models.provider-card
|
|
130
|
+
│ ├─ settings.models.footer
|
|
131
|
+
│ └─ settings.plugins.tab
|
|
132
|
+
│ └─ settings.plugin.item
|
|
133
|
+
├─ conversation
|
|
134
|
+
│ ├─ conversation.session
|
|
135
|
+
│ │ └─ conversation.view
|
|
136
|
+
│ │ ├─ conversation.chat.node
|
|
137
|
+
│ │ │ ├─ conversation.chat.assistant-actions
|
|
138
|
+
│ │ │ ├─ conversation.chat.commandview
|
|
139
|
+
│ │ │ ├─ conversation.chat.turnTail
|
|
140
|
+
│ │ │ └─ tool.call.toolview
|
|
141
|
+
│ │ │ ├─ tool.call.images
|
|
142
|
+
│ │ │ └─ tool.view.cordis
|
|
143
|
+
│ │ ├─ conversation.message.images
|
|
144
|
+
│ │ └─ conversation.trajectory.images
|
|
145
|
+
│ ├─ conversation.session.header
|
|
146
|
+
│ │ ├─ conversation.session.header.lineage
|
|
147
|
+
│ │ ├─ conversation.session.header.actions
|
|
148
|
+
│ │ └─ conversation.session.header.utilities
|
|
149
|
+
│ ├─ conversation.composer
|
|
150
|
+
│ │ └─ conversation.approval.detail
|
|
151
|
+
│ ├─ conversation.composer.bar
|
|
152
|
+
│ │ ├─ conversation.input.attachments
|
|
153
|
+
│ │ ├─ conversation.input.plan
|
|
154
|
+
│ │ └─ conversation.input.model
|
|
155
|
+
│ ├─ conversation.input.overlay
|
|
156
|
+
│ ├─ conversation.input.dock
|
|
157
|
+
│ ├─ conversation.composer.dock
|
|
158
|
+
│ ├─ conversation.input.left
|
|
159
|
+
│ ├─ conversation.input.right
|
|
160
|
+
│ ├─ conversation.hero.brand.mark
|
|
161
|
+
│ ├─ conversation.hero.workspace
|
|
162
|
+
│ │ └─ conversation.hero.workspace.directoryFlow
|
|
163
|
+
│ └─ conversation.hero.agentPreset
|
|
164
|
+
├─ details
|
|
165
|
+
│ └─ conversation.details.tool
|
|
166
|
+
└─ shell.overlay
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The generated Client inspect catalog 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`.
|
|
170
|
+
|
|
171
|
+
## Extension rules
|
|
172
|
+
|
|
173
|
+
- Import another feature package only for declarations with `import type`; never import or re-export its runtime values.
|
|
174
|
+
- 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()`.
|
|
175
|
+
- Keep business and transport state in their owning Cordis services or Client models. Slot stores hold shared viewing and interaction state only.
|
|
176
|
+
- Keep observable source and snapshot identities stable between changes. Republish through the same source whenever its value changes.
|
|
177
|
+
- Pass JSON-compatible data and callbacks between UI domains. The `hooks` compartment is the sole exception for bare observables; React content travels through slots.
|
|
178
|
+
- Treat `single` and an occupied keyed cell as replacement points. Use list ids or an unoccupied key for additive extensions.
|
|
@@ -41,7 +41,7 @@ interface SpillOwner {
|
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
A retention-period cleanup may expire old locators with other old session artifacts; the spill seam does not define a per-session cleanup policy.
|
|
45
45
|
|
|
46
46
|
```ts type-equiv
|
|
47
47
|
/**
|
|
@@ -53,7 +53,7 @@ interface SpillSource {
|
|
|
53
53
|
/** The tool whose result was spilled (e.g. `web_fetch`). */
|
|
54
54
|
toolName: string
|
|
55
55
|
/** The model-issued call id the result belongs to. */
|
|
56
|
-
callId:
|
|
56
|
+
callId: ToolCallId
|
|
57
57
|
/** A short human label for the artifact (e.g. `result`). */
|
|
58
58
|
label: string
|
|
59
59
|
}
|
|
@@ -47,7 +47,7 @@ interface StorageBackend {
|
|
|
47
47
|
}
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
A backend owns one medium (a file-tree root, a database file) and exposes optional operation groups; `kv` is the only group
|
|
50
|
+
A backend owns one medium (a file-tree root, a database file) and exposes optional operation groups; `kv` is the only shipped group. `KvFacet.open(descriptor)` opens one named unit — `KvUnitDescriptor` carries the name, current format version, optional compatible record versions, table names, and whether a global singleton slot exists — and returns a `KvUnit` with `loadAll`, `putRecord`, `deleteRecord`, `setGlobal`, and `close`. Unit and table names must match `UNIT_NAME_RE` (safe as a file name and as a SQL identifier segment); record keys are arbitrary strings that never reach file paths. A unit does not serialize concurrent writes — ordering belongs to the caller — but each single call is atomic on the medium and durable once resolved. A `single` medium stamped with a different version rejects `version-mismatch`; a `per-record` document stamped outside the accepted set reads as absent. A medium that cannot be parsed as the unit rejects `malformed-medium`. [`backend.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage/src/backend.ts) is the normative clause-by-clause contract, and the shared conformance suite in [`tests/contract.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage/tests/contract.ts) checks every clause against each backend. The [json backend](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage-json/README.md) republishes one whole human-readable file per unit atomically; the [sqlite backend](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage-sqlite/README.md) stores one document per row in one database for frequently updated data.
|
|
51
51
|
|
|
52
52
|
## Declaring a domain
|
|
53
53
|
|
|
@@ -58,8 +58,36 @@ A domain is declared once by its owning package as a spec object — the single
|
|
|
58
58
|
interface DomainSpec {
|
|
59
59
|
/** Domain name; must match `UNIT_NAME_RE` (doubles as the backend unit name). */
|
|
60
60
|
readonly name: string
|
|
61
|
-
/**
|
|
61
|
+
/** Current domain format version; reads enforce it according to the selected layout. */
|
|
62
62
|
readonly version: number
|
|
63
|
+
/**
|
|
64
|
+
* Medium layout for the backend unit: `single` (the default) stores the
|
|
65
|
+
* whole unit as one document; `per-record` stores each record as its own
|
|
66
|
+
* document, for units whose records are large, sparse, or individually
|
|
67
|
+
* disposable — the projection cache — and scopes version checks per record
|
|
68
|
+
* (an unaccepted record document is discarded, never migrated).
|
|
69
|
+
*/
|
|
70
|
+
readonly layout?: 'single' | 'per-record'
|
|
71
|
+
/**
|
|
72
|
+
* Older domain versions whose stored records the current record schemas
|
|
73
|
+
* also accept (the declaring owner vouches for that, typically by
|
|
74
|
+
* declaring the fields older records lack as optional). `per-record` backends
|
|
75
|
+
* read documents stamped with a listed version instead of discarding them,
|
|
76
|
+
* and accept a legacy whole-unit file so stamped for the one-time
|
|
77
|
+
* bootstrap; writes always stamp {@link version}.
|
|
78
|
+
*/
|
|
79
|
+
readonly compatibleVersions?: readonly number[]
|
|
80
|
+
/**
|
|
81
|
+
* What `open` does with a stored table record that fails its zod schema.
|
|
82
|
+
* Absent (the default), the whole open rejects with `invalid-record` —
|
|
83
|
+
* right for authoritative data. `'backup-and-skip'` is for domains whose
|
|
84
|
+
* records are disposable derived data: the backend moves the record's
|
|
85
|
+
* document aside (`KvUnit.backupRecord`), the failure is logged with
|
|
86
|
+
* its cause, and the open continues with the record absent. A backend
|
|
87
|
+
* without `backupRecord` (no per-record document to move) falls back
|
|
88
|
+
* to the rejecting default. The global slot always rejects.
|
|
89
|
+
*/
|
|
90
|
+
readonly invalidRecords?: 'backup-and-skip'
|
|
63
91
|
/** Optional global singleton slot. */
|
|
64
92
|
readonly global?: DomainGlobalSpec<unknown>
|
|
65
93
|
/** Table declarations keyed by table name; each name must match `UNIT_NAME_RE`. */
|
|
@@ -175,7 +203,10 @@ The mounted domain facility. Opens declared domains over routed backends; one fa
|
|
|
175
203
|
* (`facet-unsupported`); open the unit projected from the spec (backend
|
|
176
204
|
* `version-mismatch`/`malformed-medium` pass through); load and validate
|
|
177
205
|
* every stored record against the spec's zod schemas (`invalid-record`
|
|
178
|
-
* with the offending table and key
|
|
206
|
+
* with the offending table and key — unless the spec declares
|
|
207
|
+
* `invalidRecords: 'backup-and-skip'` and the unit can move documents aside, in
|
|
208
|
+
* which case the failing record is backed up, logged, and skipped);
|
|
209
|
+
* construct the domain.
|
|
179
210
|
*
|
|
180
211
|
* Lifecycle: the CALLER owns the returned handle and closes it via
|
|
181
212
|
* `Domain.close()` (typically as its own `ctx.effect` disposer) — the
|