dsh-plugin-guide 0.3.1 → 0.3.3
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/README.es.md +1 -1
- package/README.hi.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/README.zh.md +1 -1
- package/SKILL.md +1 -1
- package/dist/dsh-plugin-dev.js +5 -5
- package/guide/links.md +1 -1
- package/guide/plugin-dev-guide.md +1 -1
- package/guide/quick-reference.es.md +2 -2
- package/guide/quick-reference.hi.md +1 -1
- package/guide/quick-reference.md +2 -2
- package/guide/quick-reference.pt.md +2 -2
- package/guide/quick-reference.zh-CN.md +2 -2
- package/package.json +3 -3
- package/references/cordis-paper-and-community.md +1 -1
- package/references/official-docs/AGENTS.md +28 -23
- package/references/official-docs/README.i18n.yaml +2 -2
- package/references/official-docs/README.md +1 -1
- package/references/official-docs/README.zh.md +19 -9
- package/references/official-docs/SNAPSHOT.md +5 -5
- package/references/official-docs/THIRD_PARTY_NOTICES.md +36 -13
- package/references/official-docs/docs/AGENTS.md +4 -4
- package/references/official-docs/docs/agent-lifecycle.i18n.yaml +2 -2
- package/references/official-docs/docs/agent-lifecycle.md +1 -1
- package/references/official-docs/docs/agent-lifecycle.zh.md +2 -2
- package/references/official-docs/docs/api-gateway.i18n.yaml +2 -2
- package/references/official-docs/docs/api-gateway.md +8 -8
- package/references/official-docs/docs/api-gateway.zh.md +8 -8
- package/references/official-docs/docs/architecture.i18n.yaml +2 -2
- package/references/official-docs/docs/architecture.md +25 -8
- package/references/official-docs/docs/architecture.zh.md +38 -21
- package/references/official-docs/docs/capability-seams.i18n.yaml +2 -2
- package/references/official-docs/docs/capability-seams.md +134 -67
- package/references/official-docs/docs/capability-seams.zh.md +134 -67
- package/references/official-docs/docs/config-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/config-catalog.md +731 -403
- package/references/official-docs/docs/config-catalog.zh.md +747 -419
- package/references/official-docs/docs/cookbook/adding-a-package.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/adding-a-package.md +3 -4
- package/references/official-docs/docs/cookbook/adding-a-package.zh.md +9 -8
- package/references/official-docs/docs/cookbook/{adding-a-conversation-node.i18n.yaml → adding-a-remote-api.i18n.yaml} +3 -3
- package/references/official-docs/docs/cookbook/adding-a-remote-api.md +197 -0
- package/references/official-docs/docs/cookbook/adding-a-remote-api.zh.md +197 -0
- package/references/official-docs/docs/cookbook/adding-a-settings-card.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/adding-a-settings-card.md +102 -0
- package/references/official-docs/docs/cookbook/adding-a-settings-card.zh.md +102 -0
- package/references/official-docs/docs/cookbook/adding-a-tool.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/adding-a-tool.md +11 -4
- package/references/official-docs/docs/cookbook/adding-a-tool.zh.md +16 -9
- package/references/official-docs/docs/cookbook/adding-a-vendored-package.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/adding-a-vendored-package.md +2 -2
- package/references/official-docs/docs/cookbook/adding-a-vendored-package.zh.md +4 -4
- package/references/official-docs/docs/cookbook/adding-an-llm-adapter.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/adding-an-llm-adapter.md +1 -1
- package/references/official-docs/docs/cookbook/adding-an-llm-adapter.zh.md +3 -3
- package/references/official-docs/docs/cookbook/extension-cookbook.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/extension-cookbook.md +9 -8
- package/references/official-docs/docs/cookbook/extension-cookbook.zh.md +17 -14
- package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.i18n.yaml +1 -1
- package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.zh.md +1 -1
- package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.i18n.yaml +1 -1
- package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +1 -1
- package/references/official-docs/docs/cordis-api/context.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-api/context.zh.md +1 -1
- package/references/official-docs/docs/cordis-api/events.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-api/events.zh.md +1 -1
- package/references/official-docs/docs/cordis-api/inherited.md +1 -1
- package/references/official-docs/docs/cordis-primer.i18n.yaml +2 -2
- package/references/official-docs/docs/cordis-primer.md +2 -1
- package/references/official-docs/docs/cordis-primer.zh.md +3 -2
- package/references/official-docs/docs/cordis-tutorial/01-first-plugin.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/01-first-plugin.zh.md +4 -4
- package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +4 -4
- package/references/official-docs/docs/cordis-tutorial/03-services.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/03-services.zh.md +4 -4
- package/references/official-docs/docs/cordis-tutorial/04-events.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/04-events.zh.md +4 -4
- package/references/official-docs/docs/cordis-tutorial/05-config.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/05-config.zh.md +2 -2
- package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.zh.md +3 -3
- package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.i18n.yaml +2 -2
- package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.md +5 -4
- package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.zh.md +11 -10
- package/references/official-docs/docs/cordis-tutorial/index.i18n.yaml +1 -1
- package/references/official-docs/docs/cordis-tutorial/index.zh.md +10 -10
- package/references/official-docs/docs/deepseek-llm-api-wire-extensions.i18n.yaml +6 -0
- package/references/official-docs/docs/deepseek-llm-api-wire-extensions.md +159 -0
- package/references/official-docs/docs/deepseek-llm-api-wire-extensions.zh.md +159 -0
- package/references/official-docs/docs/defensive-patterns.i18n.yaml +1 -1
- package/references/official-docs/docs/defensive-patterns.zh.md +3 -1
- package/references/official-docs/docs/development.i18n.yaml +2 -2
- package/references/official-docs/docs/development.md +9 -13
- package/references/official-docs/docs/development.zh.md +23 -21
- package/references/official-docs/docs/event-producer-consumer.i18n.yaml +2 -2
- package/references/official-docs/docs/event-producer-consumer.md +55 -46
- package/references/official-docs/docs/event-producer-consumer.zh.md +55 -46
- package/references/official-docs/docs/glossary.i18n.yaml +2 -2
- package/references/official-docs/docs/glossary.md +1 -1
- package/references/official-docs/docs/glossary.zh.md +1 -1
- package/references/official-docs/docs/graph-atlas.i18n.yaml +2 -2
- package/references/official-docs/docs/graph-atlas.md +0 -2
- package/references/official-docs/docs/graph-atlas.zh.md +7 -9
- package/references/official-docs/docs/i18n/README.i18n.yaml +2 -2
- package/references/official-docs/docs/i18n/README.md +7 -7
- package/references/official-docs/docs/i18n/README.zh.md +11 -9
- package/references/official-docs/docs/i18n/style-samples.md +3 -3
- package/references/official-docs/docs/i18n/translation-prompt.md +3 -3
- package/references/official-docs/docs/i18n/translation-rules.i18n.yaml +2 -2
- package/references/official-docs/docs/i18n/translation-rules.md +2 -2
- package/references/official-docs/docs/i18n/translation-rules.zh.md +3 -3
- package/references/official-docs/docs/module-graph.i18n.yaml +2 -2
- package/references/official-docs/docs/module-graph.md +660 -909
- package/references/official-docs/docs/module-graph.zh.md +662 -911
- package/references/official-docs/docs/persistence-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/persistence-catalog.md +185 -53
- package/references/official-docs/docs/persistence-catalog.zh.md +193 -61
- package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.i18n.yaml +2 -2
- package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.md +2 -2
- package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.zh.md +3 -3
- package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.i18n.yaml +2 -2
- package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
- package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
- package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.i18n.yaml +2 -2
- package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
- package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
- package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.i18n.yaml +2 -2
- package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
- package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +2 -2
- package/references/official-docs/docs/postmortem/README.i18n.yaml +1 -1
- package/references/official-docs/docs/postmortem/README.zh.md +5 -5
- package/references/official-docs/docs/rescope.i18n.yaml +2 -2
- package/references/official-docs/docs/rescope.md +2 -2
- package/references/official-docs/docs/rescope.zh.md +3 -3
- package/references/official-docs/docs/subsystems/README.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/README.md +8 -2
- package/references/official-docs/docs/subsystems/README.zh.md +53 -47
- package/references/official-docs/docs/subsystems/agent-team.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/agent-team.md +207 -0
- package/references/official-docs/docs/subsystems/agent-team.zh.md +207 -0
- package/references/official-docs/docs/subsystems/approval.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/approval.md +12 -12
- package/references/official-docs/docs/subsystems/approval.zh.md +13 -13
- package/references/official-docs/docs/subsystems/attachment.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/attachment.md +90 -7
- package/references/official-docs/docs/subsystems/attachment.zh.md +90 -7
- package/references/official-docs/docs/subsystems/client-modules.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/client-modules.md +69 -19
- package/references/official-docs/docs/subsystems/client-modules.zh.md +69 -19
- package/references/official-docs/docs/subsystems/code-runtime.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/code-runtime.md +12 -8
- package/references/official-docs/docs/subsystems/code-runtime.zh.md +13 -9
- package/references/official-docs/docs/subsystems/commands.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/commands.md +30 -7
- package/references/official-docs/docs/subsystems/commands.zh.md +31 -8
- package/references/official-docs/docs/subsystems/compaction.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/compaction.md +14 -14
- package/references/official-docs/docs/subsystems/compaction.zh.md +19 -19
- package/references/official-docs/docs/subsystems/conversation.i18n.yaml +6 -0
- package/references/official-docs/docs/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +49 -24
- package/references/official-docs/docs/{cookbook/adding-a-conversation-node.zh.md → subsystems/conversation.zh.md} +49 -24
- package/references/official-docs/docs/subsystems/core.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/core.md +114 -36
- package/references/official-docs/docs/subsystems/core.zh.md +145 -65
- package/references/official-docs/docs/subsystems/credentials.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/credentials.md +207 -11
- package/references/official-docs/docs/subsystems/credentials.zh.md +207 -11
- package/references/official-docs/docs/subsystems/extensions.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/extensions.md +27 -9
- package/references/official-docs/docs/subsystems/extensions.zh.md +30 -12
- package/references/official-docs/docs/subsystems/feedback.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/feedback.md +6 -6
- package/references/official-docs/docs/subsystems/feedback.zh.md +6 -6
- package/references/official-docs/docs/subsystems/filesystem.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/filesystem.md +17 -7
- package/references/official-docs/docs/subsystems/filesystem.zh.md +19 -9
- package/references/official-docs/docs/subsystems/goal.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/goal.md +4 -4
- package/references/official-docs/docs/subsystems/goal.zh.md +8 -8
- package/references/official-docs/docs/subsystems/invariants.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/invariants.md +2 -2
- package/references/official-docs/docs/subsystems/invariants.zh.md +5 -5
- package/references/official-docs/docs/subsystems/jobs.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/jobs.md +3 -3
- package/references/official-docs/docs/subsystems/jobs.zh.md +6 -6
- package/references/official-docs/docs/subsystems/llm-streaming.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/llm-streaming.md +193 -22
- package/references/official-docs/docs/subsystems/llm-streaming.zh.md +199 -28
- package/references/official-docs/docs/subsystems/lsp.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/lsp.md +2 -2
- package/references/official-docs/docs/subsystems/lsp.zh.md +3 -3
- package/references/official-docs/docs/subsystems/permission-presets.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/permission-presets.md +8 -8
- package/references/official-docs/docs/subsystems/permission-presets.zh.md +8 -8
- package/references/official-docs/docs/subsystems/persistence.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/persistence.md +183 -173
- package/references/official-docs/docs/subsystems/persistence.zh.md +182 -172
- package/references/official-docs/docs/subsystems/plan.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/plan.md +4 -4
- package/references/official-docs/docs/subsystems/plan.zh.md +10 -10
- package/references/official-docs/docs/subsystems/sandbox.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/sandbox.md +5 -3
- package/references/official-docs/docs/subsystems/sandbox.zh.md +8 -6
- package/references/official-docs/docs/subsystems/schedule.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/schedule.md +9 -3
- package/references/official-docs/docs/subsystems/schedule.zh.md +11 -5
- package/references/official-docs/docs/subsystems/scope.i18n.yaml +1 -1
- package/references/official-docs/docs/subsystems/scope.zh.md +1 -1
- package/references/official-docs/docs/subsystems/session-projection.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-projection.md +148 -75
- package/references/official-docs/docs/subsystems/session-projection.zh.md +148 -75
- package/references/official-docs/docs/subsystems/session-query.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-query.md +30 -16
- package/references/official-docs/docs/subsystems/session-query.zh.md +31 -17
- package/references/official-docs/docs/subsystems/session-reference.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-reference.md +94 -7
- package/references/official-docs/docs/subsystems/session-reference.zh.md +95 -8
- package/references/official-docs/docs/subsystems/session-telemetry.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-telemetry.md +5 -6
- package/references/official-docs/docs/subsystems/session-telemetry.zh.md +9 -10
- package/references/official-docs/docs/subsystems/session-title.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-title.md +8 -8
- package/references/official-docs/docs/subsystems/session-title.zh.md +10 -10
- package/references/official-docs/docs/subsystems/session.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session.md +376 -71
- package/references/official-docs/docs/subsystems/session.zh.md +392 -85
- package/references/official-docs/docs/subsystems/settings.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/settings.md +105 -10
- package/references/official-docs/docs/subsystems/settings.zh.md +105 -10
- package/references/official-docs/docs/subsystems/shell.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/shell.md +3 -3
- package/references/official-docs/docs/subsystems/shell.zh.md +11 -11
- package/references/official-docs/docs/subsystems/skills.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/skills.md +26 -3
- package/references/official-docs/docs/subsystems/skills.zh.md +29 -6
- package/references/official-docs/docs/subsystems/slots.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/slots.md +175 -0
- package/references/official-docs/docs/subsystems/slots.zh.md +175 -0
- package/references/official-docs/docs/subsystems/spill.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/spill.md +4 -4
- package/references/official-docs/docs/subsystems/spill.zh.md +6 -6
- package/references/official-docs/docs/subsystems/storage.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/storage.md +38 -7
- package/references/official-docs/docs/subsystems/storage.zh.md +41 -10
- package/references/official-docs/docs/subsystems/subagent.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/subagent.md +148 -116
- package/references/official-docs/docs/subsystems/subagent.zh.md +158 -124
- package/references/official-docs/docs/subsystems/subprocess.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/subprocess.md +3 -3
- package/references/official-docs/docs/subsystems/subprocess.zh.md +5 -5
- package/references/official-docs/docs/subsystems/system-prompt.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/system-prompt.md +21 -8
- package/references/official-docs/docs/subsystems/system-prompt.zh.md +23 -10
- package/references/official-docs/docs/subsystems/terminal.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/terminal.md +2 -2
- package/references/official-docs/docs/subsystems/terminal.zh.md +4 -4
- package/references/official-docs/docs/subsystems/todo.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/todo.md +32 -0
- package/references/official-docs/docs/subsystems/todo.zh.md +32 -0
- package/references/official-docs/docs/subsystems/token-meter.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/token-meter.md +29 -14
- package/references/official-docs/docs/subsystems/token-meter.zh.md +30 -15
- package/references/official-docs/docs/subsystems/tools.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/tools.md +46 -46
- package/references/official-docs/docs/subsystems/tools.zh.md +54 -54
- package/references/official-docs/docs/subsystems/typert.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/typert.md +65 -58
- package/references/official-docs/docs/subsystems/typert.zh.md +67 -60
- package/references/official-docs/docs/subsystems/user-questions.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/user-questions.md +35 -35
- package/references/official-docs/docs/subsystems/user-questions.zh.md +35 -35
- package/references/official-docs/docs/subsystems/web-client.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/web-client.md +95 -0
- package/references/official-docs/docs/subsystems/web-client.zh.md +95 -0
- package/references/official-docs/docs/subsystems/web-server.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/web-server.md +55 -9
- package/references/official-docs/docs/subsystems/web-server.zh.md +56 -10
- package/references/official-docs/docs/subsystems/web.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/web.md +14 -7
- package/references/official-docs/docs/subsystems/web.zh.md +16 -9
- package/references/official-docs/docs/subsystems/webhook.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/webhook.md +70 -0
- package/references/official-docs/docs/subsystems/webhook.zh.md +70 -0
- package/references/official-docs/docs/subsystems/workflow.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/workflow.md +8 -8
- package/references/official-docs/docs/subsystems/workflow.zh.md +13 -13
- package/references/official-docs/docs/subsystems/workspace.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/workspace.md +98 -5
- package/references/official-docs/docs/subsystems/workspace.zh.md +102 -9
- package/references/official-docs/docs/testing.i18n.yaml +2 -2
- package/references/official-docs/docs/testing.md +15 -10
- package/references/official-docs/docs/testing.zh.md +15 -10
- package/references/official-docs/docs/tool-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/tool-catalog.md +413 -61
- package/references/official-docs/docs/tool-catalog.zh.md +418 -63
- package/references/official-docs/docs/tool-execution-pipeline.i18n.yaml +2 -2
- package/references/official-docs/docs/tool-execution-pipeline.md +1 -1
- package/references/official-docs/docs/tool-execution-pipeline.zh.md +1 -1
- package/references/official-docs/docs/user/develop/basic/config.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/basic/config.md +1 -1
- package/references/official-docs/docs/user/develop/basic/config.zh.md +4 -4
- package/references/official-docs/docs/user/develop/basic/index.i18n.yaml +1 -1
- package/references/official-docs/docs/user/develop/basic/index.zh.md +5 -5
- package/references/official-docs/docs/user/develop/basic/publish.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/basic/publish.md +3 -3
- package/references/official-docs/docs/user/develop/basic/publish.zh.md +7 -7
- package/references/official-docs/docs/user/develop/basic/tool.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/basic/tool.md +3 -3
- package/references/official-docs/docs/user/develop/basic/tool.zh.md +4 -4
- package/references/official-docs/docs/user/develop/framework/events.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/framework/events.md +2 -2
- package/references/official-docs/docs/user/develop/framework/events.zh.md +3 -3
- package/references/official-docs/docs/user/develop/framework/index.i18n.yaml +1 -1
- package/references/official-docs/docs/user/develop/framework/index.zh.md +3 -3
- package/references/official-docs/docs/user/develop/framework/service.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/framework/service.md +1 -1
- package/references/official-docs/docs/user/develop/framework/service.zh.md +3 -3
- package/references/official-docs/docs/user/develop/practice/dynamic-cordis.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/practice/dynamic-cordis.md +15 -0
- package/references/official-docs/docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
- package/references/official-docs/docs/user/develop/practice/index.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/practice/index.md +1 -1
- package/references/official-docs/docs/user/develop/practice/index.zh.md +3 -3
- package/references/official-docs/docs/user/develop/practice/llm-adapter.i18n.yaml +2 -2
- package/references/official-docs/docs/user/develop/practice/llm-adapter.md +4 -3
- package/references/official-docs/docs/user/develop/practice/llm-adapter.zh.md +4 -3
- package/references/official-docs/docs/user/guide/github-review.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/github-review.md +102 -0
- package/references/official-docs/docs/user/guide/github-review.zh.md +102 -0
- package/references/official-docs/docs/user/guide/index.i18n.yaml +2 -2
- package/references/official-docs/docs/user/guide/index.md +2 -2
- package/references/official-docs/docs/user/guide/index.zh.md +8 -8
- package/references/official-docs/docs/user/guide/mcp-memory.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/mcp-memory.md +101 -0
- package/references/official-docs/docs/user/guide/mcp-memory.zh.md +101 -0
- package/references/official-docs/docs/user/guide/providers.i18n.yaml +2 -2
- package/references/official-docs/docs/user/guide/providers.md +40 -1
- package/references/official-docs/docs/user/guide/providers.zh.md +41 -2
- package/references/official-docs/docs/user/guide/python-sdk.i18n.yaml +2 -2
- package/references/official-docs/docs/user/guide/python-sdk.md +80 -34
- package/references/official-docs/docs/user/guide/python-sdk.zh.md +87 -41
- package/references/official-docs/docs/user/guide/schedule.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/schedule.md +21 -0
- package/references/official-docs/docs/user/guide/schedule.zh.md +21 -0
- package/references/official-docs/docs/web-styling.i18n.yaml +2 -2
- package/references/official-docs/docs/web-styling.md +3 -0
- package/references/official-docs/docs/web-styling.zh.md +5 -2
- package/references/official-docs/packages/AGENTS.md +4 -3
- package/references/official-docs/packages/README.md +104 -59
- package/references/official-docs/vendor/README.md +1 -0
- package/references/official-docs/website-docs.ts +52 -11
- package/references/sources.md +2 -2
- package/references/website-pages.md +3 -3
- package/scripts/download-sources.ps1 +1 -1
- package/scripts/sync-official-docs.ps1 +19 -11
- package/scripts/verify-kit.ps1 +0 -4
- package/templates/js/README.es.md +1 -1
- package/templates/js/README.hi.md +1 -1
- package/templates/js/README.md +1 -1
- package/templates/js/README.pt.md +1 -1
- package/templates/js/README.zh.md +1 -1
- package/templates/js/package.json +4 -4
- package/templates/ts/README.es.md +1 -1
- package/templates/ts/README.hi.md +1 -1
- package/templates/ts/README.md +1 -1
- package/templates/ts/README.pt.md +1 -1
- package/templates/ts/README.zh.md +1 -1
- package/templates/ts/package.json +4 -4
- package/references/official-docs/examples/AGENTS.md +0 -20
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](user-questions.md) | 中文
|
|
4
4
|
|
|
5
|
-
[dsh-user-questions](../../packages/interaction/user-questions) 的用户交互 seam。它是工具或权限插件需要人类回答后 agent(智能体)才能继续时所使用的、提供方无关的词汇。UI
|
|
5
|
+
[dsh-user-questions](../../packages/interaction/user-questions) 的用户交互 seam。它是工具或权限插件需要人类回答后 agent(智能体)才能继续时所使用的、提供方无关的词汇。Agent-scoped waterfall listener 组合可用的 UI 界面,其中包括转发到已连接 client 的 listener。
|
|
6
6
|
|
|
7
7
|
源码:[`packages/interaction/user-questions/src/index.ts`](../../packages/interaction/user-questions/src/index.ts)
|
|
8
8
|
|
|
@@ -74,14 +74,7 @@ interface AskUserQuestionItem {
|
|
|
74
74
|
|
|
75
75
|
```ts type-equiv
|
|
76
76
|
/** Request for a human answer. */
|
|
77
|
-
interface AskUserQuestionRequest {
|
|
78
|
-
/** Questions to display. */
|
|
79
|
-
questions: AskUserQuestionItem[]
|
|
80
|
-
/** Exact live calling agent, when the request came from an agent tool call. */
|
|
81
|
-
agent?: Agent
|
|
82
|
-
/** Abort signal for the owning tool/step. */
|
|
83
|
-
signal?: AbortSignal
|
|
84
|
-
}
|
|
77
|
+
interface AskUserQuestionRequest extends AskUserQuestionRequestEvent {}
|
|
85
78
|
```
|
|
86
79
|
|
|
87
80
|
## 回答
|
|
@@ -108,17 +101,6 @@ interface AskUserQuestionAnswer {
|
|
|
108
101
|
}
|
|
109
102
|
```
|
|
110
103
|
|
|
111
|
-
## 提供方
|
|
112
|
-
|
|
113
|
-
同一上下文中只能有一个活跃的提供方。提供方注册绑定到 effect,因此 HMR(热模块替换)或 dispose(资源释放)会移除当前活跃的 UI。
|
|
114
|
-
|
|
115
|
-
```ts type-equiv
|
|
116
|
-
/** UI-side provider for user questions. */
|
|
117
|
-
interface UserQuestionProvider {
|
|
118
|
-
ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
104
|
## 错误
|
|
123
105
|
|
|
124
106
|
`UserQuestionError` 继承 `HarnessError`,因此 `ctx.tools.execute()` 会保留 `{ name, code }`,用于面向模型的工具失败,如 `EMPTY_QUESTIONS`、`NO_PROVIDER`、`ASK_ABORTED` 或 UI 侧取消。
|
|
@@ -139,25 +121,17 @@ class UserQuestionError extends HarnessError {
|
|
|
139
121
|
|
|
140
122
|
## Cordis API
|
|
141
123
|
|
|
142
|
-
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`) —
|
|
124
|
+
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.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
|
143
125
|
|
|
144
126
|
<a id="ctxuserquestions--userquestionservice"></a>
|
|
145
127
|
|
|
146
128
|
### `ctx.userQuestions` — `UserQuestionService`
|
|
147
129
|
|
|
148
|
-
`ctx.userQuestions`:
|
|
130
|
+
`ctx.userQuestions`: validation plus the scoped answerer waterfall.
|
|
149
131
|
|
|
150
132
|
```ts cordis-catalog
|
|
151
133
|
/**
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* @param provider UI-side implementation that collects answers.
|
|
155
|
-
* @returns Disposer that unregisters this provider.
|
|
156
|
-
*/
|
|
157
|
-
registerProvider(provider: UserQuestionProvider): () => void
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Ask the active UI provider and wait for the user's answer.
|
|
134
|
+
* Ask the scoped answerer waterfall and wait for the user's answer.
|
|
161
135
|
*
|
|
162
136
|
* When a caller supplies an agent, human interaction is valid only for the
|
|
163
137
|
* exact live runtime root. Runtime ownership, not durable session lineage,
|
|
@@ -167,12 +141,38 @@ registerProvider(provider: UserQuestionProvider): () => void
|
|
|
167
141
|
*
|
|
168
142
|
* @param request Questions, owner agent, and abort signal.
|
|
169
143
|
* @returns The answer chosen or typed by the human.
|
|
170
|
-
* @throws {UserQuestionError} code `
|
|
171
|
-
*
|
|
172
|
-
*
|
|
144
|
+
* @throws {UserQuestionError} code `ASK_ABORTED` when the supplied signal
|
|
145
|
+
* is already or becomes aborted, `CALLER_NOT_LIVE` when a supplied agent
|
|
146
|
+
* is not the registry's exact live instance, or `DELEGATED_CALLER` when
|
|
147
|
+
* that live agent is owned by another agent.
|
|
173
148
|
*/
|
|
174
149
|
async ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>
|
|
175
150
|
```
|
|
176
151
|
|
|
177
|
-
Source: [`packages/interaction/user-questions/src/index.ts
|
|
152
|
+
Source: [`packages/interaction/user-questions/src/index.ts`](../../packages/interaction/user-questions/src/index.ts)
|
|
153
|
+
|
|
154
|
+
<a id="user-questions-events"></a>
|
|
155
|
+
|
|
156
|
+
### `user-questions/*` events
|
|
157
|
+
|
|
158
|
+
<a id="user-questionsrequest--waterfall"></a>
|
|
159
|
+
|
|
160
|
+
#### `user-questions/request` — waterfall
|
|
161
|
+
|
|
162
|
+
Ask composed answerers for structured user input. Return an answer to claim the request or call `next()` to delegate. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
|
163
|
+
|
|
164
|
+
```ts cordis-catalog
|
|
165
|
+
/**
|
|
166
|
+
* Ask composed answerers for structured user input. Return an answer to
|
|
167
|
+
* claim the request or call `next()` to delegate. Scope-filtered dispatch
|
|
168
|
+
* (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
|
169
|
+
* @param request - pending user-question request.
|
|
170
|
+
* @mode waterfall
|
|
171
|
+
*/
|
|
172
|
+
'user-questions/request'( this: Scoped<Agent>, request: AskUserQuestionRequestEvent, next: () => Promise<AskUserQuestionAnswer>, ): Promise<AskUserQuestionAnswer>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Types: [Agent](core.zh.md) · [Scoped](scope.zh.md)
|
|
176
|
+
|
|
177
|
+
Source: [`packages/interaction/user-questions/src/types.ts`](../../packages/interaction/user-questions/src/types.ts)
|
|
178
178
|
<!-- END GENERATED cordis-surface -->
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write docs/subsystems/web-client.md
|
|
5
|
+
web-client.md: 166ad50df661e37318c5ed2f271569c292cce39a
|
|
6
|
+
web-client.zh.md: cdf91958e23c0ea5c99562e6ca347947fbeff292
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Web Client architecture
|
|
2
|
+
|
|
3
|
+
English | [中文](web-client.zh.md)
|
|
4
|
+
|
|
5
|
+
The Web Client is a browser-side Cordis application assembled from independently loaded plugins. Its architecture has four reusable foundations: [Client Modules](client-modules.md) loads the plugin graph, the [API Gateway](../api-gateway.md) provides typed Host communication, [Slots](slots.md) composes React UI, and [Conversation](conversation.md) turns a Session history window into target-owned views. This page connects those systems and defines where Client models and feature packages belong.
|
|
6
|
+
|
|
7
|
+
## Layers and ownership
|
|
8
|
+
|
|
9
|
+
| Layer | Main owners | Responsibility |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Host application | business services and `packages/api/*-controller` Host entries | Own authoritative state, persistence, mutation ordering, access policy, and stream production. |
|
|
12
|
+
| Transport and API assembly | `client/connection`, `api/gateway`, `api/remotes` | Establish a Client generation, expose generated `ctx.remote` methods and streams, forward selected Cordis events, and carry cancellation and results. |
|
|
13
|
+
| Client models | `api/session-controller/client`, `api/workspace-controller/client` | Maintain React-free mirrors of Host state, resolve stream/unary races, own object identities and subscriptions, and expose narrow command services. |
|
|
14
|
+
| UI adapters | `client/ui-session`, `client/ui-workspace` | Convert model observables into root or Session-scoped standard Slot sources without taking ownership of business state. |
|
|
15
|
+
| Conversation data | `client/ui-conversation`, target packages such as `ui-chat` and `ui-trajectory` | Assemble standard events and compact historical Assistant runs into independent target snapshots and own the shared conversation shell and input flow. |
|
|
16
|
+
| Composition and rendering | `client/ui-slots`, `client/ui-renderer`, `client/ui-layout`, feature UI packages | Declare extension locations, derive component props, bind observables to React hooks, and mount the final tree. |
|
|
17
|
+
|
|
18
|
+
The dependency direction is Host state → Remote transport → Client model → UI adapter → Conversation or presentation → Slots → React. User actions travel back through callbacks that close over an injected Client service or generated Remote namespace. A presentation component never receives Cordis `ctx`, a transport object, or another feature plugin's implementation.
|
|
19
|
+
|
|
20
|
+
## Browser boot
|
|
21
|
+
|
|
22
|
+
The Host writes the composed `WebBootGraph` to `window.__DSH_BOOT__` and installs the browser module-loader facade before parser-preloaded scripts execute. The module system is a lazy CommonJS table: loading a bundle registers its factory, while materializing an entry runs the factory with synchronous `require` over platform modules and declared dynamic dependencies.
|
|
23
|
+
|
|
24
|
+
The Web boot kernel creates the module system, prefetches `immediately` entries, mounts the vendored Cordis Loader, and creates every graph entry. Cordis service injection determines activation; module graph order determines only whether synchronous imports can be materialized. After the complete roster reaches a settled state, `ui-renderer` hydrates the framework-free boot DOM and calls the sole context-level `renderSlot('root')` operation. [Client Modules](client-modules.md) owns the graph, bundle route, cache revision, and loader details.
|
|
25
|
+
|
|
26
|
+
## Remote communication
|
|
27
|
+
|
|
28
|
+
Host business services annotate callable methods with Typert Remote decorators. Host generation emits strict descriptors, runtime codecs, declaration merges, and source maps. The Client-side `api-remotes` assembly selects those generated contributions and mounts concrete methods under `ctx.remote.<namespace>` and Session-scoped `agentCtx.remote.<namespace>`. Feature packages depend on the generated service face, not the Gateway implementation or a Host package's runtime entry.
|
|
29
|
+
|
|
30
|
+
The Connection owns request correlation, the `/api` carrier, trust checks, exact Fetch routes, and connection generations. API Gateway owns Remote dispatch, cancellation, logical streams, and selected Host event forwarding. Controller operations belong on generated Remote methods or explicit Remote streams; feature-owned downloads register exact Fetch routes. The [API Gateway reference](../api-gateway.md) defines generation and invocation, while the [Connection README](../../packages/client/connection/README.md) defines the physical carrier and trust policy.
|
|
31
|
+
|
|
32
|
+
The internal `$events` logical stream is the Connection generation source. Its opening `ready` frame carries the Host home used for path display and establishes the generation after Host listeners are attached, before any controller begins a baseline read. `ctx.remote.$on()` delivers allowlisted ordinary events to the root Client Context and scoped waterfall events to the resolved Session Context; a waterfall listener returns a result, calls `next()`, or rejects.
|
|
33
|
+
|
|
34
|
+
## Client models
|
|
35
|
+
|
|
36
|
+
Each API controller package owns a paired Host and Client face. The Host side owns authoritative mutation and stream production. The Client side owns an identity-stable, React-free model over the same generated wire types and exposes observable snapshots plus commands. UI packages consume these Client services and do not reproduce transport state in component stores.
|
|
37
|
+
|
|
38
|
+
### Sessions
|
|
39
|
+
|
|
40
|
+
[`api/session-controller`](../../packages/api/session-controller/README.md) exposes Host commands for list, search, creation, selection data, prompt, queue, cancellation, pagination, and follow/control streams. Its Client side is organized as `ClientSessions → SessionManager → Session`:
|
|
41
|
+
|
|
42
|
+
- `ClientSessions` provides `ctx.sessions`, owns Session scopes and stable `SessionBinding` objects, and projects the selected list state.
|
|
43
|
+
- `SessionManager` owns the list baseline, live list/control updates, lazy Session instances, queues, projection stores, subagent catalogs, and conflict ordering between pulls and later updates.
|
|
44
|
+
- Each `Session` owns one contiguous logical-event window represented by `SessionEventLikeEntry` values, paging, follow, prompt/control state, and the observable snapshot consumed by adapters.
|
|
45
|
+
|
|
46
|
+
The durable event path opens `follow()`, whose first frame contains the current header, tail page, cursor, and complete projection baseline. History records have an explicit `event` or `chunks` discriminator and an aligned inner `event`; the journal validates each inclusive logical sequence range before the Client retains the records as `SessionEventLikeEntry` values without per-record conversion. Each physical generation atomically replaces the retained window from that snapshot; standard live events then append by sequence. `page()` is reserved for older history and gap repair. The transient control stream starts every generation with a complete baseline and then applies queue, job, and projection updates.
|
|
47
|
+
|
|
48
|
+
### Workspaces
|
|
49
|
+
|
|
50
|
+
[`api/workspace-controller`](../../packages/api/workspace-controller/README.md) keeps Workspace mutation policy and the authoritative follow feed on the Host. `ClientWorkspaceModel` owns the browser rows, order, archived Session ids, command echoes, and stream/unary race resolution. Every stream generation starts with a complete baseline followed by `upsert`, `remove`, `order`, and `archived` increments; reconnect replaces the model from the new baseline. `WorkspaceController` exposes that model as `ctx.workspaces`, while `ui-workspace` contributes `useWorkspaces` and navigation callbacks to the UI.
|
|
51
|
+
|
|
52
|
+
This pairing is not a second source of business truth. Host controllers decide durable state and mutation outcomes; Client models maintain the latest usable local projection, preserve object identity where useful to rendering, and encode how delayed responses and replacement baselines merge.
|
|
53
|
+
|
|
54
|
+
## Conversation and presentation
|
|
55
|
+
|
|
56
|
+
`ui-session` installs the `session` scope adapter and publishes `useSessions`, `useSession`, `sessionId`, and `useProjection`. Domain adapters add further standard sources without putting React hooks on the model objects.
|
|
57
|
+
|
|
58
|
+
`ui-conversation` binds once to each `SessionBinding.eventSource`. Its event registry correlates standard events and Client-only `chunkrow/*` history events into stable business Contexts, and its view registry materializes target snapshots. Packed runs stay single inputs and Matches through replay; Chat Assistant, Trajectory Assistant, and Turn Tail are the built-in Definitions that interpret them. `ui-chat` and `ui-trajectory` register separate Definitions and builders: they may interpret the same event family, but they do not import or share each other's final display model. The shell selects a registered view and passes its snapshot through standard hooks and Slots. [Conversation](conversation.md) defines Context identity, replay, Location data, target builders, and keyed renderers.
|
|
59
|
+
|
|
60
|
+
`ui-slots` provides the typed registry and lifecycle ledger; `ui-renderer` is the only package that binds bare observables through `useSyncExternalStore`, owns React contexts, and renders the root tree. Feature components receive framework hooks, owner props, store actions, and explicit injection through their derived props. [Web Client Slots](slots.md) lists those inputs, extension APIs, and the current Slot hierarchy.
|
|
61
|
+
|
|
62
|
+
## Data paths
|
|
63
|
+
|
|
64
|
+
| Path | Sequence |
|
|
65
|
+
|---|---|
|
|
66
|
+
| durable Session display | Host Session log → packed Remote `follow`/`page` history → Client `SessionEventLikeEntry` window → Conversation Contexts → target snapshot (`chat`, `trajectory`, or another registered target) → Slot view → React |
|
|
67
|
+
| transient Session control | Host control baseline → Remote snapshot stream → `SessionManager` queue/job/projection stores → Session and list snapshots → standard hooks → components |
|
|
68
|
+
| Workspace state | Host Workspace baseline and increments → `ClientWorkspaceModel` → `ctx.workspaces.list` → `useWorkspaces` → sidebar, hero, and navigation entries |
|
|
69
|
+
| scoped interaction | Host Cordis waterfall → API Remotes `$events` → `ctx.remote.$on()` on the Session Context → owning UI package → result or `next()` |
|
|
70
|
+
| user command | component callback → registration inject face or Slot owner → `ctx.sessions`, `ctx.workspaces`, or generated scoped Remote → Host Controller → authoritative update → stream or event projection back to the Client |
|
|
71
|
+
|
|
72
|
+
## Reconnection
|
|
73
|
+
|
|
74
|
+
Physical and logical recovery are separate. Gateway mux restores the physical WebSocket; each `RemoteStream` reopens its own logical source when the Connection publishes a usable generation. A carrier failure is retryable, while a business error, malformed opening item, or protocol violation is terminal for the owning logical stream.
|
|
75
|
+
|
|
76
|
+
Recovery follows the data's semantics:
|
|
77
|
+
|
|
78
|
+
- A durable Session journal validates logical sequence ranges and replaces its window from every generation's opening snapshot; `page()` supplies older history and repairs any later range gap.
|
|
79
|
+
- Session control and Workspace streams retain the last published value while disconnected, then atomically replace it from a fresh opening baseline.
|
|
80
|
+
- Ordinary forwarded notifications are not replayed. Stateful domains need a baseline, cursor, or explicit query; scoped waterfalls retain their own request lifetime.
|
|
81
|
+
|
|
82
|
+
There is no monolithic Client `Runtime`, `HostFrame`, `events.mux`, `events.host`, or universal `resync()` API. The Connection exposes generation state, Gateway owns logical stream supervision, and each Client model defines replacement or resume semantics appropriate to its data.
|
|
83
|
+
|
|
84
|
+
## Package boundaries
|
|
85
|
+
|
|
86
|
+
Feature plugin packages may share declarations through `import type`; they do not runtime-import or re-export another feature plugin's values. Cross-package behavior uses injected Cordis services, and cross-package UI uses Slots. Target-specific Conversation Definitions, projection helpers, and final view data stay with their target package even when Chat and Trajectory intentionally implement parallel logic.
|
|
87
|
+
|
|
88
|
+
Shared runtime values need a narrow static owner with no feature lifecycle, such as `client/store`, `ui-primitives`, or a browser-safe utility package. Transport and generated API assembly may import runtime contributions because assembling one protocol is their explicit responsibility. A feature package does not add `dsh.client.external` merely to bypass this rule.
|
|
89
|
+
|
|
90
|
+
Use the four detailed references according to the extension being added:
|
|
91
|
+
|
|
92
|
+
- [Client Modules](client-modules.md) for package discovery, loading, shared module identities, and boot order.
|
|
93
|
+
- [API Gateway](../api-gateway.md) for Host methods, generated Remote contributions, streams, and forwarded events.
|
|
94
|
+
- [Web Client Slots](slots.md) for components, hooks, stores, injection, and placement.
|
|
95
|
+
- [Conversation](conversation.md) for durable event correlation, target snapshots, and Chat or Trajectory view contributions.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Web Client 架构
|
|
2
|
+
|
|
3
|
+
[English](web-client.md) | 中文
|
|
4
|
+
|
|
5
|
+
Web Client 是由独立加载插件组装而成的浏览器侧 Cordis 应用。它有四个可复用底座:[Client Modules](client-modules.zh.md) 加载插件图,[API Gateway](../api-gateway.zh.md) 提供类型化 Host 通信,[Slots](slots.zh.md) 组合 React UI,[Conversation](conversation.zh.md) 把 Session 历史窗口变成各 target 自有的视图。本文串联这些系统,并规定 Client model 与功能包各自所在的位置。
|
|
6
|
+
|
|
7
|
+
## 分层与所有权
|
|
8
|
+
|
|
9
|
+
| 层 | 主要 owner | 职责 |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Host 应用 | 业务 service 与 `packages/api/*-controller` Host entry | 拥有权威状态、持久化、mutation 顺序、访问策略与 stream 生产。 |
|
|
12
|
+
| 传输与 API assembly | `client/connection`、`api/gateway`、`api/remotes` | 建立 Client generation,公开生成的 `ctx.remote` method 与 stream,转发选定的 Cordis event,并承载取消和结果。 |
|
|
13
|
+
| Client model | `api/session-controller/client`、`api/workspace-controller/client` | 维护不依赖 React 的 Host 状态镜像,处理 stream/unary 竞态,拥有对象 identity 与订阅,并公开收窄的 command service。 |
|
|
14
|
+
| UI adapter | `client/ui-session`、`client/ui-workspace` | 把 model observable 转换为 root 或 Session scope 的标准 Slot source,不接管业务状态所有权。 |
|
|
15
|
+
| Conversation 数据 | `client/ui-conversation`、`ui-chat` 与 `ui-trajectory` 等 target package | 把标准 event 与紧凑的 Assistant 历史批次组装成相互独立的 target snapshot,并拥有共享的 Conversation shell 与输入流程。 |
|
|
16
|
+
| 组合与渲染 | `client/ui-slots`、`client/ui-renderer`、`client/ui-layout`、各 UI 功能包 | 声明扩展位置、推导组件 props、把 observable 绑定成 React hook,并挂载最终组件树。 |
|
|
17
|
+
|
|
18
|
+
依赖方向是 Host 状态 → Remote 传输 → Client model → UI adapter → Conversation 或 presentation → Slots → React。用户操作通过 callback 反向进入注入的 Client service 或生成的 Remote namespace。Presentation component 绝不接收 Cordis `ctx`、transport object 或其他功能插件的实现。
|
|
19
|
+
|
|
20
|
+
## 浏览器启动
|
|
21
|
+
|
|
22
|
+
Host 把组合后的 `WebBootGraph` 写入 `window.__DSH_BOOT__`,并在 parser-preloaded script 执行前安装浏览器 module-loader facade。模块系统是一张 lazy CommonJS 表:加载 bundle 只注册 factory;materialize entry 时才以同步 `require` 运行 factory,并解析 platform module 和已声明的动态依赖。
|
|
23
|
+
|
|
24
|
+
Web boot kernel 创建模块系统、预取 `immediately` entry、挂载 vendored Cordis Loader,再创建图中的每个 entry。Cordis service injection 决定激活顺序;module graph 顺序只决定同步 import 能否被 materialize。完整 roster 到达 settled 状态后,`ui-renderer` hydrate 不依赖框架的 boot DOM,并调用唯一一次 context 级 `renderSlot('root')`。[Client Modules](client-modules.zh.md)负责 graph、bundle route、cache revision 与 loader 细节。
|
|
25
|
+
|
|
26
|
+
## Remote 通信
|
|
27
|
+
|
|
28
|
+
Host 业务 service 使用 Typert Remote decorator 标记可调用 method。Host generation 产出严格 descriptor、runtime codec、declaration merge 与 source map。Client 侧 `api-remotes` assembly 选择这些生成贡献,并把具体 method 挂到 `ctx.remote.<namespace>` 与 Session scope 的 `agentCtx.remote.<namespace>`。功能包依赖生成的 service face,而不依赖 Gateway 实现或 Host 包的运行时 entry。
|
|
29
|
+
|
|
30
|
+
Connection 拥有 request correlation、`/api` carrier、trust check、精确 Fetch 路由与 connection generation。API Gateway 拥有 Remote dispatch、取消、logical stream 与选定 Host event 的转发。Controller 操作应进入生成的 Remote method 或显式 Remote stream;功能自有的下载则注册精确 Fetch 路由。[API Gateway 参考](../api-gateway.zh.md)定义 generation 与调用,[Connection README](../../packages/client/connection/README.zh.md)定义物理 carrier 与信任策略。
|
|
31
|
+
|
|
32
|
+
内部 `$events` logical stream 是 Connection generation source。它的 opening `ready` frame 携带用于路径显示的 Host home,并在 Host listener 已挂载、任何 controller 开始 baseline read 之前建立 generation。`ctx.remote.$on()` 把 allowlist 内的普通 event 交付给 root Client Context,并把 scoped waterfall event 交付给已解析的 Session Context;waterfall listener 可以返回结果、调用 `next()` 或拒绝。
|
|
33
|
+
|
|
34
|
+
## Client models
|
|
35
|
+
|
|
36
|
+
每个 API controller 包都拥有配对的 Host face 与 Client face。Host 侧拥有权威 mutation 与 stream 生产;Client 侧基于相同的生成 wire type 维护 identity 稳定、与 React 无关的 model,并公开 observable snapshot 与 command。UI 包消费这些 Client service,不在 component store 中复制 transport state。
|
|
37
|
+
|
|
38
|
+
### Sessions
|
|
39
|
+
|
|
40
|
+
[`api/session-controller`](../../packages/api/session-controller/README.zh.md)公开 Session list、search、creation、selection data、prompt、queue、cancellation、pagination 及 follow/control stream 等 Host command。其 Client 侧按 `ClientSessions → SessionManager → Session` 组织:
|
|
41
|
+
|
|
42
|
+
- `ClientSessions` 提供 `ctx.sessions`,拥有 Session scope 与稳定的 `SessionBinding` object,并投影选中的 list state。
|
|
43
|
+
- `SessionManager` 拥有 list baseline、实时 list/control update、惰性 Session instance、queue、projection store、subagent catalog,以及 pull 与后到 update 之间的冲突顺序。
|
|
44
|
+
- 每个 `Session` 拥有一段由 `SessionEventLikeEntry` value 表示的连续逻辑 event window、pagination、follow、prompt/control state 与供 adapter 消费的 observable snapshot。
|
|
45
|
+
|
|
46
|
+
持久 event 路径打开 `follow()`,其首帧包含当前 header、tail page、cursor 与完整 projection baseline。历史 record 带有显式 `event` 或 `chunks` 判别字段和字段对齐的内部 `event`;journal 先校验每条 record 的逻辑 seq 闭区间,Client 再直接把这些 record 保留为 `SessionEventLikeEntry`,无需逐 record 转换。每个物理 generation 都根据该 snapshot 原子替换保留窗口,随后按 seq append 标准实时 event。`page()` 只用于更早历史与 gap repair。瞬态 control stream 每代以完整 baseline 开始,随后应用 queue、job 与 projection update。
|
|
47
|
+
|
|
48
|
+
### Workspaces
|
|
49
|
+
|
|
50
|
+
[`api/workspace-controller`](../../packages/api/workspace-controller/README.zh.md)把 Workspace mutation policy 与权威 follow feed 留在 Host。`ClientWorkspaceModel` 拥有浏览器侧 row、order、archived Session id、command echo,以及 stream/unary 竞态合并。每代 stream 先给出完整 baseline,再给出 `upsert`、`remove`、`order` 和 `archived` increment;重连时以新 baseline 替换 model。`WorkspaceController` 把该 model 作为 `ctx.workspaces` 公开,而 `ui-workspace` 向 UI 提供 `useWorkspaces` 与 navigation callback。
|
|
51
|
+
|
|
52
|
+
这种配对不会产生第二份业务真相。Host controller 决定持久状态与 mutation outcome;Client model 维护最新可用的本地 projection,在有利于渲染时保持 object identity,并明确 delayed response 与 replacement baseline 的合并规则。
|
|
53
|
+
|
|
54
|
+
## Conversation 与 presentation
|
|
55
|
+
|
|
56
|
+
`ui-session` 安装 `session` scope adapter,并提供 `useSessions`、`useSession`、`sessionId` 和 `useProjection`。领域 adapter 可以继续添加标准 source,但不会把 React hook 放进 model object。
|
|
57
|
+
|
|
58
|
+
`ui-conversation` 对每个 `SessionBinding.eventSource` 只绑定一次。它的 event registry 把标准 event 与 Client-only `chunkrow/*` 历史 event 关联成稳定的业务 Context,view registry 则 materialize target snapshot。packed run 在 replay 全程保持为单个 input 与 Match;Chat Assistant、Trajectory Assistant 和 Turn Tail 是解释它的三个内建 Definition。`ui-chat` 与 `ui-trajectory` 分别注册自己的 Definition 和 builder:它们可以解释同一 event family,但不会导入或共享彼此的最终 display model。Shell 选择一个已注册 view,再通过标准 hook 与 Slot 交付其 snapshot。[Conversation](conversation.zh.md)定义 Context identity、replay、Location data、target builder 与 keyed renderer。
|
|
59
|
+
|
|
60
|
+
`ui-slots` 提供类型化 registry 与 lifecycle ledger;`ui-renderer` 是唯一通过 `useSyncExternalStore` 绑定裸 observable、拥有 React context 并渲染 root tree 的包。功能 component 通过推导出的 props 接收 framework hook、owner prop、store action 与显式 injection。[Web Client Slots](slots.zh.md)列出这些输入、扩展 API 与当前 Slot 层级。
|
|
61
|
+
|
|
62
|
+
## 数据通路
|
|
63
|
+
|
|
64
|
+
| 路径 | 顺序 |
|
|
65
|
+
|---|---|
|
|
66
|
+
| 持久 Session 展示 | Host Session log → packed Remote `follow`/`page` 历史 → Client `SessionEventLikeEntry` window → Conversation Context → target snapshot(`chat`、`trajectory` 或其他已注册 target)→ Slot view → React |
|
|
67
|
+
| 瞬态 Session control | Host control baseline → Remote snapshot stream → `SessionManager` queue/job/projection store → Session 与 list snapshot → 标准 hook → component |
|
|
68
|
+
| Workspace 状态 | Host Workspace baseline 与 increment → `ClientWorkspaceModel` → `ctx.workspaces.list` → `useWorkspaces` → sidebar、hero 与 navigation entry |
|
|
69
|
+
| scoped interaction | Host Cordis waterfall → API Remotes `$events` → Session Context 上的 `ctx.remote.$on()` → 所属 UI 包 → result 或 `next()` |
|
|
70
|
+
| 用户 command | component callback → 注册项 inject face 或 Slot owner → `ctx.sessions`、`ctx.workspaces` 或生成的 scoped Remote → Host Controller → 权威 update → stream 或 event projection 回到 Client |
|
|
71
|
+
|
|
72
|
+
## 重连
|
|
73
|
+
|
|
74
|
+
物理恢复与逻辑恢复彼此独立。Gateway mux 恢复物理 WebSocket;Connection 发布可用 generation 后,每个 `RemoteStream` 分别重开自己的 logical source。Carrier failure 可以重试;business error、非法 opening item 或 protocol violation 会令所属 logical stream 终止。
|
|
75
|
+
|
|
76
|
+
恢复方式由数据语义决定:
|
|
77
|
+
|
|
78
|
+
- 持久 Session journal 校验逻辑 seq range,并根据每个 generation 的 opening snapshot 替换窗口;`page()` 提供更早历史并修复后续 range gap。
|
|
79
|
+
- Session control 与 Workspace stream 在断开期间保留最后一次发布的值,再用新的 opening baseline 原子替换。
|
|
80
|
+
- 普通 forwarded notification 不会 replay。需要可靠恢复的 stateful domain 必须提供 baseline、cursor 或显式 query;scoped waterfall 保留自身的 request lifetime。
|
|
81
|
+
|
|
82
|
+
架构中没有统一的 Client `Runtime`、`HostFrame`、`events.mux`、`events.host` 或通用 `resync()` API。Connection 公开 generation state,Gateway 管理 logical stream,Client model 则按自身数据定义 replacement 或 resume 语义。
|
|
83
|
+
|
|
84
|
+
## 包边界
|
|
85
|
+
|
|
86
|
+
功能插件包可以通过 `import type` 共享声明;不得运行时导入或转发另一个功能插件的值。跨包行为使用注入的 Cordis service,跨包 UI 使用 Slots。特定 target 的 Conversation Definition、projection helper 与最终 view data 留在所属 target 包中,即使 Chat 和 Trajectory 有意实现平行逻辑。
|
|
87
|
+
|
|
88
|
+
共享运行时值需要一个职责收窄、没有功能生命周期的静态 owner,例如 `client/store`、`ui-primitives` 或浏览器安全的 util 包。Transport 与生成 API assembly 可以导入运行时 contribution,因为组装同一个 protocol 正是它们的显式职责。功能包不能只为绕过此规则而添加 `dsh.client.external`。
|
|
89
|
+
|
|
90
|
+
根据所添加的扩展查阅四篇详细参考:
|
|
91
|
+
|
|
92
|
+
- [Client Modules](client-modules.zh.md):package discovery、loading、共享 module identity 与 boot order。
|
|
93
|
+
- [API Gateway](../api-gateway.zh.md):Host method、生成的 Remote contribution、stream 与 forwarded event。
|
|
94
|
+
- [Web Client Slots](slots.zh.md):component、hook、store、injection 与 placement。
|
|
95
|
+
- [Conversation](conversation.zh.md):持久 event correlation、target snapshot,以及 Chat 或 Trajectory view contribution。
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write docs/subsystems/web-server.md
|
|
5
|
-
web-server.md:
|
|
6
|
-
web-server.zh.md:
|
|
5
|
+
web-server.md: d9b1ec007bc73274bb0c8b5d58745da1c76e6cb6
|
|
6
|
+
web-server.zh.md: 66375534a89e2c4674e748d4178cb7a31761e57e
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](web-server.zh.md)
|
|
4
4
|
|
|
5
|
-
[dsh-host-webserver](../../packages/host/webserver) is the browser HTTP carrier for the GUI host: a single `node:http` plugin providing `ctx.webServer`, a named-route registry, index.html transform callbacks, and one fallback handler that a plugin may claim. It is not part of the agent loop and not a capability seam; it knows no harness concepts, and another plugin registers every feature route, including the `/api` bridge, plugin bundles, and the HMR event stream ([layering note](../../.agents/notes/implemented/architecture/2026-07-
|
|
5
|
+
[dsh-host-webserver](../../packages/host/webserver) is the browser HTTP carrier for the GUI host: a single `node:http` plugin providing `ctx.webServer`, a named-route registry, optional gzip response compression, index.html transform callbacks, and one fallback handler that a plugin may claim. It is not part of the agent loop and not a capability seam; it knows no harness concepts, and another plugin registers every feature route, including the `/api` bridge, plugin bundles, and the HMR event stream ([layering note](../../.agents/notes/implemented/architecture/2026-07-24-web-config-tree-boot-and-transport-layering.md)). It serves browsers only: Electron loads the built files over `file://` and sends fetch requests through an IPC bridge instead of this server.
|
|
6
6
|
|
|
7
7
|
Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
|
|
8
8
|
|
|
@@ -24,25 +24,31 @@ interface WebRoute {
|
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Match order is fixed: exact table first, then longest matching prefix, then the registered fallback. Registration order carries no request-facing semantics — named routes are composed to be disjoint, and the fallback seat answers anything no named route claims; one owner only, a second registration throws. The shipped Web composition claims the seat with [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts), the SPA dist server with locked semantics: non-GET/HEAD is 405, traversal outside the dist root is 403,
|
|
27
|
+
Match order is fixed: exact table first, then longest matching prefix, then the registered fallback. Registration order carries no request-facing semantics — named routes are composed to be disjoint, and the fallback seat answers anything no named route claims; one owner only, a second registration throws. The shipped Web composition claims the seat with [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts), the SPA dist server with locked semantics: Connection authenticates the dist root and configured index before their HTML is read; non-index assets remain public; non-GET/HEAD is 405, traversal outside the dist root is 403, existing files are served directly, absent or non-file targets are empty 404 responses, and unknown extensions ship as octet-stream.
|
|
28
28
|
|
|
29
29
|
## Config
|
|
30
30
|
|
|
31
31
|
```ts type-equiv
|
|
32
|
-
/**
|
|
32
|
+
/** Web server listen and response-compression config. */
|
|
33
33
|
interface Config {
|
|
34
34
|
/** Listen host; the two supported values are loopback and all-interfaces. */
|
|
35
35
|
host: '127.0.0.1' | '0.0.0.0'
|
|
36
36
|
/** Listen port; zero requests an OS-assigned port. */
|
|
37
37
|
port: number
|
|
38
|
+
/** Response compression for socket-backed HTTP requests. @default 'none' */
|
|
39
|
+
compression?: 'none' | 'gzip'
|
|
40
|
+
/** Gzip DEFLATE level from 0 through 9. @default 1 */
|
|
41
|
+
compressionLevel?: number
|
|
42
|
+
/** Minimum known response length eligible for gzip; unknown-length streams are eligible. @default 1024 */
|
|
43
|
+
compressionThresholdBytes?: number
|
|
38
44
|
}
|
|
39
45
|
```
|
|
40
46
|
|
|
41
|
-
`host` accepts only `127.0.0.1` (default posture) and `0.0.0.0` (deliberate network exposure)
|
|
47
|
+
`host` accepts only `127.0.0.1` (default posture) and `0.0.0.0` (deliberate network exposure). The carrier itself owns no TLS, authentication, or Origin policy, so a non-loopback bind exposes the server unless the composition supplies those controls. `compression` defaults to `none`; the shipped Web bundle selects gzip level 1 with a 1024-byte threshold. The shipped `dsh web` command selects loopback and rejects `--host 0.0.0.0`; its Connection plugin supplies Host/Origin checks plus browser-session authentication for every Host API route and stream. Other compositions own their bind and route-authentication policy. The dist location is an assembly fact of the frontend plugin that claims the seat.
|
|
42
48
|
|
|
43
49
|
## The service
|
|
44
50
|
|
|
45
|
-
`WebServer` (`ctx.webServer`) listens immediately on activation; a listen failure (EADDRINUSE…) rejects initialization, and the boot process reports the failed fiber. `register(route)` adds one named route and returns its disposer; a duplicate `(kind, path)` throws because route patterns are a composition-level contract and a collision is a misconfiguration. `
|
|
51
|
+
`WebServer` (`ctx.webServer`) listens immediately on activation; a listen failure (EADDRINUSE…) rejects initialization, and the boot process reports the failed fiber. `register(route)` adds one named route and returns its disposer; a duplicate `(kind, path)` throws because route patterns are a composition-level contract and a collision is a misconfiguration. Gzip wraps eligible socket-backed responses inside the server, so route handlers retain direct `ServerResponse` ownership and no response-writing API is added to the service. Existing content encodings, `Cache-Control: no-transform`, ranges, SSE, ZIP, and the packaged `.gz` Worker image remain identity responses. `collectIndexInjections()` gathers structured `IndexInjection` rows over one `webserver/index-inject` emit, and `renderIndex(html)` renders them into successful root and configured index responses before applying the raw `tapIndex(transform)` escape-hatch transforms in registration order; [dsh-client-modules](../../packages/client/modules) answers the event with the boot manifest rows. `port` reads the listening port, including the port assigned by the OS when `config.port` is 0.
|
|
46
52
|
|
|
47
53
|
A request whose handling throws (a malformed %-escape hitting `decodeURIComponent`, a client dropping mid-body) is logged as a warning and answered 400 — or the socket destroyed when headers are already out — never a process exit. Disposal pairs `close()` with `closeAllConnections()` because a handler may hold its response open (SSE) and such connections never end on their own; without the force-close, teardown would hang. The package never prints: the URL line belongs to the shell. Per-package operational detail, including the dev-mode bundle watch pipeline, stays in the [README](../../packages/host/webserver/README.md).
|
|
48
54
|
|
|
@@ -52,7 +58,7 @@ A request whose handling throws (a malformed %-escape hitting `decodeURIComponen
|
|
|
52
58
|
|
|
53
59
|
## Cordis API
|
|
54
60
|
|
|
55
|
-
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`) —
|
|
61
|
+
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).
|
|
56
62
|
|
|
57
63
|
<a id="ctxwebserver--webserver"></a>
|
|
58
64
|
|
|
@@ -88,8 +94,9 @@ registerUpgrade(route: WebUpgradeRoute): () => void
|
|
|
88
94
|
registerFallback(handler: WebRoute['handler']): () => void
|
|
89
95
|
|
|
90
96
|
/**
|
|
91
|
-
* Register
|
|
92
|
-
*
|
|
97
|
+
* Register a raw-HTML index transform, the escape hatch for markup no
|
|
98
|
+
* {@link IndexInjection} row expresses: {@link renderIndex} applies taps in
|
|
99
|
+
* registration order after rendering the structured rows.
|
|
93
100
|
* @param transform - pure html-to-html function.
|
|
94
101
|
* @returns the disposer removing the transform.
|
|
95
102
|
*/
|
|
@@ -102,7 +109,46 @@ tapIndex(transform: (html: string) => string): () => void
|
|
|
102
109
|
* @returns the transformed body.
|
|
103
110
|
*/
|
|
104
111
|
applyIndexTaps(html: string): string
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gather the structured injection table: one `webserver/index-inject` emit,
|
|
115
|
+
* every subscriber pushes its current rows. Fresh per call, so subscribers
|
|
116
|
+
* read live state (module graph, theme preference) at emit time.
|
|
117
|
+
* @returns rows in subscriber activation order.
|
|
118
|
+
*/
|
|
119
|
+
collectIndexInjections(): IndexInjection[]
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Render one index.html body: the structured injection table first, then
|
|
123
|
+
* the raw `tapIndex` transforms over the result.
|
|
124
|
+
* @param html - the raw index.html body.
|
|
125
|
+
* @returns the transformed body.
|
|
126
|
+
*/
|
|
127
|
+
renderIndex(html: string): string
|
|
105
128
|
```
|
|
106
129
|
|
|
107
|
-
Source: [`packages/host/webserver/src/index.ts
|
|
130
|
+
Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
|
|
131
|
+
|
|
132
|
+
<a id="webserver-events"></a>
|
|
133
|
+
|
|
134
|
+
### `webserver/*` events
|
|
135
|
+
|
|
136
|
+
<a id="webserverindex-inject--emit"></a>
|
|
137
|
+
|
|
138
|
+
#### `webserver/index-inject` — emit
|
|
139
|
+
|
|
140
|
+
Collect the structured index injection table. Emitted on every index render and every worker boot-payload request; listeners push their current rows, so a row's data is read fresh at emit time.
|
|
141
|
+
|
|
142
|
+
```ts cordis-catalog
|
|
143
|
+
/**
|
|
144
|
+
* Collect the structured index injection table. Emitted on every index
|
|
145
|
+
* render and every worker boot-payload request; listeners push their
|
|
146
|
+
* current rows, so a row's data is read fresh at emit time.
|
|
147
|
+
* @param table - Mutable row table; listeners append in activation order.
|
|
148
|
+
* @mode emit
|
|
149
|
+
*/
|
|
150
|
+
'webserver/index-inject'(table: IndexInjection[]): void
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
|
|
108
154
|
<!-- END GENERATED cordis-surface -->
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](web-server.md) | 中文
|
|
4
4
|
|
|
5
|
-
[dsh-host-webserver](../../packages/host/webserver) 是 GUI
|
|
5
|
+
[dsh-host-webserver](../../packages/host/webserver) 是 GUI Host 的浏览器 HTTP 载体:它是一个提供 `ctx.webServer` 的 `node:http` 插件,包含具名路由注册表、可选的 gzip 响应压缩、index.html 转换回调,以及一个可由插件认领的回退处理器。它不属于 agent loop(智能体循环),也不是能力 seam;它不了解任何 harness 概念。其他插件负责注册所有功能路由,包括 `/api` 桥接、插件 bundle 和 HMR(热模块替换)事件流([分层说明](../../.agents/notes/implemented/architecture/2026-07-24-web-config-tree-boot-and-transport-layering.zh.md))。该服务器只服务浏览器:Electron 通过 `file://` 加载已构建文件,并经 IPC 桥接发送 fetch 请求,不使用本服务器。
|
|
6
6
|
|
|
7
7
|
源码:[`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
|
|
8
8
|
|
|
@@ -24,27 +24,33 @@ interface WebRoute {
|
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
匹配顺序固定:先查 exact 表,再取最长匹配前缀,最后落到已注册的回退。注册顺序不携带任何面向请求的语义:具名路由在组合上互不相交,任何未被具名路由认领的请求都由回退席位应答;席位只有一个所有者,第二次注册会抛出异常。发布的 Web 组合用 [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts) 认领席位,即遵循固定语义的 SPA dist
|
|
27
|
+
匹配顺序固定:先查 exact 表,再取最长匹配前缀,最后落到已注册的回退。注册顺序不携带任何面向请求的语义:具名路由在组合上互不相交,任何未被具名路由认领的请求都由回退席位应答;席位只有一个所有者,第二次注册会抛出异常。发布的 Web 组合用 [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts) 认领席位,即遵循固定语义的 SPA dist 服务器:Connection 在读取 dist 根目录和配置 index 的 HTML 前完成认证;非 index 资产保持公开;非 GET/HEAD 返回 405,越出 dist 根目录的遍历返回 403,现有文件直接提供,缺失或不是文件的目标返回空的 404,未知扩展名按 octet-stream 发送。
|
|
28
28
|
|
|
29
29
|
## 配置
|
|
30
30
|
|
|
31
31
|
```ts type-equiv
|
|
32
|
-
/**
|
|
32
|
+
/** Web server listen and response-compression config. */
|
|
33
33
|
interface Config {
|
|
34
34
|
/** Listen host; the two supported values are loopback and all-interfaces. */
|
|
35
35
|
host: '127.0.0.1' | '0.0.0.0'
|
|
36
36
|
/** Listen port; zero requests an OS-assigned port. */
|
|
37
37
|
port: number
|
|
38
|
+
/** Response compression for socket-backed HTTP requests. @default 'none' */
|
|
39
|
+
compression?: 'none' | 'gzip'
|
|
40
|
+
/** Gzip DEFLATE level from 0 through 9. @default 1 */
|
|
41
|
+
compressionLevel?: number
|
|
42
|
+
/** Minimum known response length eligible for gzip; unknown-length streams are eligible. @default 1024 */
|
|
43
|
+
compressionThresholdBytes?: number
|
|
38
44
|
}
|
|
39
45
|
```
|
|
40
46
|
|
|
41
|
-
`host` 只接受 `127.0.0.1`(默认姿态)和 `0.0.0.0
|
|
47
|
+
`host` 只接受 `127.0.0.1`(默认姿态)和 `0.0.0.0`(刻意的网络暴露)。载体本身不拥有 TLS、认证或 Origin 策略,因此绑定到非回环地址会暴露服务器,除非组合层提供这些控制。`compression` 默认为 `none`;随附的 Web 组合选择 gzip level 1 和 1024 字节阈值。随附的 `dsh web` 命令选择 loopback 并拒绝 `--host 0.0.0.0`;其 Connection 插件为每个 Host API route 与 stream 提供 Host/Origin 校验和浏览器会话认证。其他组合自行拥有绑定与路由认证策略。dist 位置是认领席位的前端插件的组装事实。
|
|
42
48
|
|
|
43
49
|
## 服务
|
|
44
50
|
|
|
45
|
-
`WebServer`(`ctx.webServer`)在激活时立即监听;监听失败(EADDRINUSE 等)会使初始化被拒绝,启动进程会报告失败的 fiber。`register(route)` 添加一条具名路由并返回其 disposer;重复的 `(kind, path)`
|
|
51
|
+
`WebServer`(`ctx.webServer`)在激活时立即监听;监听失败(EADDRINUSE 等)会使初始化被拒绝,启动进程会报告失败的 fiber。`register(route)` 添加一条具名路由并返回其 disposer;重复的 `(kind, path)` 抛出异常,因为路由模式是组合层约定,冲突即配置错误。Gzip 在服务器内部包装符合条件且基于 socket 的响应,因此 route handler 继续直接持有 `ServerResponse`,服务也不新增响应写出 API。已有内容编码、`Cache-Control: no-transform`、范围响应、SSE、ZIP 与打包后的 `.gz` Worker 镜像均保持 identity 响应。`collectIndexInjections()` 经一次 `webserver/index-inject` emit 收集结构化 `IndexInjection` 行,`renderIndex(html)` 把它们渲染进成功的根路径和配置 index 响应,随后再按注册顺序应用原始的 `tapIndex(transform)` 逃生口转换;[dsh-client-modules](../../packages/client/modules) 以启动 manifest(元数据清单)行回应该事件。`port` 读取监听端口,包括 `config.port` 为 0 时操作系统分配的端口。
|
|
46
52
|
|
|
47
|
-
处理过程中抛出异常的请求(畸形的 % 转义撞上 `decodeURIComponent`、客户端在请求体中途断开)会记录为警告并应答 400(响应头已发出时则销毁 socket),绝不导致进程退出。dispose(资源释放)把 `close()` 与 `closeAllConnections()` 配对使用,因为处理器可能像 SSE(Server-Sent Events)那样保持响应打开,而这类连接永远不会自行结束;没有强制关闭,拆卸就会挂起。该包从不打印输出:URL 行归 shell 所有。逐包运维细节(含开发模式的 bundle 监视流水线)留在 [README](../../packages/host/webserver/README.md) 中。
|
|
53
|
+
处理过程中抛出异常的请求(畸形的 % 转义撞上 `decodeURIComponent`、客户端在请求体中途断开)会记录为警告并应答 400(响应头已发出时则销毁 socket),绝不导致进程退出。dispose(资源释放)把 `close()` 与 `closeAllConnections()` 配对使用,因为处理器可能像 SSE(Server-Sent Events)那样保持响应打开,而这类连接永远不会自行结束;没有强制关闭,拆卸就会挂起。该包从不打印输出:URL 行归 shell 所有。逐包运维细节(含开发模式的 bundle 监视流水线)留在 [README](../../packages/host/webserver/README.zh.md) 中。
|
|
48
54
|
|
|
49
55
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
50
56
|
|
|
@@ -52,7 +58,7 @@ interface Config {
|
|
|
52
58
|
|
|
53
59
|
## Cordis API
|
|
54
60
|
|
|
55
|
-
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`) —
|
|
61
|
+
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.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
|
56
62
|
|
|
57
63
|
<a id="ctxwebserver--webserver"></a>
|
|
58
64
|
|
|
@@ -88,8 +94,9 @@ registerUpgrade(route: WebUpgradeRoute): () => void
|
|
|
88
94
|
registerFallback(handler: WebRoute['handler']): () => void
|
|
89
95
|
|
|
90
96
|
/**
|
|
91
|
-
* Register
|
|
92
|
-
*
|
|
97
|
+
* Register a raw-HTML index transform, the escape hatch for markup no
|
|
98
|
+
* {@link IndexInjection} row expresses: {@link renderIndex} applies taps in
|
|
99
|
+
* registration order after rendering the structured rows.
|
|
93
100
|
* @param transform - pure html-to-html function.
|
|
94
101
|
* @returns the disposer removing the transform.
|
|
95
102
|
*/
|
|
@@ -102,7 +109,46 @@ tapIndex(transform: (html: string) => string): () => void
|
|
|
102
109
|
* @returns the transformed body.
|
|
103
110
|
*/
|
|
104
111
|
applyIndexTaps(html: string): string
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gather the structured injection table: one `webserver/index-inject` emit,
|
|
115
|
+
* every subscriber pushes its current rows. Fresh per call, so subscribers
|
|
116
|
+
* read live state (module graph, theme preference) at emit time.
|
|
117
|
+
* @returns rows in subscriber activation order.
|
|
118
|
+
*/
|
|
119
|
+
collectIndexInjections(): IndexInjection[]
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Render one index.html body: the structured injection table first, then
|
|
123
|
+
* the raw `tapIndex` transforms over the result.
|
|
124
|
+
* @param html - the raw index.html body.
|
|
125
|
+
* @returns the transformed body.
|
|
126
|
+
*/
|
|
127
|
+
renderIndex(html: string): string
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
|
|
131
|
+
|
|
132
|
+
<a id="webserver-events"></a>
|
|
133
|
+
|
|
134
|
+
### `webserver/*` events
|
|
135
|
+
|
|
136
|
+
<a id="webserverindex-inject--emit"></a>
|
|
137
|
+
|
|
138
|
+
#### `webserver/index-inject` — emit
|
|
139
|
+
|
|
140
|
+
Collect the structured index injection table. Emitted on every index render and every worker boot-payload request; listeners push their current rows, so a row's data is read fresh at emit time.
|
|
141
|
+
|
|
142
|
+
```ts cordis-catalog
|
|
143
|
+
/**
|
|
144
|
+
* Collect the structured index injection table. Emitted on every index
|
|
145
|
+
* render and every worker boot-payload request; listeners push their
|
|
146
|
+
* current rows, so a row's data is read fresh at emit time.
|
|
147
|
+
* @param table - Mutable row table; listeners append in activation order.
|
|
148
|
+
* @mode emit
|
|
149
|
+
*/
|
|
150
|
+
'webserver/index-inject'(table: IndexInjection[]): void
|
|
105
151
|
```
|
|
106
152
|
|
|
107
|
-
Source: [`packages/host/webserver/src/index.ts
|
|
153
|
+
Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
|
|
108
154
|
<!-- END GENERATED cordis-surface -->
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write docs/subsystems/web.md
|
|
5
|
-
web.md:
|
|
6
|
-
web.zh.md:
|
|
5
|
+
web.md: fe6f1ca357eec19f55848ffbe54ed339eb638924
|
|
6
|
+
web.zh.md: bef3803abcd9c23582ee94479c89a05c7e3943ef
|