dsh-plugin-dev-kb 1.1.0 → 1.4.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 +31 -0
- package/README.en.md +14 -8
- package/README.md +15 -9
- package/docs/banner.svg +25 -0
- package/kb/INDEX.md +23 -19
- package/kb/README.md +8 -6
- package/kb/extra/AGENTS.md +11 -10
- package/kb/extra/cookbook/adding-a-remote-api.md +2 -2
- package/kb/extra/cookbook/adding-a-remote-api.zh.md +2 -2
- package/kb/extra/cookbook/adding-a-session-format-version.md +151 -0
- package/kb/extra/cookbook/adding-a-session-format-version.zh.md +151 -0
- package/kb/extra/cookbook/adding-a-vendored-package.md +1 -1
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +1 -1
- package/kb/extra/cookbook/reviewing-persistence-type-changes.md +120 -0
- package/kb/extra/cookbook/reviewing-persistence-type-changes.zh.md +120 -0
- package/kb/extra/deepseek-llm-api-wire-extensions.md +19 -20
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +18 -19
- package/kb/extra/development.md +37 -10
- package/kb/extra/development.zh.md +37 -10
- package/kb/extra/event-producer-consumer.md +90 -67
- package/kb/extra/event-producer-consumer.zh.md +91 -68
- package/kb/extra/glossary.md +1 -1
- package/kb/extra/glossary.zh.md +1 -1
- package/kb/extra/i18n/README.md +16 -7
- package/kb/extra/i18n/README.zh.md +17 -8
- package/kb/extra/i18n/terminology.md +4 -4
- package/kb/extra/i18n/translation-prompt.md +3 -3
- package/kb/extra/module-graph.md +621 -335
- package/kb/extra/module-graph.zh.md +621 -335
- package/kb/extra/persistence-changes/2026-09-11-initial.md +280 -0
- package/kb/extra/persistence-changes/2026-09-11-initial.zh.md +280 -0
- package/kb/extra/persistence-changes/2026-09-12-auto-review-error-metadata.md +52 -0
- package/kb/extra/persistence-changes/2026-09-12-auto-review-error-metadata.zh.md +52 -0
- package/kb/extra/persistence-changes/2026-09-14-image-offload.md +96 -0
- package/kb/extra/persistence-changes/2026-09-14-image-offload.zh.md +96 -0
- package/kb/extra/persistence-changes/2026-09-14-workspace-changes-event.md +48 -0
- package/kb/extra/persistence-changes/2026-09-14-workspace-changes-event.zh.md +48 -0
- package/kb/extra/persistence-changes/2026-09-16-session-format-v4.md +120 -0
- package/kb/extra/persistence-changes/2026-09-16-session-format-v4.zh.md +120 -0
- package/kb/extra/persistence-changes/2026-09-18-schedule-optional-title.md +48 -0
- package/kb/extra/persistence-changes/2026-09-18-schedule-optional-title.zh.md +48 -0
- package/kb/extra/persistence-changes/2026-09-20-unknown-child-catalog.md +48 -0
- package/kb/extra/persistence-changes/2026-09-20-unknown-child-catalog.zh.md +48 -0
- package/kb/extra/persistence-changes/2026-09-21-user-question-reply.md +60 -0
- package/kb/extra/persistence-changes/2026-09-21-user-question-reply.zh.md +60 -0
- package/kb/extra/persistence-changes/README.md +88 -0
- package/kb/extra/persistence-changes/README.zh.md +88 -0
- package/kb/extra/persistence-changes/historical-formats/README.md +75 -0
- package/kb/extra/persistence-changes/historical-formats/README.zh.md +75 -0
- package/kb/extra/persistence-changes/historical-formats/v0.md +5105 -0
- package/kb/extra/persistence-changes/historical-formats/v0.zh.md +5105 -0
- package/kb/extra/persistence-changes/historical-formats/v1.md +5107 -0
- package/kb/extra/persistence-changes/historical-formats/v1.zh.md +5107 -0
- package/kb/extra/persistence-changes/historical-formats/v2.md +5362 -0
- package/kb/extra/persistence-changes/historical-formats/v2.zh.md +5362 -0
- package/kb/extra/persistence-changes/historical-formats/v3.md +5634 -0
- package/kb/extra/persistence-changes/historical-formats/v3.zh.md +5634 -0
- package/kb/extra/persistence-changes/releases/README.md +103 -0
- package/kb/extra/persistence-changes/releases/README.zh.md +103 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.1.md +201 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.1.zh.md +201 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.2.md +261 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.2.zh.md +261 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.3.md +126 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.3.zh.md +126 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.4.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.4.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.5.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.0.1-rc.5.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.1.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.1.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.2.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.2.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.3.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.3.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.5.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.5.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.6.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.6.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.7.md +82 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.7.zh.md +82 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.8.md +110 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.0-rc.8.zh.md +110 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.1-rc.1.md +82 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.1-rc.1.zh.md +82 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.1-rc.2.md +119 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.1-rc.2.zh.md +119 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.1.md +295 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.1.zh.md +295 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.2.md +286 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.2.zh.md +286 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.3.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.3.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.4.md +95 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.4.zh.md +95 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.5.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-alpha.5.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-rc.1.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.2-rc.1.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.3-alpha.1.md +154 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.3-alpha.1.zh.md +154 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.3-alpha.2.md +86 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.3-alpha.2.zh.md +86 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-alpha.1.md +139 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-alpha.1.zh.md +139 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-alpha.2.md +95 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-alpha.2.zh.md +95 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-rc.1.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-rc.1.zh.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-rc.2.md +75 -0
- package/kb/extra/persistence-changes/releases/dsh-v0.1.5-rc.2.zh.md +75 -0
- package/kb/extra/rescope.md +2 -2
- package/kb/extra/rescope.zh.md +2 -2
- package/kb/extra/session-format-status.md +63 -0
- package/kb/extra/session-format-status.zh.md +63 -0
- package/kb/extra/subsystems/agent-team.md +52 -28
- package/kb/extra/subsystems/agent-team.zh.md +52 -28
- package/kb/extra/subsystems/attachment.md +19 -9
- package/kb/extra/subsystems/attachment.zh.md +19 -9
- package/kb/extra/subsystems/boot.md +323 -0
- package/kb/extra/subsystems/boot.zh.md +323 -0
- package/kb/extra/subsystems/browser-use.md +67 -0
- package/kb/extra/subsystems/browser-use.zh.md +67 -0
- package/kb/extra/subsystems/claude-code-mods.md +146 -0
- package/kb/extra/subsystems/claude-code-mods.zh.md +146 -0
- package/kb/extra/subsystems/computer-use.md +56 -0
- package/kb/extra/subsystems/computer-use.zh.md +56 -0
- package/kb/extra/subsystems/deliverables.md +178 -0
- package/kb/extra/subsystems/deliverables.zh.md +178 -0
- package/kb/extra/subsystems/extensions.md +6 -4
- package/kb/extra/subsystems/extensions.zh.md +6 -4
- package/kb/extra/subsystems/feedback.md +165 -31
- package/kb/extra/subsystems/feedback.zh.md +165 -31
- package/kb/extra/subsystems/mcp.md +139 -0
- package/kb/extra/subsystems/mcp.zh.md +139 -0
- package/kb/extra/subsystems/office-to-pdf.md +87 -0
- package/kb/extra/subsystems/office-to-pdf.zh.md +87 -0
- package/kb/extra/subsystems/otel.md +44 -0
- package/kb/extra/subsystems/otel.zh.md +44 -0
- package/kb/extra/subsystems/product-telemetry.md +79 -0
- package/kb/extra/subsystems/product-telemetry.zh.md +79 -0
- package/kb/extra/subsystems/ssh.md +135 -0
- package/kb/extra/subsystems/ssh.zh.md +135 -0
- package/kb/extra/subsystems/todo.md +3 -3
- package/kb/extra/subsystems/todo.zh.md +3 -3
- package/kb/extra/subsystems/voice-input.md +164 -0
- package/kb/extra/subsystems/voice-input.zh.md +164 -0
- package/kb/extra/subsystems/webhook.md +3 -3
- package/kb/extra/subsystems/webhook.zh.md +1 -1
- package/kb/extra/testing.md +5 -4
- package/kb/extra/testing.zh.md +5 -4
- package/kb/extra/ui-radius.md +115 -0
- package/kb/extra/ui-radius.zh.md +115 -0
- package/kb/extra/upgrade-guide/v0.1.7-rc.2/schedule-optional-bundle/guide.md +22 -0
- package/kb/extra/upgrade-guide/v0.1.7-rc.2/schedule-optional-bundle/guide.zh.md +22 -0
- package/kb/extra/upgrade-guide/v0.1.7-rc.2/transcript-view-legacy-normal/guide.md +25 -0
- package/kb/extra/upgrade-guide/v0.1.7-rc.2/transcript-view-legacy-normal/guide.zh.md +25 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/account-sign-in-errors/guide.md +18 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/account-sign-in-errors/guide.zh.md +18 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/remove-runtime-invariants/guide.md +23 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/remove-runtime-invariants/guide.zh.md +23 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/schedule-bundle-retired/guide.md +22 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/schedule-bundle-retired/guide.zh.md +22 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/subpath-plugin-display-manifest/guide.md +27 -0
- package/kb/extra/upgrade-guide/v0.2.0-rc.2/subpath-plugin-display-manifest/guide.zh.md +27 -0
- package/kb/extra/web-styling.md +12 -2
- package/kb/extra/web-styling.zh.md +12 -2
- package/kb/meta/search-index.json +1019 -251
- package/kb/meta/site-pages.txt +187 -183
- package/kb/meta/source.json +8 -8
- package/kb/meta/topics.md +11 -7
- package/kb/site/develop/basic/config.md +1 -0
- package/kb/site/develop/basic/index.md +1 -0
- package/kb/site/develop/basic/publish.md +10 -3
- package/kb/site/develop/basic/tool.md +1 -0
- package/kb/site/develop/cordis-tutorial/01-first-plugin.md +1 -0
- package/kb/site/develop/cordis-tutorial/02-lifecycle-and-effects.md +1 -0
- package/kb/site/develop/cordis-tutorial/03-services.md +1 -0
- package/kb/site/develop/cordis-tutorial/04-events.md +1 -0
- package/kb/site/develop/cordis-tutorial/05-config.md +28 -0
- package/kb/site/develop/cordis-tutorial/06-composition-and-hmr.md +3 -2
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +1 -0
- package/kb/site/develop/cordis-tutorial/index.md +1 -0
- package/kb/site/develop/framework/events.md +1 -0
- package/kb/site/develop/framework/index.md +2 -1
- package/kb/site/develop/framework/service.md +1 -0
- package/kb/site/develop/practice/dynamic-cordis.md +9 -8
- package/kb/site/develop/practice/index.md +1 -0
- package/kb/site/develop/practice/llm-adapter.md +2 -1
- package/kb/site/en/develop/basic/config.md +1 -0
- package/kb/site/en/develop/basic/index.md +1 -0
- package/kb/site/en/develop/basic/publish.md +10 -3
- package/kb/site/en/develop/basic/tool.md +1 -0
- package/kb/site/en/develop/cordis-tutorial/01-first-plugin.md +1 -0
- package/kb/site/en/develop/cordis-tutorial/02-lifecycle-and-effects.md +1 -0
- package/kb/site/en/develop/cordis-tutorial/03-services.md +1 -0
- package/kb/site/en/develop/cordis-tutorial/04-events.md +1 -0
- package/kb/site/en/develop/cordis-tutorial/05-config.md +28 -0
- package/kb/site/en/develop/cordis-tutorial/06-composition-and-hmr.md +3 -2
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +1 -0
- package/kb/site/en/develop/cordis-tutorial/index.md +1 -0
- package/kb/site/en/develop/framework/events.md +1 -0
- package/kb/site/en/develop/framework/index.md +2 -1
- package/kb/site/en/develop/framework/service.md +1 -0
- package/kb/site/en/develop/practice/dynamic-cordis.md +9 -8
- package/kb/site/en/develop/practice/index.md +1 -0
- package/kb/site/en/develop/practice/llm-adapter.md +2 -1
- package/kb/site/en/guide/github-review.md +1 -0
- package/kb/site/en/guide/mcp-memory.md +1 -0
- package/kb/site/en/guide/network-proxy.md +2 -1
- package/kb/site/en/guide/providers-custom-form.png +0 -0
- package/kb/site/en/guide/providers-models-page.png +0 -0
- package/kb/site/en/guide/providers.md +98 -83
- package/kb/site/en/guide/public-deployments.md +36 -0
- package/kb/site/en/guide/python-sdk.md +60 -23
- package/kb/site/en/guide/quickstart.md +2 -0
- package/kb/site/en/guide/schedule.md +70 -11
- package/kb/site/en/reference/agent-lifecycle.md +13 -5
- package/kb/site/en/reference/api-gateway.md +13 -11
- package/kb/site/en/reference/capability-seams.md +187 -62
- package/kb/site/en/reference/config-catalog.md +1887 -819
- package/kb/site/en/reference/cookbook/adding-a-package.md +57 -3
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +35 -64
- package/kb/site/en/reference/cookbook/adding-a-tool.md +5 -4
- package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +1 -0
- package/kb/site/en/reference/cookbook/extension-cookbook.md +7 -6
- package/kb/site/en/reference/cordis-api/context.md +1 -0
- package/kb/site/en/reference/cordis-api/events.md +1 -0
- package/kb/site/en/reference/cordis-api/fiber.md +4 -3
- package/kb/site/en/reference/cordis-api/inherited.md +16 -16
- package/kb/site/en/reference/cordis-api/registry.md +1 -0
- package/kb/site/en/reference/cordis-api/service.md +1 -0
- package/kb/site/en/reference/cordis-primer.md +1 -0
- package/kb/site/en/reference/index.md +32 -15
- package/kb/site/en/reference/persistence-catalog.md +7787 -81
- package/kb/site/en/reference/subsystems/approval.md +3 -2
- package/kb/site/en/reference/subsystems/client-modules.md +30 -13
- package/kb/site/en/reference/subsystems/client-resources.md +96 -0
- package/kb/site/en/reference/subsystems/commands.md +6 -1
- package/kb/site/en/reference/subsystems/compaction.md +50 -3
- package/kb/site/en/reference/subsystems/conversation.md +36 -6
- package/kb/site/en/reference/subsystems/core.md +174 -271
- package/kb/site/en/reference/subsystems/credentials.md +169 -5
- package/kb/site/en/reference/subsystems/filesystem.md +26 -0
- package/kb/site/en/reference/subsystems/goal.md +39 -2
- package/kb/site/en/reference/subsystems/index.md +18 -5
- package/kb/site/en/reference/subsystems/jobs.md +337 -127
- package/kb/site/en/reference/subsystems/llm-streaming.md +93 -43
- package/kb/site/en/reference/subsystems/lsp.md +2 -1
- package/kb/site/en/reference/subsystems/permission-presets.md +66 -29
- package/kb/site/en/reference/subsystems/persistence.md +40 -18
- package/kb/site/en/reference/subsystems/plan.md +2 -1
- package/kb/site/en/reference/subsystems/ptc-runtime.md +236 -0
- package/kb/site/en/reference/subsystems/sandbox.md +7 -5
- package/kb/site/en/reference/subsystems/schedule.md +392 -33
- package/kb/site/en/reference/subsystems/scope.md +2 -1
- package/kb/site/en/reference/subsystems/session-projection.md +22 -19
- package/kb/site/en/reference/subsystems/session-query.md +1 -0
- package/kb/site/en/reference/subsystems/session-reference.md +12 -6
- package/kb/site/en/reference/subsystems/session-telemetry.md +27 -8
- package/kb/site/en/reference/subsystems/session-title.md +6 -5
- package/kb/site/en/reference/subsystems/session.md +258 -118
- package/kb/site/en/reference/subsystems/settings.md +43 -292
- package/kb/site/en/reference/subsystems/shell.md +44 -32
- package/kb/site/en/reference/subsystems/sidebar-right.md +162 -0
- package/kb/site/en/reference/subsystems/skills.md +5 -6
- package/kb/site/en/reference/subsystems/slots.md +68 -39
- package/kb/site/en/reference/subsystems/spill.md +15 -7
- package/kb/site/en/reference/subsystems/storage.md +2 -2
- package/kb/site/en/reference/subsystems/subagent.md +65 -72
- package/kb/site/en/reference/subsystems/subprocess.md +42 -44
- package/kb/site/en/reference/subsystems/system-prompt.md +7 -2
- package/kb/site/en/reference/subsystems/terminal.md +1 -0
- package/kb/site/en/reference/subsystems/token-meter.md +3 -1
- package/kb/site/en/reference/subsystems/tools.md +44 -16
- package/kb/site/en/reference/subsystems/typert.md +153 -10
- package/kb/site/en/reference/subsystems/user-questions.md +131 -1
- package/kb/site/en/reference/subsystems/web-client.md +15 -9
- package/kb/site/en/reference/subsystems/web-server.md +74 -1
- package/kb/site/en/reference/subsystems/web.md +1 -0
- package/kb/site/en/reference/subsystems/workflow.md +10 -9
- package/kb/site/en/reference/subsystems/workspace.md +343 -4
- package/kb/site/en/reference/tool-catalog.md +806 -311
- package/kb/site/en/reference/tool-execution-pipeline.md +9 -5
- package/kb/site/guide/github-review.md +1 -0
- package/kb/site/guide/mcp-memory.md +1 -0
- package/kb/site/guide/network-proxy.md +2 -1
- package/kb/site/guide/providers-custom-form.zh.png +0 -0
- package/kb/site/guide/providers-models-page.zh.png +0 -0
- package/kb/site/guide/providers.md +109 -94
- package/kb/site/guide/public-deployments.md +36 -0
- package/kb/site/guide/python-sdk.md +60 -23
- package/kb/site/guide/quickstart.md +2 -0
- package/kb/site/guide/schedule.md +70 -11
- package/kb/site/reference/agent-lifecycle.md +13 -5
- package/kb/site/reference/api-gateway.md +13 -11
- package/kb/site/reference/capability-seams.md +187 -62
- package/kb/site/reference/config-catalog.md +1889 -820
- package/kb/site/reference/cookbook/adding-a-package.md +55 -3
- package/kb/site/reference/cookbook/adding-a-settings-card.md +35 -64
- package/kb/site/reference/cookbook/adding-a-tool.md +5 -4
- package/kb/site/reference/cookbook/adding-an-llm-adapter.md +1 -0
- package/kb/site/reference/cookbook/extension-cookbook.md +7 -6
- package/kb/site/reference/cordis-api/context.md +1 -0
- package/kb/site/reference/cordis-api/events.md +1 -0
- package/kb/site/reference/cordis-api/fiber.md +4 -3
- package/kb/site/reference/cordis-api/inherited.md +16 -16
- package/kb/site/reference/cordis-api/registry.md +1 -0
- package/kb/site/reference/cordis-api/service.md +1 -0
- package/kb/site/reference/cordis-primer.md +1 -0
- package/kb/site/reference/index.md +32 -15
- package/kb/site/reference/persistence-catalog.md +7791 -85
- package/kb/site/reference/subsystems/approval.md +3 -2
- package/kb/site/reference/subsystems/client-modules.md +30 -13
- package/kb/site/reference/subsystems/client-resources.md +96 -0
- package/kb/site/reference/subsystems/commands.md +6 -1
- package/kb/site/reference/subsystems/compaction.md +50 -3
- package/kb/site/reference/subsystems/conversation.md +35 -5
- package/kb/site/reference/subsystems/core.md +174 -271
- package/kb/site/reference/subsystems/credentials.md +169 -5
- package/kb/site/reference/subsystems/filesystem.md +26 -0
- package/kb/site/reference/subsystems/goal.md +39 -2
- package/kb/site/reference/subsystems/index.md +28 -15
- package/kb/site/reference/subsystems/jobs.md +336 -126
- package/kb/site/reference/subsystems/llm-streaming.md +93 -43
- package/kb/site/reference/subsystems/lsp.md +2 -1
- package/kb/site/reference/subsystems/permission-presets.md +66 -29
- package/kb/site/reference/subsystems/persistence.md +40 -18
- package/kb/site/reference/subsystems/plan.md +2 -1
- package/kb/site/reference/subsystems/ptc-runtime.md +236 -0
- package/kb/site/reference/subsystems/sandbox.md +7 -5
- package/kb/site/reference/subsystems/schedule.md +392 -33
- package/kb/site/reference/subsystems/scope.md +2 -1
- package/kb/site/reference/subsystems/session-projection.md +22 -19
- package/kb/site/reference/subsystems/session-query.md +1 -0
- package/kb/site/reference/subsystems/session-reference.md +12 -6
- package/kb/site/reference/subsystems/session-telemetry.md +27 -8
- package/kb/site/reference/subsystems/session-title.md +6 -5
- package/kb/site/reference/subsystems/session.md +258 -118
- package/kb/site/reference/subsystems/settings.md +43 -292
- package/kb/site/reference/subsystems/shell.md +44 -32
- package/kb/site/reference/subsystems/sidebar-right.md +162 -0
- package/kb/site/reference/subsystems/skills.md +5 -6
- package/kb/site/reference/subsystems/slots.md +68 -39
- package/kb/site/reference/subsystems/spill.md +15 -7
- package/kb/site/reference/subsystems/storage.md +2 -2
- package/kb/site/reference/subsystems/subagent.md +64 -71
- package/kb/site/reference/subsystems/subprocess.md +42 -44
- package/kb/site/reference/subsystems/system-prompt.md +7 -2
- package/kb/site/reference/subsystems/terminal.md +1 -0
- package/kb/site/reference/subsystems/token-meter.md +3 -1
- package/kb/site/reference/subsystems/tools.md +44 -16
- package/kb/site/reference/subsystems/typert.md +153 -10
- package/kb/site/reference/subsystems/user-questions.md +132 -2
- package/kb/site/reference/subsystems/web-client.md +15 -9
- package/kb/site/reference/subsystems/web-server.md +74 -1
- package/kb/site/reference/subsystems/web.md +1 -0
- package/kb/site/reference/subsystems/workflow.md +10 -9
- package/kb/site/reference/subsystems/workspace.md +343 -4
- package/kb/site/reference/tool-catalog.md +810 -315
- package/kb/site/reference/tool-execution-pipeline.md +9 -5
- package/lib/index.js +25 -44
- package/package.json +3 -2
- package/skills/dsh-plugin-dev-kb.md +6 -5
- package/kb/site/en/reference/subsystems/code-runtime.md +0 -198
- package/kb/site/en/reference/subsystems/invariants.md +0 -91
- package/kb/site/reference/subsystems/code-runtime.md +0 -198
- package/kb/site/reference/subsystems/invariants.md +0 -91
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
editSource: "docs/subsystems/session.md"
|
|
3
|
+
rawMarkdownPath: "en/reference/subsystems/session.md"
|
|
3
4
|
outline: [2,3]
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -14,8 +15,8 @@ Source: [`packages/core/session/src/types.ts`](https://github.com/deepseek-ai/de
|
|
|
14
15
|
The append-only event types. Merge-extensible: a plugin declares extra event types via declaration merging — e.g. the [compaction seam](./compaction.md) adds `compaction/start` / `compaction/summary` / `compaction/end`, and `@deepseek-ai/dsh-hook-protocol` adds log-only `hook/invoked` / `hook/result` records for a hook bridge. Like `compaction/*`, these are NOT `SurfaceEventType`s (no `surfaceOp`). The generated [persistence log event catalog](../persistence-catalog.md) enumerates every member — core and merged — with its payload, surface badge, and declaration site.
|
|
15
16
|
|
|
16
17
|
```ts type-equiv
|
|
17
|
-
/** A user-role specialization of the
|
|
18
|
-
interface UserMessage extends
|
|
18
|
+
/** A user-role specialization of the shared message representation. */
|
|
19
|
+
interface UserMessage extends MessageBase {
|
|
19
20
|
readonly role: 'user'
|
|
20
21
|
}
|
|
21
22
|
```
|
|
@@ -56,6 +57,27 @@ interface SessionEventMap {
|
|
|
56
57
|
* project their `content` verbatim; `source` tells them apart.
|
|
57
58
|
*/
|
|
58
59
|
'user/message': UserMessage
|
|
60
|
+
/** An incremental agent session change admitted at the named turn and step. */
|
|
61
|
+
'developer/message': {
|
|
62
|
+
turn: number
|
|
63
|
+
step: number
|
|
64
|
+
message: DeveloperMessage
|
|
65
|
+
/** Earlier request/header defining every tool addition; required exactly when additions are present. */
|
|
66
|
+
headerSeq?: SessionSeq
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The rendered system prompt on the model-visible surface. The loop appends
|
|
70
|
+
* the first one as surface node 0 before the step's first `user/message`.
|
|
71
|
+
* A prepared in-history route can append nonempty changes in a continuing
|
|
72
|
+
* series. An incapable route or new series normalizes text to the first system
|
|
73
|
+
* node. Normalization empties nonempty later nodes, then rewrites the head if
|
|
74
|
+
* needed, through logged per-node replacements. An empty rendering always
|
|
75
|
+
* clears all active system nodes, leaving no older instructions model-visible.
|
|
76
|
+
* Empty later nodes are dormant and project to no message; an empty head with
|
|
77
|
+
* no active later node records "no system prompt". Restored nonempty text follows
|
|
78
|
+
* the same route and series rule; empty nodes never restore older text.
|
|
79
|
+
*/
|
|
80
|
+
'system/message': { turn: number; step: number; message: SystemMessage }
|
|
59
81
|
/**
|
|
60
82
|
* Assembled assistant message for one step (derived history uses this).
|
|
61
83
|
* Carries the step's `usage` when the adapter reported token accounting, so
|
|
@@ -89,7 +111,9 @@ interface SessionEventMap {
|
|
|
89
111
|
'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string }
|
|
90
112
|
/**
|
|
91
113
|
* A completed tool call's model-facing result, optional internal failure
|
|
92
|
-
* identity, and optional tool-private `meta`
|
|
114
|
+
* identity and user-facing reason, and optional tool-private `meta`
|
|
115
|
+
* presentation payload. The reason remains outside the model-facing message.
|
|
116
|
+
* `meta` is
|
|
93
117
|
* opaque to the core (the producing tool owns its shape and reads it back in
|
|
94
118
|
* `presentResult`) but MUST be JSON-serializable: `Session.append`
|
|
95
119
|
* runtime-validates all event data with `isJsonValue`, so a non-serializable
|
|
@@ -102,7 +126,11 @@ interface SessionEventMap {
|
|
|
102
126
|
turn: number
|
|
103
127
|
step: number
|
|
104
128
|
message: ToolResultMessage
|
|
105
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Optional failure identity and raw user-facing reason, outside model content;
|
|
131
|
+
* allowed only when the message has `isError: true`.
|
|
132
|
+
*/
|
|
133
|
+
error?: { name: string; code: string; reason?: string }
|
|
106
134
|
meta?: JsonValue
|
|
107
135
|
}
|
|
108
136
|
/**
|
|
@@ -112,27 +140,31 @@ interface SessionEventMap {
|
|
|
112
140
|
'request/header': {
|
|
113
141
|
header: EpochHeader
|
|
114
142
|
reason: RequestHeaderReason
|
|
115
|
-
/**
|
|
143
|
+
/** This request begins a distinct model-message series, independently of the header reason. */
|
|
116
144
|
startsSeries?: true
|
|
117
145
|
}
|
|
118
146
|
/**
|
|
119
|
-
* Route metadata for the next request, logged only when the route
|
|
120
|
-
* changes. It does not participate in request
|
|
147
|
+
* Route metadata for the next request, logged only when the route, capacity,
|
|
148
|
+
* or system prompt update mode changes. It does not participate in request
|
|
149
|
+
* reconstruction or header equality. Prompt admission uses the bound prepared
|
|
150
|
+
* call's capability, not this snapshot from an earlier request.
|
|
121
151
|
*/
|
|
122
152
|
'request/context': RequestContext
|
|
123
153
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
154
|
+
* Separates inherited or restored history from later lifecycle-owned work.
|
|
155
|
+
* This log-only marker need not be at {@link Session.firstLiveSeq}: a fork
|
|
156
|
+
* seed can already contain its tagged marker and child-owned synthetic
|
|
157
|
+
* closers before construction.
|
|
128
158
|
*
|
|
129
159
|
* A fresh fork child owns one `{ inherited: true }` marker at its exact
|
|
130
160
|
* inherited-prefix cut, even when that prefix ends in an ancestor marker.
|
|
131
|
-
*
|
|
132
|
-
*
|
|
161
|
+
* `buildForkSeed` appends that marker before any synthetic closers; the
|
|
162
|
+
* `Session` constructor supplies it when given only the inherited prefix.
|
|
163
|
+
* The last tagged marker is the current Session's cut; untagged markers
|
|
164
|
+
* keep ordinary restore and replay lifecycle boundaries.
|
|
133
165
|
*
|
|
134
|
-
* `Session`
|
|
135
|
-
*
|
|
166
|
+
* Only the `Session` constructor and `buildForkSeed` may create this marker.
|
|
167
|
+
* Session append does not reject other writers, so a plugin appending one
|
|
136
168
|
* would silently classify every live bracket before it as seed history.
|
|
137
169
|
*
|
|
138
170
|
* An owner of a standalone open/close bracket (`compaction/start` …
|
|
@@ -152,12 +184,13 @@ interface SessionEventMap {
|
|
|
152
184
|
|
|
153
185
|
### The request header event: `request/header`
|
|
154
186
|
|
|
155
|
-
The request envelope — the `EpochHeader` (call config + markers for adapter-supplied defaults +
|
|
187
|
+
The request envelope — the `EpochHeader` (call config + markers for adapter-supplied defaults + assembled tool schemas) — is logged session state, so every conversation request is a pure function of the log (the reconstructability Agent Note). The rendered system prompt is not part of the header: it is derived history, the `system/message` event at surface node 0 and any later in-history system node ([decision](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-09-02-system-prompt-as-surface-node.md)), so a prompt change replaces or appends a system node and leaves the header unchanged. A full `request/header` snapshot with reason `'initial'` or `'resume'` records each loop-instance boundary; a changed request appends a snapshot with reason `'change'`; and an unchanged envelope beginning an explicitly declared message series or following a surface replacement appends a snapshot with reason `'series'`. An `'initial'`, `'resume'`, or `'change'` snapshot carries `startsSeries: true` when that request also begins a series; reason `'series'` already records that fact. Ordinary append-only later Turns, further Steps, and retries in the same model-message series inherit the latest snapshot. `foldRequestHeader(events)` reconstructs the header by selecting the latest snapshot. The event is not a `SurfaceEventType`: it produces no LLM message.
|
|
156
188
|
|
|
157
189
|
```ts type-equiv
|
|
158
190
|
/**
|
|
159
|
-
* Logged request state outside derived history: call config
|
|
160
|
-
*
|
|
191
|
+
* Logged request state outside derived history: call config and tools. The
|
|
192
|
+
* system prompt is derived history — surface node 0, a `system/message` event.
|
|
193
|
+
* The latest full `request/header` snapshot reconstructs the header; canonical
|
|
161
194
|
* empty optional fields are absent.
|
|
162
195
|
*/
|
|
163
196
|
interface EpochHeader {
|
|
@@ -165,18 +198,20 @@ interface EpochHeader {
|
|
|
165
198
|
config: LlmCallConfig
|
|
166
199
|
/** Effective config fields materialized from the exact adapter rather than proposed by a caller. */
|
|
167
200
|
adapterDefaults?: LlmCallConfigAdapterDefaults
|
|
168
|
-
/** Rendered system prompt text; absent for a system-less request. */
|
|
169
|
-
system?: string
|
|
170
201
|
/** Assembled tool schemas; absent for a tool-less request. */
|
|
171
202
|
tools?: ToolSchema[]
|
|
203
|
+
/** Retired request text; system prompts belong to system/message events.
|
|
204
|
+
* @persistenceReserved
|
|
205
|
+
*/
|
|
206
|
+
system?: never
|
|
172
207
|
}
|
|
173
208
|
```
|
|
174
209
|
|
|
175
|
-
|
|
210
|
+
Current event acceptance requires canonical `request/header.header`: any `system` field is forbidden, and `tools: []` and `adapterDefaults: {}` must be omitted. Whitespace-only system-message content, `config.stop: []`, and nested extensions remain unchanged. Seed, append, and current persistence reads reject noncanonical headers rather than silently normalizing them; [the V3 envelope decision](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-09-06-v3-canonical-session-envelopes.md) owns historical conversion. Legacy v0 logs containing `request/header-delta` or its full-snapshot `fallback` reason are rejected rather than replayed incompletely.
|
|
176
211
|
|
|
177
212
|
### The route capacity event: `request/context`
|
|
178
213
|
|
|
179
|
-
The context metadata of the route a request resolved to is separate logged state, appended beside `request/header` inside the same step and only when the provider, model, or
|
|
214
|
+
The context metadata of the route a request resolved to is separate logged state, appended beside `request/header` inside the same step and only when the provider, model, capacity, or `systemPromptUpdate` mode differs from the previous record. It stays outside `EpochHeader` because that type is the reconstruction contract compared field-wise by `headerEquals`: capacity and the update mode describe a route, not a request input, so folding them in would let a route change register as a request-envelope `change` and would pull adapter metadata into the loop's request reconstruction. Like `request/header`, it is not a `SurfaceEventType` and produces no LLM message. `session.requestContext()` folds the latest record incrementally; the agent loop reads that record's `systemPromptUpdate` when it decides whether a changed system prompt replaces the latest system node or is appended after the cached history ([decision rule](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent-loop/README.md#understand-the-implementation)). A route whose adapter advertises no capacity is recorded with `contextWindow` absent, so the new record clears an older route's capacity; a route without a declared update mode likewise clears an older route's `systemPromptUpdate`.
|
|
180
215
|
|
|
181
216
|
```ts type-equiv
|
|
182
217
|
/** Registration-bound metadata for one resolved model route. */
|
|
@@ -187,6 +222,8 @@ interface RequestContext {
|
|
|
187
222
|
model: string
|
|
188
223
|
/** Maximum combined request and response context in tokens, when advertised. */
|
|
189
224
|
contextWindow?: number
|
|
225
|
+
/** `'in-history'` when the route reads the latest `system` message at any position as the effective system prompt. */
|
|
226
|
+
systemPromptUpdate?: SystemPromptUpdate
|
|
190
227
|
}
|
|
191
228
|
```
|
|
192
229
|
|
|
@@ -224,7 +261,7 @@ type OptionalSessionSeq = SessionSeq | null
|
|
|
224
261
|
* unions), so `switch (event.type)` narrows `event.data` without casts.
|
|
225
262
|
*
|
|
226
263
|
* The {@link sourceEventSeqs} and {@link surfaceOp} fields are conditional:
|
|
227
|
-
* they only exist on {@link SurfaceEventType} variants (`user/message`,
|
|
264
|
+
* they only exist on {@link SurfaceEventType} variants (`system/message`, `user/message`,
|
|
228
265
|
* `assistant/message`, `tool/result`).
|
|
229
266
|
* Non-surface events (boundary markers, attempts, errors) never carry
|
|
230
267
|
* surface metadata — the compiler enforces this at `Session.append()`
|
|
@@ -249,26 +286,20 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
|
|
249
286
|
* inconvenience) rather than silently resuming a gutted session.
|
|
250
287
|
*/
|
|
251
288
|
ignorable?: true
|
|
252
|
-
} & (K extends SurfaceEventType ? {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* `assistant/message` embeds its provider stream and cannot carry this field.
|
|
257
|
-
*/
|
|
258
|
-
sourceEventSeqs?: SessionSeq[]
|
|
259
|
-
/** How this event entered the surface; absent for non-surface events. */
|
|
260
|
-
surfaceOp?: SurfaceOp
|
|
261
|
-
} : object)
|
|
289
|
+
} & (K extends SurfaceEventType ? SurfaceIntent<K> : {
|
|
290
|
+
surfaceOp?: never
|
|
291
|
+
sourceEventSeqs?: never
|
|
292
|
+
})
|
|
262
293
|
}[T]
|
|
263
294
|
```
|
|
264
295
|
|
|
265
296
|
`SessionEventType = keyof SessionEventMap`. Because `SessionEventMap` is merge-extensible, switches over `SessionEvent` must NOT use `assertNever` — a plugin-added variant is a valid unknown value; handle the known cases and fall through `default`.
|
|
266
297
|
|
|
267
|
-
|
|
298
|
+
Every surface event requires `surfaceOp`; known log-only events forbid both surface metadata fields. Native unknown or obsolete ignorable envelopes remain opaque. `assistant/message` embeds its provider stream and forbids `sourceEventSeqs`. System, user, and tool surface events may cite a complete non-empty set of unique earlier events when source attribution or replacement coverage requires it. A `tool/result` may carry `data.error` only when its message has `isError: true`; failure identity remains optional for failed results.
|
|
268
299
|
|
|
269
300
|
## Surface types
|
|
270
301
|
|
|
271
|
-
The
|
|
302
|
+
The message-producing types (`SurfaceEventType` — `system/message`, `developer/message`, `user/message`, `assistant/message`, `tool/result`) carry surface metadata declaring how they join the ordered derived surface. `system/message` holds the rendered system prompt: the loop appends the first one as surface node 0 and, when the prompt changes, replaces exactly the latest system node or appends a new one on an in-history route; the surface fold rejects any other replacement covering a `system/message` at node 0, while a later system node is ordinary history that a compaction replacement may shadow. See the [session surface Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-06-18-session-surface.md).
|
|
272
303
|
|
|
273
304
|
### `SurfaceEventType` — the message-producing subset of event types
|
|
274
305
|
|
|
@@ -276,10 +307,12 @@ The three message-producing types (`SurfaceEventType` — `user/message`, `assis
|
|
|
276
307
|
/**
|
|
277
308
|
* The subset of {@link SessionEventType} values whose events produce LLM
|
|
278
309
|
* messages and are eligible to appear on the ordered surface. Only these
|
|
279
|
-
* event types may carry {@link SurfaceOp}; user and tool events may also cite
|
|
310
|
+
* event types may carry {@link SurfaceOp}; system, user, and tool events may also cite
|
|
280
311
|
* earlier sources through {@link SessionEvent.sourceEventSeqs}.
|
|
281
312
|
*/
|
|
282
313
|
type SurfaceEventType =
|
|
314
|
+
| 'system/message'
|
|
315
|
+
| 'developer/message'
|
|
283
316
|
| 'user/message'
|
|
284
317
|
| 'assistant/message'
|
|
285
318
|
| 'tool/result'
|
|
@@ -294,19 +327,19 @@ type SurfaceEventType =
|
|
|
294
327
|
*
|
|
295
328
|
* - `'append'`: added to the tail — normal path for user/assistant/tool
|
|
296
329
|
* messages.
|
|
297
|
-
* - `{ op: 'replace',
|
|
298
|
-
* (inclusive) through `
|
|
299
|
-
* surface nodes in the current surface. `
|
|
330
|
+
* - `{ op: 'replace', startSeq, endSeq }`: replaces surface nodes from `startSeq`
|
|
331
|
+
* (inclusive) through `endSeq` (inclusive) with this node. Both must exist as
|
|
332
|
+
* surface nodes in the current surface. `startSeq === endSeq` replaces a single
|
|
300
333
|
* node. The node's {@link SessionEvent.sourceEventSeqs} must include every
|
|
301
334
|
* shadowed surface node. Used by compaction; any surface-replacing producer
|
|
302
335
|
* may use it.
|
|
303
336
|
*/
|
|
304
337
|
type SurfaceOp =
|
|
305
338
|
| 'append'
|
|
306
|
-
| { op: 'replace';
|
|
339
|
+
| { op: 'replace'; startSeq: SessionSeq; endSeq: SessionSeq }
|
|
307
340
|
```
|
|
308
341
|
|
|
309
|
-
`'append'` is the normal tail-append path. `replace`
|
|
342
|
+
`'append'` is the normal tail-append path. `replace` contains exactly `op`, `startSeq`, and `endSeq`, with no aliases or extra keys. It shadows the inclusive span between those current surface event sequences and inserts the new event in their place; equal endpoints replace one entry. Endpoints must precede the replacing event, but their relative order is surface order, not numeric sequence order.
|
|
310
343
|
|
|
311
344
|
### `SurfaceIntent` — the parameter to `session.append()`
|
|
312
345
|
|
|
@@ -318,7 +351,7 @@ type SurfaceOp =
|
|
|
318
351
|
type SurfaceIntent<T extends SurfaceEventType = SurfaceEventType> = {
|
|
319
352
|
surfaceOp: SurfaceOp
|
|
320
353
|
} & (T extends 'assistant/message' ? {
|
|
321
|
-
/**
|
|
354
|
+
/** Assistant messages embed their provider stream instead of citing source events. */
|
|
322
355
|
sourceEventSeqs?: never
|
|
323
356
|
} : {
|
|
324
357
|
/** Complete non-empty set of known earlier source-event seqs. */
|
|
@@ -330,11 +363,47 @@ Required for `SurfaceEventType` events — every message-producing event must de
|
|
|
330
363
|
|
|
331
364
|
`assistant/message` cannot carry `sourceEventSeqs`; its `stream` owns exact provider evidence. Other surface events omit the field when they cite no earlier event and use a complete non-empty list when they do.
|
|
332
365
|
|
|
366
|
+
<a id="plugin-owned-message-projections"></a>
|
|
367
|
+
### Plugin-owned message projections
|
|
368
|
+
|
|
369
|
+
Content-changing plugins mark their event declaration with `@messageProjection` and register a pure definition through `ctx.sessions.registerMessageProjection()`. Session validates the complete decision through that definition before commit, applies its immutable message updates, and advances `contentGeneration`. It rejects missing interpreters, including on restore and detached folding; unloading a used definition blocks cached reads. Detached readers pass explicit definitions to `foldSurface(events, projections)` and apply `projectedMessages` through `deriveEventMessage()`. The installed format catalog assembles first-party definitions for offline readers. The [image-offload plugin](./compaction.md#image-offload) owns its image-specific event and interpretation.
|
|
370
|
+
|
|
371
|
+
```ts type-equiv
|
|
372
|
+
/** Readonly history immediately before a message-projection event. */
|
|
373
|
+
interface SessionMessageProjectionContext {
|
|
374
|
+
/** Current message-producing event sequences in model-visible order. */
|
|
375
|
+
nodes: readonly SessionSeq[]
|
|
376
|
+
/** Contiguous event window; entries at or beyond the candidate seq are not committed inputs. */
|
|
377
|
+
events: readonly SessionEvent[]
|
|
378
|
+
/** Absolute sequence of the window's first event. */
|
|
379
|
+
baseSeq: SessionLogOffset
|
|
380
|
+
/** Previously projected messages keyed by their original event sequences. */
|
|
381
|
+
messages: ReadonlyMap<SessionSeq, Message>
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
```ts type-equiv
|
|
386
|
+
/** Pure interpretation of one plugin-owned event that changes existing message content. */
|
|
387
|
+
interface SessionMessageProjection<T extends SessionEventType = SessionEventType> {
|
|
388
|
+
/** Event interpreted by this definition; declare it with `@messageProjection` in SessionEventMap. */
|
|
389
|
+
type: T
|
|
390
|
+
/**
|
|
391
|
+
* Validate the complete durable decision before returning any updates. Preserve
|
|
392
|
+
* message identities and publish immutable copies without mutating the input.
|
|
393
|
+
* @param event - candidate event, not yet applied to the supplied history.
|
|
394
|
+
* @param context - history preceding this decision.
|
|
395
|
+
* @returns changed current messages keyed by their original sequences.
|
|
396
|
+
* @throws when the durable decision cannot be applied to this history.
|
|
397
|
+
*/
|
|
398
|
+
project(event: SessionEvent<T>, context: SessionMessageProjectionContext): ReadonlyMap<SessionSeq, Message>
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
333
402
|
### `SessionSurface` — the live readonly surface projection
|
|
334
403
|
|
|
335
404
|
`Session.surface` returns the session's stable `SessionSurface` view. The same incremental manager validates append candidates before commit and advances this projection from committed events; callers can observe membership and replacement generation but cannot invoke validation.
|
|
336
405
|
|
|
337
|
-
`SurfaceManager(log, baseSeq?)` can instead fold a contiguous loaded window whose first event has the absolute sequence `baseSeq`. Every event remains contiguous in that absolute sequence space, and a replacement that crosses the window head fails because its declared range is absent.
|
|
406
|
+
`SurfaceManager(log, baseSeq?, projections?)` can instead fold a contiguous loaded window whose first event has the absolute sequence `baseSeq`. Every event remains contiguous in that absolute sequence space, and a replacement that crosses the window head fails because its declared range is absent.
|
|
338
407
|
|
|
339
408
|
```ts type-equiv
|
|
340
409
|
/** Readonly live projection of the message-producing session events. */
|
|
@@ -343,12 +412,14 @@ interface SessionSurface {
|
|
|
343
412
|
readonly nodes: readonly SessionSeq[]
|
|
344
413
|
/** Monotonic count of committed positional replacements. */
|
|
345
414
|
readonly replaceGeneration: number
|
|
415
|
+
/** Monotonic count of committed replacements and plugin-owned message changes. */
|
|
416
|
+
readonly contentGeneration: number
|
|
346
417
|
}
|
|
347
418
|
```
|
|
348
419
|
|
|
349
420
|
### `SurfaceFoldReplacement` and `SurfaceFoldResult` — a complete surface replay
|
|
350
421
|
|
|
351
|
-
`foldSurface(events)` returns detached current event sequences together with the actual sequences shadowed by each declared replacement range. The live manager uses the same transitions without retaining replacement history. Its `replaceGeneration` increments for each committed replacement so incremental consumers can distinguish pure tail growth from a rewrite.
|
|
422
|
+
`foldSurface(events, projections)` returns detached current event sequences together with the actual sequences shadowed by each declared replacement range. The live manager uses the same transitions without retaining replacement history. Its `replaceGeneration` increments for each committed replacement so incremental consumers can distinguish pure tail growth from a rewrite.
|
|
352
423
|
|
|
353
424
|
```ts type-equiv
|
|
354
425
|
/** One replacement operation observed while folding a session surface. */
|
|
@@ -371,6 +442,8 @@ interface SurfaceFoldResult {
|
|
|
371
442
|
nodes: SessionSeq[]
|
|
372
443
|
/** Replacement operations in event order. */
|
|
373
444
|
replacements: SurfaceFoldReplacement[]
|
|
445
|
+
/** Immutable projected messages, keyed by their original event sequences. */
|
|
446
|
+
projectedMessages: ReadonlyMap<SessionSeq, Message>
|
|
374
447
|
}
|
|
375
448
|
```
|
|
376
449
|
|
|
@@ -404,29 +477,26 @@ declare class Session {
|
|
|
404
477
|
/** The session identity, derived from its durable header's single copy. */
|
|
405
478
|
get id(): SessionId;
|
|
406
479
|
/**
|
|
407
|
-
* The
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
* the constructor-input boundary for lifecycle ownership and persistence
|
|
412
|
-
* adoption; consumers that need complete canonical history still start at
|
|
413
|
-
* seq 0. Distinct from {@link inheritedEventCount}, the DURABLE
|
|
414
|
-
* fork-lineage cut: a resumed session's constructor seed is its full stored
|
|
415
|
-
* log, while the inherited count keeps the original fork value — this field is the
|
|
416
|
-
* in-process construction fact.
|
|
417
|
-
*
|
|
418
|
-
* Not persisted itself: a seeded session projects it into the log as the
|
|
419
|
-
* `session/end-seed` event, which is what a consumer reading STORED history
|
|
420
|
-
* reads. Locate the LAST such event, not necessarily one at this seq — a
|
|
421
|
-
* seed already ending in one is not re-marked, so reopening an untouched
|
|
422
|
-
* session leaves that event at a smaller seq than `firstLiveSeq`. Prefer
|
|
423
|
-
* this field in-process: it is exact before the marker reaches storage.
|
|
480
|
+
* The constructor seed length (0 without one), before any marker appended
|
|
481
|
+
* during construction. Seed events never publish on `session/event`. A
|
|
482
|
+
* marker appended before the store attaches occupies this seq without
|
|
483
|
+
* publishing either; otherwise this seq is available for the next append.
|
|
424
484
|
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
|
|
485
|
+
* This in-process offset is not persisted. A fork seed can already contain
|
|
486
|
+
* the child's inherited marker and synthetic closers, so its child-owned
|
|
487
|
+
* history starts at {@link inheritedEventCount}, before this offset. A
|
|
488
|
+
* resumed Session's seed contains its full stored log, while its inherited
|
|
489
|
+
* count keeps the durable fork cut. Consumers needing complete canonical
|
|
490
|
+
* history start at seq 0.
|
|
491
|
+
*/
|
|
429
492
|
readonly firstLiveSeq: SessionLogOffset;
|
|
493
|
+
/**
|
|
494
|
+
* First event produced for this object lifecycle. A new fork includes its
|
|
495
|
+
* child-owned seed marker and closers; a restored Session starts after its
|
|
496
|
+
* complete stored prefix. This in-process capture offset is not persisted.
|
|
497
|
+
*/
|
|
498
|
+
readonly firstLifecycleSeq: SessionLogOffset;
|
|
499
|
+
|
|
430
500
|
/**
|
|
431
501
|
* Create a detached session by validating and snapshotting borrowed seed
|
|
432
502
|
* events and storage metadata.
|
|
@@ -434,32 +504,44 @@ declare class Session {
|
|
|
434
504
|
* @param seed - optional borrowed replay or fork events.
|
|
435
505
|
* @param header - optional borrowed storage metadata.
|
|
436
506
|
* @param inheritedEventCount - exact fork-inherited prefix length for a seeded header.
|
|
507
|
+
* @param projections - pure interpreters for plugin-owned message changes.
|
|
437
508
|
* @returns a detached session.
|
|
509
|
+
* @throws when a seed event requires a missing message interpreter or fails validation.
|
|
438
510
|
*/
|
|
439
511
|
static create(
|
|
440
512
|
id: SessionId,
|
|
441
513
|
seed?: readonly SessionEvent[],
|
|
442
514
|
header?: SessionHeader,
|
|
443
515
|
inheritedEventCount?: SessionLogOffset,
|
|
444
|
-
|
|
516
|
+
projections?: readonly SessionMessageProjection[],
|
|
517
|
+
): Session;
|
|
445
518
|
/**
|
|
446
|
-
* Restore a detached session by
|
|
447
|
-
*
|
|
448
|
-
* and header fields are validated
|
|
519
|
+
* Restore a detached session by adopting an independently owned or deeply frozen seed.
|
|
520
|
+
* Runtime-required event fields, event envelopes, sequence continuity, surface
|
|
521
|
+
* transitions, and header fields are validated without copying or freezing events.
|
|
522
|
+
* Embedded Assistant streams remain opaque until a stream consumer or storage
|
|
523
|
+
* verifier reads them.
|
|
449
524
|
* @param id - restored session identity.
|
|
450
|
-
* @param seed -
|
|
451
|
-
* @param header -
|
|
525
|
+
* @param seed - independently owned or deeply frozen events.
|
|
526
|
+
* @param header - independently owned storage metadata.
|
|
452
527
|
* @param inheritedEventCount - exact fork-inherited prefix length decoded from storage.
|
|
528
|
+
* @param eventState - aliasing state carried from the operation that produced the seed.
|
|
529
|
+
* @param projections - pure interpreters for plugin-owned message changes.
|
|
453
530
|
* @returns a restored detached session.
|
|
531
|
+
* @throws when a seed event requires a missing message interpreter or fails validation.
|
|
454
532
|
*/
|
|
455
533
|
static fromRestore(
|
|
456
534
|
id: SessionId,
|
|
457
535
|
seed: readonly SessionEvent[],
|
|
458
536
|
header: SessionHeader,
|
|
459
537
|
inheritedEventCount: SessionLogOffset,
|
|
460
|
-
|
|
538
|
+
eventState: SessionSeedEventState,
|
|
539
|
+
projections?: readonly SessionMessageProjection[],
|
|
540
|
+
): Session;
|
|
461
541
|
/**
|
|
462
542
|
* Return the immutable event stored at one exact sequence number.
|
|
543
|
+
* @deprecated Existing logic may remain unmigrated for now, but new calls are prohibited.
|
|
544
|
+
* See the [Agent Note](../../../../.agents/notes/implemented/architecture/2026-09-09-deprecate-synchronous-session-event-reads.md).
|
|
463
545
|
* @param seq - event sequence number.
|
|
464
546
|
* @returns the accepted event, or undefined when the log does not contain it.
|
|
465
547
|
*/
|
|
@@ -468,6 +550,8 @@ declare class Session {
|
|
|
468
550
|
* Materialize an immutable snapshot of a half-open event sequence range.
|
|
469
551
|
* A full current snapshot is reused until the next append; every previously
|
|
470
552
|
* returned snapshot remains stable after later appends.
|
|
553
|
+
* @deprecated Existing logic may remain unmigrated for now, but new calls are prohibited.
|
|
554
|
+
* See the [Agent Note](../../../../.agents/notes/implemented/architecture/2026-09-09-deprecate-synchronous-session-event-reads.md).
|
|
471
555
|
* @param fromSeq - non-negative inclusive sequence number; defaults to the log start.
|
|
472
556
|
* @param toSeqExclusive - non-negative exclusive sequence number; defaults to the current end.
|
|
473
557
|
* @returns a frozen array of the selected deeply frozen events.
|
|
@@ -475,9 +559,11 @@ declare class Session {
|
|
|
475
559
|
snapshotEvents(
|
|
476
560
|
fromSeq: SessionLogOffset = SessionLogOffset(0),
|
|
477
561
|
toSeqExclusive: SessionLogOffset = this.seq,
|
|
478
|
-
|
|
562
|
+
): readonly SessionEvent[];
|
|
479
563
|
/**
|
|
480
564
|
* Return this Session's events after its fork-inherited prefix.
|
|
565
|
+
* @deprecated Existing logic may remain unmigrated for now, but new calls are prohibited.
|
|
566
|
+
* See the [Agent Note](../../../../.agents/notes/implemented/architecture/2026-09-09-deprecate-synchronous-session-event-reads.md).
|
|
481
567
|
* @returns a fresh array containing child-owned events in log order.
|
|
482
568
|
*/
|
|
483
569
|
ownEvents(): readonly SessionEvent[];
|
|
@@ -515,6 +601,7 @@ declare class Session {
|
|
|
515
601
|
* (BigInt, function, symbol, undefined, negative zero, non-finite number,
|
|
516
602
|
* circular reference, sparse array, or an exotic object such as
|
|
517
603
|
* Map/Set/Date/class instance), or when the candidate violates the
|
|
604
|
+
* request-header empty-field or tool-error consistency rules, or the
|
|
518
605
|
* canonical surface contract (marker shape and eligibility, unique
|
|
519
606
|
* earlier source-event references, positional replacement validity, and complete
|
|
520
607
|
* shadowed-node coverage). One iterative pass reads, validates, and
|
|
@@ -529,7 +616,7 @@ declare class Session {
|
|
|
529
616
|
type: T,
|
|
530
617
|
data: SessionEventMap[T],
|
|
531
618
|
...opts: T extends SurfaceEventType ? [opts: SurfaceIntent<T>] : []
|
|
532
|
-
|
|
619
|
+
): SessionEvent<T>;
|
|
533
620
|
/**
|
|
534
621
|
* The {@link EpochHeader} in force after the log's last header event — the
|
|
535
622
|
* header the NEXT request will be compared against — or undefined before
|
|
@@ -545,6 +632,12 @@ declare class Session {
|
|
|
545
632
|
* @returns the latest immutable route metadata.
|
|
546
633
|
*/
|
|
547
634
|
requestContext(): RequestContext | undefined;
|
|
635
|
+
/**
|
|
636
|
+
* Fold unseen committed events into capability-independent tool history.
|
|
637
|
+
* Initial access reconstructs inherited history; later reads consume only new events.
|
|
638
|
+
* @returns an immutable snapshot for LLM request projection, including historical addition definitions.
|
|
639
|
+
*/
|
|
640
|
+
toolHistory(): ToolHistory;
|
|
548
641
|
/**
|
|
549
642
|
* Derive the LLM message history by walking the ordered sequences of
|
|
550
643
|
* message-producing events maintained by `surfaceOp` markers. The
|
|
@@ -552,21 +645,21 @@ declare class Session {
|
|
|
552
645
|
* append records its `surfaceOp`, so a raw event with no marker (a chunk, a
|
|
553
646
|
* turn boundary) is correctly absent, and a compaction `replace` deletes the
|
|
554
647
|
* shadowed nodes from the derivation. The projection rules are
|
|
555
|
-
* {@link deriveEventMessage},
|
|
648
|
+
* {@link deriveEventMessage}, with logged message projections applied
|
|
649
|
+
* without changing node membership or message identity.
|
|
556
650
|
*
|
|
557
|
-
* CACHED:
|
|
558
|
-
*
|
|
559
|
-
* {@link SessionSurface.replaceGeneration}) rebuilds. The returned array is
|
|
651
|
+
* CACHED: pure tail growth costs O(new nodes); a replacement or message projection
|
|
652
|
+
* ({@link SessionSurface.contentGeneration}) rebuilds. The returned array is
|
|
560
653
|
* a fresh snapshot per call (later appends never grow an array a caller
|
|
561
654
|
* already holds); the `Message` objects in it are SHARED and **deep-frozen**.
|
|
562
|
-
*
|
|
563
|
-
*
|
|
655
|
+
* Unchanged content reuses frozen event data; projected blocks are frozen
|
|
656
|
+
* derived copies. Consumers cannot mutate the log through either form.
|
|
564
657
|
* @returns a fresh array of the shared, frozen derived history.
|
|
565
658
|
*/
|
|
566
659
|
deriveMessages(): Message[];
|
|
567
660
|
/**
|
|
568
|
-
*
|
|
569
|
-
*
|
|
661
|
+
* Project one event with all committed message projections applied.
|
|
662
|
+
* The original durable event remains unchanged.
|
|
570
663
|
* @param event - the event to project.
|
|
571
664
|
* @returns the derived message, or null when the event produces none.
|
|
572
665
|
*/
|
|
@@ -576,11 +669,11 @@ declare class Session {
|
|
|
576
669
|
|
|
577
670
|
## Derived history: `deriveMessages()` and `deriveEventMessage()`
|
|
578
671
|
|
|
579
|
-
`Session.deriveMessages()` projects the event log into the `Message[]` the model sees — cached (each surface node projected once, when first seen; a surface rewrite rebuilds) and frozen (a fresh array per call over shared, deep-frozen messages, so mutating logged history through a projection is unrepresentable). `deriveEventMessage(event)` is the per-node pure function the fold applies — public so external reconstructors
|
|
672
|
+
`Session.deriveMessages()` projects the event log into the `Message[]` the model sees — cached (each surface node projected once, when first seen; a surface rewrite rebuilds) and frozen (a fresh array per call over shared, deep-frozen messages, so mutating logged history through a projection is unrepresentable). `deriveEventMessage(event)` is the per-node pure function the fold applies — public so external reconstructors project a log prefix with exactly the same rules and cannot disagree with the cache. The projection rules:
|
|
580
673
|
|
|
581
674
|
- `user/message` → a user message carrying exact `content`; an optional envelope remains log-only display metadata.
|
|
582
675
|
- `assistant/message` → an assistant message with the provider and model that produced it plus optional adapter-private replay state. Its embedded compact stream is replay, usage, and UI evidence rather than a second message. An **empty-content** `assistant/message` is also skipped — a max-tokens step cut off with no content still records an `assistant/message` to hold its stream, usage, provider, and model, but a content-less assistant turn must not enter the provider transcript.
|
|
583
|
-
- `tool/result` → a
|
|
676
|
+
- `tool/result` → a first-class tool-role message carrying its result content and tool-call identity.
|
|
584
677
|
- `user/message` (injected context, i.e. non-`user` source) → a user-role message carrying its `content` verbatim at its chronological position; its typed source names the producer and carries any producer-specific data.
|
|
585
678
|
|
|
586
679
|
Everything else (`turn/*`, `step/*`, `assistant/attempt`, plugin-owned `llm/retry`) is structural and does not project into a message. Token accounting expands the embedded stream on each `assistant/message` or `assistant/attempt`, while the message's top-level `usage` remains the committed-message authority when present. A failed model-request attempt therefore retains its provider usage without fabricating an assistant message. Current logical validation rejects request headers and assistant messages that omit provider/model instead of guessing a route; supported historical representations are normalized and validated by their adjacent format edge before a current Session exists.
|
|
@@ -591,7 +684,7 @@ Everything else (`turn/*`, `step/*`, `assistant/attempt`, plugin-owned `llm/retr
|
|
|
591
684
|
|
|
592
685
|
- `fork(source, boundary?, childSessionId?)` accepts a live `Session` object or live `SessionId`, selects source events through the inclusive `SessionSeq` boundary (default: current last event), requires the selected prefix to end outside an open turn, then creates a live child session with deep-cloned seed events, `parentSession`, `isSeeded: true`, the exact `inheritedEventCount`, and inherited `cwd`.
|
|
593
686
|
|
|
594
|
-
An explicit `boundary` lets callers fork from any stable between-turn position, including a previous `turn/end` or a later standalone log-only event, even if the source has newer events or an open current turn. The API rejects a prefix that ends inside an open turn instead of clipping silently.
|
|
687
|
+
An explicit `boundary` lets callers fork from any stable between-turn position, including a previous `turn/end` or a later standalone log-only event, even if the source has newer events or an open current turn. The API rejects a prefix that ends inside an open turn instead of clipping silently. `dsh-subagent-fork-in-process` keeps its completed-prefix clipping because tool-time delegation usually starts while the parent turn is open; ordinary session branching should make the requested boundary explicit.
|
|
595
688
|
|
|
596
689
|
## Why a turn ended: `TurnEndReasonMap`
|
|
597
690
|
|
|
@@ -627,22 +720,29 @@ interface TurnEndReasonMap {
|
|
|
627
720
|
* the events recorded before the crash remain intact.
|
|
628
721
|
*/
|
|
629
722
|
interrupted: { kind: 'interrupted' }
|
|
723
|
+
/**
|
|
724
|
+
* Fork-seed construction closed a turn that was still open at the fork
|
|
725
|
+
* boundary in the source session. Only fork seeds carry this marker — the
|
|
726
|
+
* loop never emits it — and the source events before the boundary remain
|
|
727
|
+
* intact in the child.
|
|
728
|
+
*/
|
|
729
|
+
forked: { kind: 'forked' }
|
|
630
730
|
}
|
|
631
731
|
```
|
|
632
732
|
|
|
633
|
-
`max-tokens` mirrors the model-call `FinishReason` of the same name: any `max-tokens` step in a turn makes the whole turn end `max-tokens` rather than `completed` (the cut-short fact wins over a later continuation), so a consumer can tell a clean stop from a truncated one. Cancellation and errors remain distinct outcomes.
|
|
733
|
+
`max-tokens` mirrors the model-call `FinishReason` of the same name: any `max-tokens` step in a turn makes the whole turn end `max-tokens` rather than `completed` (the cut-short fact wins over a later continuation), so a consumer can tell a clean stop from a truncated one. Cancellation and errors remain distinct outcomes. The loop emits neither `interrupted` nor `forked` live: crash recovery synthesizes `interrupted` (see [persistence.md](./persistence.md)), while fork-seed construction synthesizes `forked`. The map is merge-extensible.
|
|
634
734
|
|
|
635
735
|
## Execution enclosure and standalone events
|
|
636
736
|
|
|
637
737
|
A turn encloses one model-loop execution, not the whole session log. AgentLoop records injected `user/message` events only from entering pre-step batches inside a turn; plugin-owned log-only events may still appear between `turn/end` and the next `turn/start`, consuming event seqs without incrementing turn numbers. Persistence admits every contiguous accepted event into a bounded durable batch, while crash repair closes only a genuinely open trailing turn. A producer that needs an immediate durability barrier explicitly awaits `ctx.sessions.flush(session)`.
|
|
638
738
|
|
|
639
|
-
|
|
739
|
+
Merge-extensible event relations belong to the plugin that declares them, so core does not reject an unknown event merely because no turn is open. See [the standalone-event decision](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/simplification/2026-07-28-remove-synthetic-log-only-turns.md).
|
|
640
740
|
|
|
641
741
|
## The end-seed boundary: `session/end-seed`
|
|
642
742
|
|
|
643
|
-
|
|
743
|
+
`buildForkSeed` appends `session/end-seed { inherited: true }` at the exact inherited-prefix cut before adding synthetic fork closers. The `Session` constructor retains that prepared marker or appends one when given only the inherited prefix. A restore retains the tagged marker and appends an ordinary `session/end-seed {}` only when its complete stored seed does not already end in a marker. Both forms are log-only and produce no message; only the constructor and `buildForkSeed` may create them.
|
|
644
744
|
|
|
645
|
-
For fork lineage, locate the LAST marker whose payload carries `inherited: true`;
|
|
745
|
+
For fork lineage, locate the LAST marker whose payload carries `inherited: true`; current-format decoding requires it exactly when `SessionHeader.isSeeded` is true and derives `inheritedEventCount` from its seq. For lifecycle ownership, locate the last `session/end-seed` of either form. Reopening a seed that already ends in any marker does not append another ordinary marker.
|
|
646
746
|
|
|
647
747
|
It exists because seed history and live work are otherwise byte-identical, which defeats any plugin owning a standalone open/close bracket: an unmatched `compaction/start` reads the same whether the writer crashed mid-compaction or is compacting right now. An opening marker before `session/end-seed` came from the constructor seed and belongs to an ended lifecycle, whatever ended it (a crash, a succeeding process, or a fork out of a still-running parent), so its owner may treat it as dead. That covers only brackets *this* session inherited: a concurrently live session holding an open bracket over the same history has its own boundary elsewhere, so tolerating concurrent writers needs a liveness signal beyond the log. Core writes the boundary and reads nothing from it — a bracket's vocabulary stays with its owning plugin, which is why crash repair closes turn/step/tool boundaries and never `compaction/*`.
|
|
648
748
|
|
|
@@ -650,15 +750,15 @@ Consumers that order Sessions by human activity exclude this boundary: picking a
|
|
|
650
750
|
|
|
651
751
|
## Plugin-contributed log-only events
|
|
652
752
|
|
|
653
|
-
A plugin may declaration-merge extra `SessionEventMap` types. These are **log-only**: NOT `SurfaceEventType`s (they carry no `surfaceOp` and contribute nothing to derived history). Their owner decides whether they belong to an open execution turn or may stand between turns
|
|
753
|
+
A plugin may declaration-merge extra `SessionEventMap` types. These are **log-only**: NOT `SurfaceEventType`s (they carry no `surfaceOp` and contribute nothing to derived history). Their owner decides whether they belong to an open execution turn or may stand between turns. The generated [persistence log event catalog](../persistence-catalog.md) enumerates every core and plugin-contributed event; the compaction seam's `compaction/*` semantics are discussed on [compaction.md](./compaction.md).
|
|
654
754
|
|
|
655
755
|
When several events in one plugin-owned family assemble into one Web Client Conversation Node, every start, update, result, resource, or interruption event in that family carries or independently derives the same stable business id. This requirement applies to correlated Node families, not to every Session event; it lets the client group each event without guessing from adjacency or scanning history. See the [Conversation subsystem](./conversation.md).
|
|
656
756
|
|
|
657
|
-
The hook bridges' `hook/invoked` / `hook/result` pairs (from `@deepseek-ai/dsh-hook-protocol`) correlate by `handlerId`. `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, and `Stop` fire inside the loop's open turn, so their `hook/*` records are turn-enclosed by construction. `SessionStart` gets no `hook/*` record because it runs before turn 1; its context remains pending in the inbox until a waking delivery opens a turn
|
|
757
|
+
The hook bridges' `hook/invoked` / `hook/result` pairs (from `@deepseek-ai/dsh-hook-protocol`) correlate by `handlerId`. `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, and `Stop` fire inside the loop's open turn, so their `hook/*` records are turn-enclosed by construction. `SessionStart` gets no `hook/*` record because it runs before turn 1; its context remains pending in the inbox until a waking delivery opens a turn.
|
|
658
758
|
|
|
659
759
|
## Durability contract
|
|
660
760
|
|
|
661
|
-
What a persistence backend relies on: the durable log persists every event losslessly, and every Assistant attempt is one `assistant/message` or `assistant/attempt` whose embedded compact stream preserves the original timed chunks. `seq` stays contiguous across these settlements and all interleaved events. A backend may choose its own storage framing for an event batch as long as a handle's `read()` returns the exact appended events; current JSONL
|
|
761
|
+
What a persistence backend relies on: the durable log persists every event losslessly, and every Assistant attempt is one `assistant/message` or `assistant/attempt` whose embedded compact stream preserves the original timed chunks. `seq` stays contiguous across these settlements and all interleaved events. A backend may choose its own storage framing for an event batch as long as a handle's `read()` returns the exact appended events; current JSONL writes one row per event (see [persistence.md](./persistence.md)). All `event.data` must be JSON-serializable; `Session.append` enforces this at the source (throwing on non-serializable data), so a bad event never enters the log and `session.snapshotEvents()` always equals what a backend can persist. Adding an event type that carries non-serializable data, corrupts core execution nesting, or violates its owner's declared relation is a breaking change to the on-disk format.
|
|
662
762
|
|
|
663
763
|
The backends that consume this contract are on [persistence.md](./persistence.md).
|
|
664
764
|
|
|
@@ -666,7 +766,9 @@ The backends that consume this contract are on [persistence.md](./persistence.md
|
|
|
666
766
|
|
|
667
767
|
`ModelCatalog` is the Host-generation model directory returned by `session/modelCatalog`: it carries the deployment default, routable provider ids, successful provider groups, and isolated provider failures. It is not derived from one Session and remains separate from Session projections.
|
|
668
768
|
|
|
669
|
-
`SessionOpenWorkspacePathRequest` carries an absolute or workspace-resolved `path
|
|
769
|
+
`SessionOpenWorkspacePathRequest` carries an absolute or workspace-resolved `path`; optional `action: "reveal"` selects file-manager navigation instead of default-application opening. `SessionOpenWorkspacePathValue` confirms that the Host accepted the native handoff. A Session-aware Client resolves relative paths against its current Session cwd when known; the controller hands the path to the opener unchanged and reports invalid requests, cancellation, and opener failures through the Session Remote error vocabulary.
|
|
770
|
+
|
|
771
|
+
The optional `application` selects a registered file handler without changing the system default; `workspacePathApplications({ path })` returns current handlers, names, icons, and default selection after Host path verification.
|
|
670
772
|
|
|
671
773
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
672
774
|
|
|
@@ -701,7 +803,7 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
|
|
701
803
|
/**
|
|
702
804
|
* Read all visible Session rows without resuming an Agent.
|
|
703
805
|
* @param _request - reserved empty list request.
|
|
704
|
-
* @param signal - cancellation for persistence reads.
|
|
806
|
+
* @param signal - cancellation for persistence reads and summary generation.
|
|
705
807
|
* @returns visible Session summaries ordered by activity.
|
|
706
808
|
*/
|
|
707
809
|
@Remote('list') async list(_request: SessionListRequest, signal: AbortSignal): Promise<SessionListValue>
|
|
@@ -722,12 +824,18 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
|
|
722
824
|
@Remote('create') create(request: SessionCreateRequest): Promise<SessionCreateValue>
|
|
723
825
|
|
|
724
826
|
/**
|
|
725
|
-
* Select one Session-local model after explicitly resuming the Session.
|
|
827
|
+
* Select one Session-local model after explicitly resuming the Session; save the default in the background.
|
|
726
828
|
* @param request - Session identity and requested model selection.
|
|
727
|
-
* @returns the normalized selection installed for the Session.
|
|
829
|
+
* @returns the normalized selection installed for the Session, without waiting for default persistence.
|
|
728
830
|
*/
|
|
729
831
|
@Remote('selectModel') selectModel(request: SessionSelectModelRequest): Promise<SessionSelectModelValue>
|
|
730
832
|
|
|
833
|
+
/**
|
|
834
|
+
* Select the first available account model after login when no provider API key is configured.
|
|
835
|
+
* @returns after saving the first available model or retaining the existing default.
|
|
836
|
+
*/
|
|
837
|
+
@Remote async initializeDefaultModel(): Promise<void>
|
|
838
|
+
|
|
731
839
|
/**
|
|
732
840
|
* Describe every currently routable model for Host-generation selectors.
|
|
733
841
|
* @returns provider-grouped models, the deployment default, and isolated provider failures.
|
|
@@ -741,14 +849,29 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
|
|
741
849
|
@Remote canOpenWorkspacePath(): boolean
|
|
742
850
|
|
|
743
851
|
/**
|
|
744
|
-
*
|
|
852
|
+
* Describe the serving desktop for authenticated file-action routes.
|
|
853
|
+
* @returns Host name, configured availability, and platform-specific file-manager behavior.
|
|
854
|
+
*/
|
|
855
|
+
workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | 'explorer' | 'directory' | null }
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Verify one path through the composed filesystem and open it on the Host desktop.
|
|
745
859
|
* @param request - path after best-effort Session workspace resolution.
|
|
746
860
|
* @param signal - caller lifetime; abort terminates the native command.
|
|
747
861
|
* @returns confirmation after the native opener accepts the path.
|
|
748
|
-
* @throws RemoteError when the request is invalid, cancelled, or the opener fails.
|
|
862
|
+
* @throws RemoteError when the request is invalid, has no verified Host mapping, is cancelled, or the opener fails.
|
|
749
863
|
*/
|
|
750
864
|
@Remote('openWorkspacePath') async openWorkspacePath( request: SessionOpenWorkspacePathRequest, signal: AbortSignal, ): Promise<SessionOpenWorkspacePathValue>
|
|
751
865
|
|
|
866
|
+
/**
|
|
867
|
+
* Query current file handlers on the serving desktop without activating an Agent.
|
|
868
|
+
* @param request - file path in Host filesystem syntax.
|
|
869
|
+
* @param signal - caller lifetime, propagated to filesystem and desktop queries.
|
|
870
|
+
* @returns OS application names, icons, and default selection; empty when desktop opening is unavailable.
|
|
871
|
+
* @throws RemoteError when the path is invalid, the query is cancelled, or native discovery fails.
|
|
872
|
+
*/
|
|
873
|
+
@Remote('workspacePathApplications') async workspacePathApplications( request: { readonly path: string }, signal: AbortSignal, ): Promise<readonly SessionWorkspacePathApplication[]>
|
|
874
|
+
|
|
752
875
|
/**
|
|
753
876
|
* Rename one Session after explicitly resuming it.
|
|
754
877
|
* @param request - Session identity and proposed title.
|
|
@@ -757,8 +880,10 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
|
|
757
880
|
@Remote('rename') rename(request: SessionRenameRequest): Promise<SessionRenameValue>
|
|
758
881
|
|
|
759
882
|
/**
|
|
760
|
-
* Fork one cold-readable
|
|
761
|
-
*
|
|
883
|
+
* Fork one cold-readable exact event prefix into a new Session. An omitted
|
|
884
|
+
* boundary selects the latest completed-turn prefix; an open cut receives
|
|
885
|
+
* synthetic fork closers.
|
|
886
|
+
* @param request - source Session and optional exact inclusive event boundary.
|
|
762
887
|
* @returns the new Session identity.
|
|
763
888
|
*/
|
|
764
889
|
@Remote('fork') fork(request: SessionForkRequest): Promise<SessionForkValue>
|
|
@@ -779,11 +904,11 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
|
|
779
904
|
@Remote('attachment') attachment(request: SessionAttachmentRequest): Promise<SessionAttachmentValue>
|
|
780
905
|
|
|
781
906
|
/**
|
|
782
|
-
* Mutate one still-pending queue occurrence
|
|
907
|
+
* Mutate one still-pending queue occurrence, resuming a cold Agent first.
|
|
783
908
|
* @param request - Session, queue item, and requested mutation.
|
|
784
909
|
* @returns acknowledgement that the queue mutation was applied.
|
|
785
910
|
*/
|
|
786
|
-
@Remote('updateQueue') updateQueue(request: SessionUpdateQueueRequest): SessionUpdateQueueValue
|
|
911
|
+
@Remote('updateQueue') updateQueue(request: SessionUpdateQueueRequest): Promise<SessionUpdateQueueValue>
|
|
787
912
|
|
|
788
913
|
/**
|
|
789
914
|
* Cancel one active Agent turn without dropping its pending inbox.
|
|
@@ -809,6 +934,14 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
|
|
809
934
|
*/
|
|
810
935
|
@Remote({ mode: 'stream' }) follow(request: SessionFollowRequest, signal: AbortSignal): AsyncIterable<SessionFollowFrame>
|
|
811
936
|
|
|
937
|
+
/**
|
|
938
|
+
* Read all registered projections without activating an Agent.
|
|
939
|
+
* @param request - Session whose current values are required.
|
|
940
|
+
* @param signal - cancellation for the Session observation.
|
|
941
|
+
* @returns complete baseline, or null when the Session does not exist.
|
|
942
|
+
*/
|
|
943
|
+
@Remote('projections') async projections(request: SessionProjectionsRequest, signal: AbortSignal): Promise<SessionProjectionsValue>
|
|
944
|
+
|
|
812
945
|
/**
|
|
813
946
|
* Stream a complete live-control baseline followed by replacement frames.
|
|
814
947
|
* @param signal - cancellation owned by the Remote stream carrier.
|
|
@@ -830,6 +963,15 @@ In-memory session store (`ctx.sessions`).
|
|
|
830
963
|
Persistence is intentionally not implemented here — the agent lifecycle attaches a session-log writer to each published session's write handle; a session published outside that lifecycle persists nothing.
|
|
831
964
|
|
|
832
965
|
```ts cordis-catalog
|
|
966
|
+
/**
|
|
967
|
+
* Register one event interpreter for live creation, restore, and fork.
|
|
968
|
+
* Disposing the contribution makes sessions that used it refuse further derivation.
|
|
969
|
+
* @param projection - pure definition owned by the event's plugin.
|
|
970
|
+
* @returns the fiber-owned disposer.
|
|
971
|
+
* @throws when another definition already owns this event type.
|
|
972
|
+
*/
|
|
973
|
+
registerMessageProjection(projection: SessionMessageProjection): () => Promise<void>
|
|
974
|
+
|
|
833
975
|
/**
|
|
834
976
|
* Create a session owned by the calling fiber: disposing that fiber stops
|
|
835
977
|
* event notification and removes the session from the store. `options.seed`
|
|
@@ -864,10 +1006,9 @@ create(id?: SessionId, options?: CreateSessionOptions): Session
|
|
|
864
1006
|
*
|
|
865
1007
|
* @param id - the session id; omitted, the store mints `session-<n>`.
|
|
866
1008
|
* @param options - seed events and/or creation metadata for the header. With
|
|
867
|
-
* `
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
* retain no mutable aliases.
|
|
1009
|
+
* `eventState`, every seed event is either independently owned or any
|
|
1010
|
+
* shared value is deeply frozen; {@link Session.fromRestore} validates and
|
|
1011
|
+
* adopts those values without copying or freezing them.
|
|
871
1012
|
* @returns the constructed session, NOT yet in the store.
|
|
872
1013
|
* @throws if a session with `id` already exists, metadata is not a plain
|
|
873
1014
|
* lossless-JSON record with valid scalar fields, or `meta.cwd` is a
|
|
@@ -914,8 +1055,8 @@ announce(session: Session): void
|
|
|
914
1055
|
* store owns the carrier, so callers (the checkpoint policy's per-request
|
|
915
1056
|
* barrier, goal-round-driver's idle checkpoint, teardown drains, and consumers
|
|
916
1057
|
* that flush themselves before reading storage) must come through here
|
|
917
|
-
* rather than dispatch a raw `ctx.parallel('session/flush', …)` — one owner
|
|
918
|
-
* one spelling
|
|
1058
|
+
* rather than dispatch a raw `ctx.parallel('session/flush', …)` — one owner
|
|
1059
|
+
* and one spelling.
|
|
919
1060
|
* @param session - the session whose buffered events must reach durable storage.
|
|
920
1061
|
* @returns whether at least one durability listener participated, after every
|
|
921
1062
|
* listener has settled successfully.
|
|
@@ -937,10 +1078,12 @@ get(id: SessionId): Session | undefined
|
|
|
937
1078
|
list(): Session[]
|
|
938
1079
|
|
|
939
1080
|
/**
|
|
940
|
-
* Create a live child session from
|
|
1081
|
+
* Create a live child session from an exact prefix of a live source.
|
|
941
1082
|
* `boundary` is an inclusive source event seq; omitted means the source's
|
|
942
|
-
* current last event.
|
|
943
|
-
*
|
|
1083
|
+
* current last event. An open tail receives synthetic tool results and
|
|
1084
|
+
* step/turn closers with the forked cause. Closed steps and turns remain
|
|
1085
|
+
* unchanged, including any failed tool calls already missing results.
|
|
1086
|
+
* `inheritedEventCount` counts only copied source events, excluding these closers.
|
|
944
1087
|
*
|
|
945
1088
|
* @param source - Live source session object or id.
|
|
946
1089
|
* @param boundary - Inclusive source event seq to fork through; omitted means
|
|
@@ -985,13 +1128,14 @@ Source: [`packages/api/session-controller/src/types.ts`](https://github.com/deep
|
|
|
985
1128
|
|
|
986
1129
|
#### `api-session/added` — emit
|
|
987
1130
|
|
|
988
|
-
A Session became visible
|
|
1131
|
+
A Session became visible or its Agent was created or disposed. Consumers upsert the summary and replace its current running and availability state.
|
|
989
1132
|
|
|
990
1133
|
```ts cordis-catalog
|
|
991
1134
|
/**
|
|
992
|
-
* A Session became visible
|
|
1135
|
+
* A Session became visible or its Agent was created or disposed.
|
|
1136
|
+
* Consumers upsert the summary and replace its current running and availability state.
|
|
993
1137
|
* @mode emit
|
|
994
|
-
* @param summary -
|
|
1138
|
+
* @param summary - current list row for the Session.
|
|
995
1139
|
*/
|
|
996
1140
|
'api-session/added'(summary: SessionSummary): void
|
|
997
1141
|
```
|
|
@@ -1076,7 +1220,6 @@ Creation announcement during session publication. A synchronous throw vetoes and
|
|
|
1076
1220
|
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners
|
|
1077
1221
|
* receive only sessions entered through that agent's context.
|
|
1078
1222
|
* @param session - the session just entered and announced.
|
|
1079
|
-
* @dshScopeScan unsupported
|
|
1080
1223
|
* @mode emit
|
|
1081
1224
|
*/
|
|
1082
1225
|
'session/created'(this: Scoped<Session>, session: Session): void
|
|
@@ -1099,7 +1242,6 @@ Emitted once when an announced session leaves the store, including publication r
|
|
|
1099
1242
|
* did not begin. Listener failures are logged and contained.
|
|
1100
1243
|
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`) reuses the owner scope.
|
|
1101
1244
|
* @param session - the session that is no longer live in the store.
|
|
1102
|
-
* @dshScopeScan unsupported
|
|
1103
1245
|
* @mode emit
|
|
1104
1246
|
*/
|
|
1105
1247
|
'session/disposed'(this: Scoped<Session>, session: Session): void
|
|
@@ -1124,7 +1266,6 @@ Post-commit, fire-and-forget append feed. The listener snapshot resolves before
|
|
|
1124
1266
|
* receive only events from sessions entered through that agent's context.
|
|
1125
1267
|
* @param session - the session whose log grew.
|
|
1126
1268
|
* @param event - the appended event, exactly as recorded.
|
|
1127
|
-
* @dshScopeScan unsupported
|
|
1128
1269
|
* @mode emit
|
|
1129
1270
|
*/
|
|
1130
1271
|
'session/event'(this: Scoped<Session>, session: Session, event: SessionEvent): void
|
|
@@ -1146,7 +1287,6 @@ Awaited parallel durability checkpoint: every listener runs and the caller await
|
|
|
1146
1287
|
* caller awaits all of them, with no waterfall veto. Scope-filtered dispatch
|
|
1147
1288
|
* (`@deepseek-ai/dsh-scope`) reuses the session's owner scope.
|
|
1148
1289
|
* @param session - the session whose buffered events must reach durable storage.
|
|
1149
|
-
* @dshScopeScan unsupported
|
|
1150
1290
|
* @mode parallel
|
|
1151
1291
|
*/
|
|
1152
1292
|
'session/flush'(this: Scoped<Session>, session: Session): Promise<void> | void
|