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` 在 schema 接纳该值之后运行,因此它看到的默认值和组合 base 与 owner 实际看到的完全一致。`dsh-llm-pi-ai` 用它在写入处拒绝自己无法服务的提供方 profile,而不是先存下来、再让该 namespace 下每条路由失效。
|
|
56
56
|
|
|
57
|
-
`applies` 是 UI 提示而非机制:`restart` 的 owner
|
|
57
|
+
`applies` 是 UI 提示而非机制:`restart` 的 owner 从不 watch,其值在构造期读取一次,配置界面可为待生效变更加标。
|
|
58
58
|
|
|
59
59
|
```ts type-equiv
|
|
60
60
|
/** When a namespace's changes take effect for its owner. */
|
|
@@ -164,6 +164,10 @@ interface SettingsDescribeOptions {
|
|
|
164
164
|
type SettingsUpdateSource = 'update' | 'provider'
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
## 原生文档操作
|
|
168
|
+
|
|
169
|
+
`SettingsDocumentOpenValue` 确认 `settings/openSettingsDocument` 已准备好 provider 持有的文档,并将其交给原生文本编辑器。`AgentPresetDirectoryOpenValue` 报告已完成的原生交接,或在桌面打开不可用时返回解析后的用户 preset 目录。两项操作都不接受由浏览器选择的 Host 路径。
|
|
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 @@ interface Config {
|
|
|
237
237
|
|
|
238
238
|
面向模型的 `skill({ name })` 工具校验 kebab-case 名称,在与调用策略无关的目录中查找摘要,并在加载前通过 `isModelInvocable` 拒绝无权访问的 skill;随后它根据调用方 agent 的 cwd 重新读取完整定义,并在返回内容前再次检查策略。该工具将无法解析的 skill 报告为未知或已不可用,并返回包含 `<skill_content name="...">`、`<skill_resources>` 和 `<skill_instructions>` 的工具结果。`resourceBase` 仅按需解析显式引用的脚本、参考资料和资产;加载结果不枚举 skill 目录。因此,仅修改正文会改变后续工具调用,而不会生成目录消息或改写先前工具结果。
|
|
239
239
|
|
|
240
|
+
## 浏览器 Session 目录
|
|
241
|
+
|
|
242
|
+
`SkillListRequest` 通过 `sessionId` 指定一个 Session;`SkillListValue` 返回允许用户调用的条目,其中包含名称、描述、可选使用提示与模型调用可用性。`SessionSkillCatalog` 在不激活 Agent 的前提下读取 Session cwd 与记录的 preset。live Agent 可以提供其作用域 registry,冷 Session 则使用 preset 的 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 @@ interface Config {
|
|
|
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.zh.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Client Slots
|
|
7
|
+
|
|
8
|
+
Slots 是 Web Client 的类型化 React 组合系统。[`dsh-client-ui-slots`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-slots/README.zh.md)定义不依赖 React 的注册表与类型代数;[`dsh-client-ui-renderer`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-renderer/README.zh.md)把可观测源绑定成钩子、渲染整棵树,并在内部拥有 React context。功能插件通过 `ctx.slots.register()` 贡献 UI,绝不导入其他功能插件的组件。
|
|
9
|
+
|
|
10
|
+
本文记录 slot 的所有权、组件输入、扩展 API 与当前层级。外围的启动、Remote、Client model 与 Conversation 数据通路见 [Web Client 架构](./web-client.md)。
|
|
11
|
+
|
|
12
|
+
## 声明与生命周期
|
|
13
|
+
|
|
14
|
+
`SlotMap` 是编译期注册表。包通过声明合并写入 key、cardinality(基数)、scope、owner props、keyed props 与可选的 slot 级 inject face。运行时声明则是拥有该渲染位置的组件在 `children` 中给出的对应条目。
|
|
15
|
+
|
|
16
|
+
声明一个 child 会同时产生三种效果:令该 child key 生效、授权 parent entry 调用 `renderSlot` 或 `renderSlotChain`,以及记录运行时 dispatch 规格。每个声明只能有一个存活 owner。向未声明 slot 注册,或重复声明其他 entry 已拥有的 child,都会在插件激活时失败。
|
|
17
|
+
|
|
18
|
+
`root` 是唯一内建声明,也是唯一由 Cordis service 自身渲染的 key。`ui-renderer` 调用 `ctx.slots.renderSlot('root', {})`;其余每个后代都通过声明它的 entry 所收到的 `renderSlot` 或 `renderSlotChain` prop 渲染。
|
|
19
|
+
|
|
20
|
+
注册和声明遵循 Cordis effect 生命周期。销毁一个 entry 会移除其贡献,并递归折叠它声明的 child slots。因此,向其他包的 slot 贡献功能时使用 `ctx.slots.inject(key, callback)`:callback 会在每段声明生命周期内运行,owner 折叠时其 effect 随之移除,owner 再次挂载时则重新运行。
|
|
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 与 scope
|
|
48
|
+
|
|
49
|
+
Slot 声明固定两个相互独立的维度。
|
|
50
|
+
|
|
51
|
+
| 维度 | 值 | 含义 |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| cardinality | `single` | 单个 cell,渲染当前 priority 胜者;需要并列内容时应声明 child slot,而不是把它当作列表。 |
|
|
54
|
+
| cardinality | `list` | cell 由必填 `id` 定址,先按 `order`、再按注册顺序排列。 |
|
|
55
|
+
| cardinality | `keyed` | owner 传入 `entryKey`;匹配 cell 以该 key 对应的 props 渲染。 |
|
|
56
|
+
| cardinality | `chain` | 每个 entry 提供纯 `select(owner)` 函数;按 priority 顺序遇到的第一个非 null 结果获选,并以 `matched` 传给组件;全部拒绝时渲染 owner fallback。 |
|
|
57
|
+
| scope | `root` | 一个 root 作用域组件和 store 实例。 |
|
|
58
|
+
| scope | `session-maybe` | 跟随当前选择,但没有 Session 时仍可渲染;Session 值是可选的。 |
|
|
59
|
+
| scope | `session` | 要求可解析的 Session binding,并收到确定存在的 Session 值。 |
|
|
60
|
+
|
|
61
|
+
对于 `single`、`list` 和 `keyed` cell,`priority` 是遮蔽优先级;对于 `chain`,它是选举顺序。数值越小越先运行或渲染。普通增量贡献应选用新的 list `id` 或 keyed `key`;复用已有 cell 表示有意替换其展示。
|
|
62
|
+
|
|
63
|
+
## 组件输入
|
|
64
|
+
|
|
65
|
+
注册组件会在 binding 位置收到组装后的输入。组件应从这些类型推导 props,不要重新抄写成员。
|
|
66
|
+
|
|
67
|
+
| 输入 | 声明者 | 组件类型 |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| owner 值与标准 scope 值 | `SlotMap` 条目与已安装的 scope adapter | `PropsRuntime<K>` |
|
|
70
|
+
| 获授权的 child renderer | 注册项的 `children` keys | `PropsRenderSlots<S>` |
|
|
71
|
+
| 共享视图状态的 selector hook 与 mutation callback | 注册项的 `store` | `PropsStore<H>` |
|
|
72
|
+
| 私有数据、callback 与 observable hook | 注册项的 `inject` factory | `InjectFace<I>` |
|
|
73
|
+
| 本地化 `t` 函数 | 注册项的 `locale` namespace | `PropsLocale<N>` |
|
|
74
|
+
| chain 选中的值 | 注册项的 `select` 结果 | 通过 `ComposedProps` 提供的 `matched` |
|
|
75
|
+
|
|
76
|
+
当 entry 声明 strict Session child 时,`PropsRenderSlots` 还会提供 `SessionProvider`。它把子树绑定到当前 Session identity,并在 identity 改变时重新挂载 body。
|
|
77
|
+
|
|
78
|
+
组件绝不会收到 `ctx`。父组件在某次渲染时已经知道的值通过 `renderSlot` 的 owner 参数进入;共享视图状态使用声明的 store;service 与 model object 留在 `apply` closure 中,只向组件投影 callback 或 observable source。
|
|
79
|
+
|
|
80
|
+
## 框架提供的 hooks
|
|
81
|
+
|
|
82
|
+
当前组合中的 adapter 会添加以下标准 props。它们按目标 slot 的 scope 提供,与注册组件来自哪个包无关。
|
|
83
|
+
|
|
84
|
+
| 可用范围 | Props | Owner |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| 所有 scope | `useSessions`、`useSessionPendingInteraction` | `ui-session` |
|
|
87
|
+
| 所有 scope | `useWorkspaces` | `ui-workspace` |
|
|
88
|
+
| `session` | `sessionId`、`useSession`、`useProjection` | `ui-session` |
|
|
89
|
+
| `session-maybe` | 结果可选的 `sessionId`、`useSession`、`useProjection` | `ui-session` |
|
|
90
|
+
| `session` | `useConversation`、`useInput`、`inputActions` | `ui-conversation` |
|
|
91
|
+
| `session-maybe` | 结果可选的 `useConversation`、`useInput`、`inputActions` | `ui-conversation` |
|
|
92
|
+
| `session` | `useChat` | `ui-chat` |
|
|
93
|
+
| `session` | `useTrajectory` | `ui-trajectory` |
|
|
94
|
+
|
|
95
|
+
Renderer 还会根据声明的 store 创建 `useStore`,并根据声明的 locale namespace 创建 `t`。这些是由注册项推导的 props,不属于全局标准 props。
|
|
96
|
+
|
|
97
|
+
框架与领域 adapter owner 可以通过 `ctx.slots.provideRoot()` 或 `ctx.uiSession.provide()` 扩展标准集合,同时提供对应的 `GlobalStandardProps`、`SessionStandardProps` 或 `SessionMaybeStandardProps` 声明合并。普通功能组件不应自行创建 React hook prop,也不应为 entry 私有数据添加全局标准 prop。
|
|
98
|
+
|
|
99
|
+
## 开发者提供的 injection
|
|
100
|
+
|
|
101
|
+
注册项的 `inject` 选项是通常使用的功能私有注入点。它的 factory 在插件的 `apply` 世界中运行,可以闭包捕获已经注入的 Cordis service,并且只返回组件所需的数据与 callback。对于 `session` slot,它会收到 `sessionId`;对于 `session-maybe`,它收到 `sessionId | undefined`;声明 store 后,它还会收到该 store 绑定后的 actions。
|
|
102
|
+
|
|
103
|
+
返回值中保留的 `hooks` 对象接收裸 `getSnapshot`/`subscribe` source。Renderer 把 `hooks: { status }` 转换为组件 prop `useStatus(selector)`,并按 source identity 缓存绑定。组件不会收到 source 本身,也不直接调用 `useSyncExternalStore`。
|
|
104
|
+
|
|
105
|
+
当每个 occupant 都需要同一种能力时,slot owner 可以在 child 声明里放置 `inject` face。普通成员会原样交给所有 occupant;其 `hooks` 对象中的函数成员是 hook factory,它会收到 slot 的标准 props 与可选的逐次渲染 `hookContext`,再返回提供给 occupant 的受限 hook。`conversation.chat.node` 正是通过这种机制,为当前渲染的 node 提供 `useTurnData(key)`。
|
|
106
|
+
|
|
107
|
+
一次渲染时 owner 已知的值走 owner props;单个 entry 的 callback 与私有 observable 走注册项 `inject`;由 slot owner 控制、所有 occupant 共享的能力走 slot 级 `inject`;需要跨 entry 共享或跨重新挂载保留的可变视图状态走声明的 store。React node 通过 child slot 组合,不通过注入值传递。
|
|
108
|
+
|
|
109
|
+
## 当前层级
|
|
110
|
+
|
|
111
|
+
下图是当前发布组合的声明树。只有具名 parent entry 已挂载时,其 child 才存在;因此可选功能 entry 可以作为一个生命周期单元让整棵子树出现或消失。
|
|
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
|
+
生成的 Client inspect catalog 是每个 key 的完整参考,包含 cardinality、scope、owner props、标准 props、当前 occupant、声明 owner 与替换风险。运行中的动态包可以用 `cordis_inspect what:"client"` 查询实时树与某个精确 key;源码 catalog 由 `pnpm run gen-client-catalog` 根据 `SlotMap` 声明和 `slots.register()` 调用点生成。
|
|
170
|
+
|
|
171
|
+
## 扩展规则
|
|
172
|
+
|
|
173
|
+
- 另一个功能包只能通过 `import type` 引入声明;绝不导入或转发它的运行时值。
|
|
174
|
+
- 只在拥有并渲染某个位置的组件中声明新的 child slot。其他包通过 `ctx.slots.inject()` 等待,再通过 `ctx.slots.register()` 贡献内容。
|
|
175
|
+
- 业务与传输状态留在所属 Cordis service 或 Client model 中。Slot store 只承载共享的视图与交互状态。
|
|
176
|
+
- 可观测 source 及其 snapshot identity 在值变化前保持稳定;值变化时通过同一个 source 发布。
|
|
177
|
+
- UI domain 之间只传 JSON 兼容数据和 callback。`hooks` compartment 是裸 observable 的唯一例外;React 内容通过 slot 传递。
|
|
178
|
+
- 将 `single` 和已有 occupant 的 keyed cell 视为替换点。增量扩展使用 list id 或尚未占用的 key。
|
|
@@ -41,7 +41,7 @@ interface SpillOwner {
|
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
保留期清理可以连同其他旧会话产物一起使旧定位符失效;spill seam 不定义逐会话的清理策略。
|
|
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
|
-
|
|
50
|
+
一个后端拥有一个介质(一棵文件树的根目录、一个数据库文件),并提供可选的操作组;`kv` 是唯一已交付的操作组。`KvFacet.open(descriptor)` 打开一个具名 unit——`KvUnitDescriptor` 携带名称、当前格式版本、可选的兼容记录版本、表名清单,以及是否存在全局单例 slot——并返回提供 `loadAll`、`putRecord`、`deleteRecord`、`setGlobal` 和 `close` 的 `KvUnit`。unit 名与表名必须匹配 `UNIT_NAME_RE`(既可安全用作文件名,也可安全用作 SQL 标识符片段);记录键是任意字符串,绝不进入文件路径。unit 不对并发写入做串行化——顺序由调用方负责——但每次单独调用在介质上都是原子的,且 resolve 后即已持久。`single` 介质上记录的版本不同时拒绝 `version-mismatch`;`per-record` 文档的版本在接受集合之外时读作不存在。无法按该 unit 解析的介质拒绝 `malformed-medium`。[`backend.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage/src/backend.ts) 是逐条款的规范性约定,[`tests/contract.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage/tests/contract.ts) 中的共享一致性套件会针对每个后端检查每项条款。[json 后端](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage-json/README.zh.md)以原子方式为每个 unit 整文件重新发布一份人类可读文件;[sqlite 后端](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/storage/storage-sqlite/README.zh.md)在单个数据库中每行存储一份文档,用于频繁更新的数据。
|
|
51
51
|
|
|
52
52
|
## 声明领域
|
|
53
53
|
|
|
@@ -58,8 +58,36 @@ interface StorageBackend {
|
|
|
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
|