dsh-plugin-guide 0.3.1 → 0.3.2
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 +27 -22
- 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 +23 -7
- package/references/official-docs/docs/architecture.zh.md +36 -20
- package/references/official-docs/docs/capability-seams.i18n.yaml +2 -2
- package/references/official-docs/docs/capability-seams.md +132 -67
- package/references/official-docs/docs/capability-seams.zh.md +132 -67
- package/references/official-docs/docs/config-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/config-catalog.md +659 -373
- package/references/official-docs/docs/config-catalog.zh.md +677 -391
- package/references/official-docs/docs/cookbook/adding-a-package.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/adding-a-package.md +2 -3
- package/references/official-docs/docs/cookbook/adding-a-package.zh.md +8 -7
- 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 +666 -747
- package/references/official-docs/docs/module-graph.zh.md +668 -749
- package/references/official-docs/docs/persistence-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/persistence-catalog.md +172 -40
- package/references/official-docs/docs/persistence-catalog.zh.md +180 -48
- 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 +206 -0
- package/references/official-docs/docs/subsystems/agent-team.zh.md +206 -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 +5 -5
- package/references/official-docs/docs/subsystems/code-runtime.zh.md +6 -6
- package/references/official-docs/docs/subsystems/commands.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/commands.md +29 -6
- package/references/official-docs/docs/subsystems/commands.zh.md +30 -7
- package/references/official-docs/docs/subsystems/compaction.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/compaction.md +5 -5
- package/references/official-docs/docs/subsystems/compaction.zh.md +11 -11
- 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 +110 -33
- package/references/official-docs/docs/subsystems/core.zh.md +141 -62
- 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 +4 -4
- package/references/official-docs/docs/subsystems/feedback.zh.md +4 -4
- 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 +35 -17
- package/references/official-docs/docs/subsystems/persistence.zh.md +38 -20
- 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 +136 -67
- package/references/official-docs/docs/subsystems/session-projection.zh.md +136 -67
- package/references/official-docs/docs/subsystems/session-query.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-query.md +11 -3
- package/references/official-docs/docs/subsystems/session-query.zh.md +12 -4
- 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 +3 -3
- package/references/official-docs/docs/subsystems/session-title.zh.md +5 -5
- package/references/official-docs/docs/subsystems/session.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session.md +284 -39
- package/references/official-docs/docs/subsystems/session.zh.md +301 -54
- 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 +174 -0
- package/references/official-docs/docs/subsystems/slots.zh.md +174 -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 +13 -5
- package/references/official-docs/docs/subsystems/storage.zh.md +16 -8
- package/references/official-docs/docs/subsystems/subagent.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/subagent.md +120 -32
- package/references/official-docs/docs/subsystems/subagent.zh.md +131 -41
- 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 +27 -12
- package/references/official-docs/docs/subsystems/token-meter.zh.md +28 -13
- 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 +433 -27
- package/references/official-docs/docs/tool-catalog.zh.md +438 -29
- 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 +1 -1
- package/references/official-docs/docs/web-styling.zh.md +2 -2
- package/references/official-docs/packages/AGENTS.md +3 -2
- 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
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Cookbook: 新增设置卡片
|
|
2
|
+
|
|
3
|
+
[English](adding-a-settings-card.md) | 中文
|
|
4
|
+
|
|
5
|
+
插件如何把自己的配置放上 Web 设置页。这条路径上没有任何一步需要改动本仓库:Host 服务每一个已注册的 settings 命名空间,而**插件配置**分区以卡片所编辑的命名空间为键,因此同时注册了两个半侧的插件会被自动配对。
|
|
6
|
+
|
|
7
|
+
两个半侧住在同一个包里——Host 半侧在 `src/`,浏览器半侧在 `src/client/`,以 `./client` 导出并用 `dsh.client` 声明。[`packages/client/ui-theme`](../../packages/client/ui-theme) 是这种打包方式的现成例子;本分区自带的卡片在 [`packages/client/ui-settings-plugins`](../../packages/client/ui-settings-plugins)。
|
|
8
|
+
|
|
9
|
+
## 1. 注册命名空间(Host 半侧)
|
|
10
|
+
|
|
11
|
+
命名空间就是配对用的键,所以只挑一次,并在两个半侧都写出它。已经有 `cordis.yml` entry 的消费方应通过 `ctx.settings.installSection()` 注册——它把 entry 层叠在用户文档之下,并在没有挂载 settings provider 时照常工作:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
15
|
+
import type {} from '@deepseek-ai/dsh-settings'
|
|
16
|
+
import z from '@deepseek-ai/schemastery'
|
|
17
|
+
|
|
18
|
+
declare function assertReachable(endpoint: string | undefined): void
|
|
19
|
+
declare function rebuildFromSettings(config: Config): void
|
|
20
|
+
|
|
21
|
+
export const MY_PLUGIN_NS = 'my-plugin'
|
|
22
|
+
|
|
23
|
+
export interface Config {
|
|
24
|
+
endpoint?: string
|
|
25
|
+
retries?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Config: z<Config> = z.object({
|
|
29
|
+
endpoint: z.string(),
|
|
30
|
+
retries: z.number().step(1).min(0).default(3),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export function apply(ctx: Context, config: Config) {
|
|
34
|
+
let source = () => config
|
|
35
|
+
ctx.inject(['settings'], (settingsCtx) => {
|
|
36
|
+
settingsCtx.settings.installSection(ctx, MY_PLUGIN_NS, Config, config, {
|
|
37
|
+
// Constraints the schema cannot express refuse the write, not the next use.
|
|
38
|
+
validate: value => void assertReachable(value.endpoint),
|
|
39
|
+
setSource: (current) => { source = current },
|
|
40
|
+
onChange: () => { rebuildFromSettings(source()) },
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
字段上的 `role('secret')` 让它的值不出现在任何响应里;卡片把这类字段写进 `update`/`mutate` 载荷,或改为经 `credentials` 领域寻址一个凭据引用。`applies: 'restart'` 告诉配置表层:拥有方要到下次启动才会对变更生效。
|
|
47
|
+
|
|
48
|
+
## 2. 注册卡片(浏览器半侧)
|
|
49
|
+
|
|
50
|
+
卡片以自己的命名空间为键注册进 `settings.plugin.item`,并拥有其中的一切——外观、控件与文案。它通过 `ctx.settingsScope` 读写,后者用读取时的 revision 为每次写入设栅:
|
|
51
|
+
|
|
52
|
+
```ts ignore-check
|
|
53
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis'
|
|
54
|
+
// Type-only: the keyed slot's declaration. Cross-plugin collaboration goes
|
|
55
|
+
// through cordis services; a value import fails the client bundle-purity gate.
|
|
56
|
+
import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'
|
|
57
|
+
|
|
58
|
+
export const inject = ['slots', 'locale', 'connection', 'remote', 'settingsScope']
|
|
59
|
+
|
|
60
|
+
export function apply(ctx: ClientContext): void {
|
|
61
|
+
const card = new MyPluginCardController(ctx.settingsScope.bind({ namespace: 'my-plugin' }))
|
|
62
|
+
ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({
|
|
63
|
+
name: 'settings.plugin.item',
|
|
64
|
+
key: 'my-plugin',
|
|
65
|
+
locale: 'settings.myPlugin',
|
|
66
|
+
inject: () => card.inject(),
|
|
67
|
+
}, MyPluginCard),
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
scope 快照携带表单所需的一切:解析后的 `value`、组装层 `base`,以及原始的 `user` 层——字段是否被覆盖,取决于它在 `user` 层中是否**出现**,而非它的值。`scope.set(field, value)` 存一个字段,`scope.unset(field)` 把它清回组装层。
|
|
73
|
+
|
|
74
|
+
## 3. 标签页拿它做什么
|
|
75
|
+
|
|
76
|
+
**插件配置**标签页读取 Host 服务了哪些命名空间,并为每个命名空间派发一个 slot 键。当 Host 服务了某卡片的键时它被渲染,否则被跳过,因此从未组装过 Host 半侧的部署不会留下这张卡片的任何痕迹。被服务却无人认领的命名空间什么都不渲染——归其他页面所有的那些命名空间(`ui-theme`、`permission`、`llm-*`)正是这样留在本标签页之外的。
|
|
77
|
+
|
|
78
|
+
卡片按其注册进该 slot 的顺序出现;keyed entry 不声明自己的 `order`。
|
|
79
|
+
|
|
80
|
+
## 打包
|
|
81
|
+
|
|
82
|
+
浏览器半侧由[客户端模块系统](../../packages/client/modules)提供给页面:它扫描已启用的 Loader entries 中声明了 `dsh.client` 的包,并提供每个包构建出的 `./client` 导出。因此只要 `cordis.yml` 挂载了该插件,它就会出现在页面上——无需重新构建 Web 应用。
|
|
83
|
+
|
|
84
|
+
```jsonc
|
|
85
|
+
{
|
|
86
|
+
"exports": {
|
|
87
|
+
".": { "types": "./lib/types/index.d.ts", "default": "./lib/index.js" },
|
|
88
|
+
"./client": { "types": "./lib/types/client/index.d.ts", "default": "./lib/client.js" }
|
|
89
|
+
},
|
|
90
|
+
"dsh": { "client": { "platform": "web", "inject": ["@deepseek-ai/dsh-client-ui-settings-plugins"] } }
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
bundle 必须是 loader 的 lazy-CJS factory 产物。在本仓库内,`tsdown.config.ts` 就是基于共享预设的三行:
|
|
95
|
+
|
|
96
|
+
```ts ignore-check
|
|
97
|
+
import { clientBundle } from '../tsdown.client.ts'
|
|
98
|
+
|
|
99
|
+
export default clientBundle('@deepseek-ai/dsh-client-my-plugin', ['lib/types/index.js', 'lib/types/invariant.js'])
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
没有已发布的预设暴露该包,因此本仓库之外的包得自行复刻同样的输出格式。bundle 纯净度门禁同时拒绝跨插件的值导入,所以卡片无法导入本分区的卡片外观或其暂存表单模型——它渲染自己的那一份,并自行拥有暂存与 revision 设栅。这两条限制都记在[本分区的已知限制](../../packages/client/ui-settings-plugins/README.zh.md#known-limitations-and-deferred-work)里。
|
|
@@ -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/cookbook/adding-a-tool.md
|
|
5
|
-
adding-a-tool.md:
|
|
6
|
-
adding-a-tool.zh.md:
|
|
5
|
+
adding-a-tool.md: f6b2703f3db69a6abc04dbd0fd9893555eed0602
|
|
6
|
+
adding-a-tool.zh.md: d4831e2be061c2565e88004062cbb1558491bb9d
|
|
@@ -50,7 +50,7 @@ Registration is effect-based: disposing the plugin fiber unregisters the tool. S
|
|
|
50
50
|
|
|
51
51
|
## Long-running work
|
|
52
52
|
|
|
53
|
-
Gate `run_in_background` with producer config, then register through `ctx.jobs.start({ kind, label, owner: exec.agent, run })`. The registry rejects a pre-aborted invocation before the producer body; the runtime validates ownership and task-controller availability before `run()` starts work, then supplies the id, session fence, generic control tools, notices, and owner cleanup. A successful background branch returns a typed canonical handle such as `{ kind: 'background', jobId }`; its Native renderer may keep human prose such as `started background job bash-1`, but
|
|
53
|
+
Gate `run_in_background` with producer config, then register through `ctx.jobs.start({ kind, label, owner: exec.agent, run })`. The registry rejects a pre-aborted invocation before the producer body; the runtime validates ownership and task-controller availability before `run()` starts work, then supplies the id, session fence, generic control tools, notices, and owner cleanup. A successful background branch returns a typed canonical handle such as `{ kind: 'background', jobId }`; its Native renderer may keep human prose such as `started background job bash-1`, but PTC mode must never parse that prose to recover the id.
|
|
54
54
|
|
|
55
55
|
The producer supplies synchronous `cancel`, non-rejecting `done` that settles after resource cleanup, and optional consuming `readOutput` with bounded-output formatting. A pre-aborted call is a failure because no task exists whose id could satisfy the successful output schema. Once `ctx.jobs.start()` publishes the id, use a task-owned cancellation signal rather than `exec.signal`: later outer-call cancellation stops waiting for the call but does not kill published work; `job_kill`, owner disposal, and service teardown own that lifetime. Foreground work remains coupled to `exec.signal`. See the [background job runtime Agent Note](../../.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md) and `dsh-tool-bash` for a stream producer.
|
|
56
56
|
|
|
@@ -58,9 +58,9 @@ The producer supplies synchronous `cancel`, non-rejecting `done` that settles af
|
|
|
58
58
|
|
|
59
59
|
Prefer not to build deployment policy into the tool. Use `tools/pre-execute` for extensible allow/deny/ask policy (the [permission-gate example](extension-cookbook.md#a-hook-plugin-permission-gate-example)), `ctx.tools.guard()` for a final monotonic deny that later listeners cannot undo, `tools/execute` to wrap dispatch with a deadline, retry, or metrics collection, `tools/post-execute` to replace presentation content or the returned value, block the result, or attach model-facing context, and `tools/result` to observe the immutable normalized outcome. A content replacement leaves programmatic access to `value` intact; confidentiality policy blocks or replaces the value. A sandboxing implementation can also run inside the tool's executor implementation; the [`dsh-tools` README](../../packages/core/tools/README.md#extension-points) defines each extension point's inputs, order, return values, and failure behavior.
|
|
60
60
|
|
|
61
|
-
##
|
|
61
|
+
## PTC mode reaches your tool for free
|
|
62
62
|
|
|
63
|
-
In [
|
|
63
|
+
In [PTC mode](../../packages/core/tools/README.md), every visible registered tool is available as `await tools.<name>(args)` without extra integration. The generated `ToolArgsMap` and `ToolOutputMap` derive exact argument and canonical-return types from the same schemas, and calls re-enter the normal execution pipeline. A successful call resolves to the final canonical JSON value after policy, not to rendered Native content. A failed call rejects with the real `ToolCallError`; programs can inspect only its `name`, `toolName`, and human-readable `message`, not internal error codes or a failure union.
|
|
64
64
|
|
|
65
65
|
Design `output.schema` as a useful programmatic API: return handles and fields directly, allow scalar/array/null roots when they are the honest value, and keep human explanation in `output.render`. Intermediate values are execution-local, are not persisted or prompt-truncated, and have no byte cap, so the producer's truthful acquisition bounds and process memory still matter. Only the outer `run_code` logs/result cross the configurable output cap and model-facing spill pipeline.
|
|
66
66
|
|
|
@@ -78,6 +78,7 @@ Both methods return a **`card`-tagged render intent** — pick the card kind tha
|
|
|
78
78
|
- `generic` supplies an optional title and content.
|
|
79
79
|
- `terminal` supplies raw output and optional exit metadata; each UI renders its capable or fallback view.
|
|
80
80
|
- `diff` supplies applied hunks, often derived by `output.presentationMeta` and carried in persisted `result.meta` so replay reproduces them. Mutation tools keep a diff result because the completed view replaces the pending card.
|
|
81
|
+
- `read` supplies a completed file window reconstructed from persisted `result.meta`: the file `path`, a 1-based `offset`, the returned `lines` (each keeping its file line number), `totalLines`, and an optional `lang` highlight hint; a UI without the `read` capability falls back to the raw result content. There is no `read` call view — a read call's pending state stays a generic card, since content exists only after `execute`. (tool-fs `read`.)
|
|
81
82
|
- `search` supplies a discovery result reconstructed from persisted `result.meta`: grouped-by-file matches (`shape: 'matches'`, grep) or a flat path list (`shape: 'paths'`, glob), plus `truncated`/`total` so a UI never presents a capped result as complete. The view carries no result text (a UI without a search card falls back to the raw result content), and there is no `search` call view — a discovery call's pending state stays a generic card, since matches exist only after `execute`. (tool-fs-search `grep`/`glob`.)
|
|
82
83
|
- `web` supplies a completed web retrieval, discriminated by `kind: 'search' | 'fetch'` (the structured search sources or the fetch summary), derived from `result.meta`; it carries no body copy, so a UI without the `web` capability falls back to the raw result content. (tool-web `web_search`/`web_fetch`.)
|
|
83
84
|
|
|
@@ -87,7 +88,13 @@ Hard rules (they bite if broken):
|
|
|
87
88
|
- **UI-only formatting stays out of the model result.** A fenced ` ```console ` block, a diff, a relativized path—none of these belongs in the canonical value or Native content merely to serve a UI. `output.render` owns model-facing prose; `presentationMeta` plus the card presenters own replayable UI state. A `terminal` result view carries raw output and the adapter adds any fallback framing.
|
|
88
89
|
- **`defineTool` soft-validates the display path.** Malformed or older logged arguments make the wrapper return `undefined` (a generic fallback) rather than throw — display must never crash a replay.
|
|
89
90
|
|
|
90
|
-
The neutral vocabulary lives in `dsh-tools`; tools never import a UI or transport type.
|
|
91
|
+
The neutral vocabulary lives in `dsh-tools`; tools never import a UI or transport type. Consumers of this API map each `card` into their own view. The design and the why are in [the render-intent-union Agent Note](../../.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md); `dsh-tool-fs` (generic/diff) and `dsh-tool-bash` (terminal) are the reference implementations.
|
|
92
|
+
|
|
93
|
+
## Web Client presentation
|
|
94
|
+
|
|
95
|
+
The built-in Web Client does not consume `presentCall` or `presentResult`. Session `page` and `follow` transport raw `tool/call` and `tool/result` events, including persisted `result.meta`. A Client plugin registers its wire tool name in the `tool.call.toolview` keyed slot and derives component props from the `ToolCallBlock` arguments, content, error, metadata, existing Code Dispatch `parentCallId`, and Session path facts. It validates these wire values locally and returns the generic row for malformed or unsupported input.
|
|
96
|
+
|
|
97
|
+
Use `output.presentationMeta(args, value)` when an existing Web card needs bounded structured result facts that model-facing content cannot preserve losslessly. Do not store React props or a selected card in metadata, import a Host tool implementation into a browser bundle, or create another Client presenter registry. Defining Host presentation methods alone does not add a specialized Web card. The [Client-derived presentation Agent Note](../../.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.md) defines ownership, fallback, and equivalence requirements.
|
|
91
98
|
|
|
92
99
|
## Verification
|
|
93
100
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](adding-a-tool.md) | 中文
|
|
4
4
|
|
|
5
|
-
面向模型的工具必须满足哪些约定,均以本文为准。如需按步骤构建第一个工具,请阅读[构建工具](../user/develop/basic/tool.md)。`packages/shell/tool-bash` 是生产级的三包示例。
|
|
5
|
+
面向模型的工具必须满足哪些约定,均以本文为准。如需按步骤构建第一个工具,请阅读[构建工具](../user/develop/basic/tool.zh.md)。`packages/shell/tool-bash` 是生产级的三包示例。
|
|
6
6
|
|
|
7
7
|
## 最小形态
|
|
8
8
|
|
|
@@ -39,7 +39,7 @@ export function apply(ctx: Context) {
|
|
|
39
39
|
|
|
40
40
|
## execute() 约定的规则
|
|
41
41
|
|
|
42
|
-
- **参数已为你校验。** `defineTool` 在 `execute` 运行前,会根据统一的 `ParameterSchemaSpec` 校验模型生成的 `arguments`(类型、必填键、字面量约束、恰好匹配一个分支的联合以及嵌套值——见[运行时参数校验](../../.agents/notes/implemented/architecture/2026-06-11-runtime-arg-validation.md)),因此 `execute` 内的 args 会匹配 `InferArgs`。显式对象节点必须声明 `additionalProperties: true | false`;隐式参数根对象保持开放。你仍需手动检查 schema DSL 无法表达的约束,例如非空字符串、正数或跨字段规则。直接注册的原始 JSON Schema 工具自行负责输入校验。
|
|
42
|
+
- **参数已为你校验。** `defineTool` 在 `execute` 运行前,会根据统一的 `ParameterSchemaSpec` 校验模型生成的 `arguments`(类型、必填键、字面量约束、恰好匹配一个分支的联合以及嵌套值——见[运行时参数校验](../../.agents/notes/implemented/architecture/2026-06-11-runtime-arg-validation.zh.md)),因此 `execute` 内的 args 会匹配 `InferArgs`。显式对象节点必须声明 `additionalProperties: true | false`;隐式参数根对象保持开放。你仍需手动检查 schema DSL 无法表达的约束,例如非空字符串、正数或跨字段规则。直接注册的原始 JSON Schema 工具自行负责输入校验。
|
|
43
43
|
- **注册借用你的只读定义。** 类型化的同进程贡献不是序列化边界;注册后不要修改其 schema 或替换回调。`schemas()` 只物化显式的模型可见投影。如需热替换工具,请 dispose 其所属副作用并注册替代品;回调闭包内的可变状态仍是普通的插件状态。
|
|
44
44
|
- **执行身份受保护。** 注册表在一次递归遍历中将 `arguments` 物化为分离的无损 JSON,在策略开始前冻结该值,并分配一个不透明的 `exec.token`;`callId`、`name`、`arguments`、`agent`、`token`、必填且由调用方持有的 `signal`,以及可选的外层传输 `parent` token 在整个分发过程中保持不可变。`parent` 仅用于身份标识,不暴露活跃的外层执行。请将 `args` 视为只读输入。只有 around-dispatch 包装器会收到可变视图;它可以替换并恢复必填的 `exec.signal` 以施加截止时间,但不能移除该信号。
|
|
45
45
|
- **声明并返回一个规范 JSON 值。** `output.schema` 使用 `ValueSchemaSpec`,根可以是对象、数组、标量或 null。`execute` 只返回推导出的值;注册表将其快照为无损 JSON,完成校验和冻结后,再传给 `output.render(args, value)`。工具主体不要返回内容块,也不要迫使调用方从自然语言中解析 id 和字段。
|
|
@@ -50,19 +50,19 @@ export function apply(ctx: Context) {
|
|
|
50
50
|
|
|
51
51
|
## 长时间运行的工作
|
|
52
52
|
|
|
53
|
-
通过 producer 配置控制 `run_in_background`,然后使用 `ctx.jobs.start({ kind, label, owner: exec.agent, run })` 注册任务。注册表会在进入 producer 主体前将已预先中止的调用判为失败;运行时会在 `run()` 启动工作前校验 owner 和任务控制器是否可用,随后提供 id、会话围栏、通用控制工具、通知和 owner cleanup。成功的后台分支会返回类型化的规范句柄,如 `{ kind: 'background', jobId }`;其 Native 渲染器可以保留 `started background job bash-1` 这类供人阅读的自然语言,但
|
|
53
|
+
通过 producer 配置控制 `run_in_background`,然后使用 `ctx.jobs.start({ kind, label, owner: exec.agent, run })` 注册任务。注册表会在进入 producer 主体前将已预先中止的调用判为失败;运行时会在 `run()` 启动工作前校验 owner 和任务控制器是否可用,随后提供 id、会话围栏、通用控制工具、通知和 owner cleanup。成功的后台分支会返回类型化的规范句柄,如 `{ kind: 'background', jobId }`;其 Native 渲染器可以保留 `started background job bash-1` 这类供人阅读的自然语言,但 PTC mode 绝不能通过解析该文本取得 id。
|
|
54
54
|
|
|
55
|
-
producer 提供同步的 `cancel`、在资源清理后 settle 且不 reject 的 `done`,以及可选的消费式 `readOutput`(负责有界输出的格式化)。预先中止的调用属于失败,因为此时没有任务,其 id 无法满足成功输出 schema。`ctx.jobs.start()` 发布 id 后,应使用任务自有的取消信号,而不是 `exec.signal`:之后取消外层调用只会停止等待本次调用,不会终止已经发布的工作;该生命周期归 `job_kill`、owner dispose 和服务 teardown 所有。前台工作仍与 `exec.signal` 耦合。流式 producer 的示例和完整约定见[后台任务运行时 Agent Note](../../.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md)与 `dsh-tool-bash`。
|
|
55
|
+
producer 提供同步的 `cancel`、在资源清理后 settle 且不 reject 的 `done`,以及可选的消费式 `readOutput`(负责有界输出的格式化)。预先中止的调用属于失败,因为此时没有任务,其 id 无法满足成功输出 schema。`ctx.jobs.start()` 发布 id 后,应使用任务自有的取消信号,而不是 `exec.signal`:之后取消外层调用只会停止等待本次调用,不会终止已经发布的工作;该生命周期归 `job_kill`、owner dispose 和服务 teardown 所有。前台工作仍与 `exec.signal` 耦合。流式 producer 的示例和完整约定见[后台任务运行时 Agent Note](../../.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md)与 `dsh-tool-bash`。
|
|
56
56
|
|
|
57
57
|
<a id="execution-policy-and-observation"></a>
|
|
58
58
|
|
|
59
59
|
## 执行策略与观测
|
|
60
60
|
|
|
61
|
-
尽量不要把部署策略内建到工具中。使用 `tools/pre-execute` 实现可扩展的允许/拒绝/询问策略(见[权限门禁示例](extension-cookbook.md#a-hook-plugin-permission-gate-example));使用 `ctx.tools.guard()` 设置最终的单调拒绝,后续监听器无法撤销;使用 `tools/execute` 为分发添加截止时间、重试或指标收集;使用 `tools/post-execute` 替换展示内容或返回值、阻止结果,或附加模型可见上下文;使用 `tools/result` 观测不可变的归一化结果而不改变它。替换内容不会阻止程序化访问 `value`;保密策略会屏蔽或替换该值。沙箱实现也可以在工具的执行器实现中运行;[`dsh-tools` README](../../packages/core/tools/README.md#extension-points) 定义每个扩展点的输入、顺序、返回值和失败行为。
|
|
61
|
+
尽量不要把部署策略内建到工具中。使用 `tools/pre-execute` 实现可扩展的允许/拒绝/询问策略(见[权限门禁示例](extension-cookbook.zh.md#a-hook-plugin-permission-gate-example));使用 `ctx.tools.guard()` 设置最终的单调拒绝,后续监听器无法撤销;使用 `tools/execute` 为分发添加截止时间、重试或指标收集;使用 `tools/post-execute` 替换展示内容或返回值、阻止结果,或附加模型可见上下文;使用 `tools/result` 观测不可变的归一化结果而不改变它。替换内容不会阻止程序化访问 `value`;保密策略会屏蔽或替换该值。沙箱实现也可以在工具的执行器实现中运行;[`dsh-tools` README](../../packages/core/tools/README.zh.md#extension-points) 定义每个扩展点的输入、顺序、返回值和失败行为。
|
|
62
62
|
|
|
63
|
-
##
|
|
63
|
+
## PTC mode 自动触达你的工具
|
|
64
64
|
|
|
65
|
-
在 [
|
|
65
|
+
在 [PTC mode](../../packages/core/tools/README.zh.md) 中,每个可见的已注册工具都可通过 `await tools.<name>(args)` 调用,无需额外集成。生成的 `ToolArgsMap` 和 `ToolOutputMap` 会根据同一组 schema 分别派生精确的参数类型与规范返回类型,调用则重新进入正常的执行流水线。成功调用会解析为策略处理后的最终规范 JSON 值,而不是渲染后的 Native 内容。失败调用会以真正的 `ToolCallError` reject;程序只能检查其 `name`、`toolName` 和可供人阅读的 `message`,无法取得内部错误代码或失败联合。
|
|
66
66
|
|
|
67
67
|
请把 `output.schema` 设计为实用的程序化 API:直接返回句柄与字段;当标量、数组或 null 确实就是结果时,允许采用相应的根类型;将面向人类的解释放入 `output.render`。中间值只存在于执行期间,不会被持久化或按提示词上限截断,也不设字节上限,因此生产方如实声明的采集边界和进程内存仍然重要。只有外层 `run_code` 日志/结果会受到可配置输出上限和面向模型的 spill 流水线约束。
|
|
68
68
|
|
|
@@ -80,6 +80,7 @@ producer 提供同步的 `cancel`、在资源清理后 settle 且不 reject 的
|
|
|
80
80
|
- `generic` 提供可选的标题和内容。
|
|
81
81
|
- `terminal` 提供原始输出和可选的退出元数据;各 UI 根据自身能力渲染对应视图或回退视图。
|
|
82
82
|
- `diff` 提供已应用的 hunk,通常由 `output.presentationMeta` 派生并通过持久化的 `result.meta` 携带,使回放能重现它们。变更类工具保留 diff 结果,因为完成后的视图会替换 pending 卡片。
|
|
83
|
+
- `read` 提供从持久化 `result.meta` 重建的已完成文件窗口:文件 `path`、从 1 开始的 `offset`、返回的 `lines`(每行保留其文件行号)、`totalLines`,以及可选的 `lang` 高亮提示;不具备 `read` 能力的 UI 回退到原始结果内容。没有 `read` 调用视图——读取调用的 pending 状态保持为 generic 卡片,因为内容只在 `execute` 之后才存在。(tool-fs `read`。)
|
|
83
84
|
- `search` 提供从持久化 `result.meta` 重建的发现型结果:按文件分组的匹配(`shape: 'matches'`,grep)或扁平路径列表(`shape: 'paths'`,glob),外加 `truncated`/`total` 使 UI 永不把被截断的结果当作完整结果呈现。该视图不携带结果文本(无 search 卡片的 UI 回退到原始结果内容),也没有 `search` 调用视图——发现型调用的 pending 状态保持为 generic 卡片,因为匹配只在 `execute` 之后才存在。(tool-fs-search 的 `grep`/`glob`。)
|
|
84
85
|
- `web` 提供已完成的 web 检索,以 `kind: 'search' | 'fetch'` 区分(结构化的搜索来源或抓取摘要),由 `result.meta` 派生;它不携带正文副本,因此不具备 `web` 能力的 UI 回退到原始结果内容。(tool-web `web_search`/`web_fetch`。)
|
|
85
86
|
|
|
@@ -89,8 +90,14 @@ producer 提供同步的 `cancel`、在资源清理后 settle 且不 reject 的
|
|
|
89
90
|
- **UI 格式不进入模型结果。** 围栏 ` ```console ` 块、diff、相对化路径均不应仅为服务 UI 而进入规范值或 Native 内容。`output.render` 负责模型可见的自然语言;`presentationMeta` 和卡片展示器负责可回放的 UI 状态。`terminal` 结果视图携带原始输出,由适配器按需添加回退格式。
|
|
90
91
|
- **`defineTool` 对展示路径做软校验。** 格式错误或旧版日志中的参数会使包装器返回 `undefined`(通用回退)而非抛异常——展示绝不能导致回放崩溃。
|
|
91
92
|
|
|
92
|
-
中性词汇定义在 `dsh-tools` 中;工具绝不导入 UI
|
|
93
|
+
中性词汇定义在 `dsh-tools` 中;工具绝不导入 UI 或传输类型。使用该 API 的消费方把每个 `card` 映射到自己的视图。设计与原因见[渲染意图联合体 Agent Note](../../.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.zh.md);`dsh-tool-fs`(generic/diff)和 `dsh-tool-bash`(terminal)是参考实现。
|
|
94
|
+
|
|
95
|
+
## Web Client 展示
|
|
96
|
+
|
|
97
|
+
内置 Web Client 不消费 `presentCall` 或 `presentResult`。Session `page` 与 `follow` 运输原始 `tool/call` 和 `tool/result` 事件,包括持久化的 `result.meta`。Client 插件在 keyed slot `tool.call.toolview` 中注册自己的 wire 工具名称,并从 `ToolCallBlock` 的参数、内容、错误、metadata、现有 Code Dispatch `parentCallId` 与 Session 路径事实派生组件 props。插件在本地校验这些 wire 值,并让格式错误或不受支持的输入回退到 generic 行。
|
|
98
|
+
|
|
99
|
+
现有 Web 卡片需要模型可见内容无法无损保存的有界结构化结果事实时,使用 `output.presentationMeta(args, value)`。不要在 metadata 中保存 React props 或预选卡片,不要把 Host 工具实现导入浏览器 bundle,也不要建立另一套 Client presenter registry。只定义 Host 展示方法不会增加专用 Web 卡片。[Client 派生展示 Agent Note](../../.agents/notes/implemented/architecture/2026-08-23-client-derived-tool-presentation.zh.md)规定 owner、fallback 与对等要求。
|
|
93
100
|
|
|
94
101
|
## 验证
|
|
95
102
|
|
|
96
|
-
遵循[仓库测试策略](../testing.md)和所属包的测试文档。已交付且面向模型或 UI 的变更必须提供其中规定的组装覆盖。
|
|
103
|
+
遵循[仓库测试策略](../testing.zh.md)和所属包的测试文档。已交付且面向模型或 UI 的变更必须提供其中规定的组装覆盖。
|
|
@@ -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/cookbook/adding-a-vendored-package.md
|
|
5
|
-
adding-a-vendored-package.md:
|
|
6
|
-
adding-a-vendored-package.zh.md:
|
|
5
|
+
adding-a-vendored-package.md: 5c0d9b22eac4db916cd1eab37c1e90690be40e3c
|
|
6
|
+
adding-a-vendored-package.zh.md: 274bd467ef9a969adccdd813fbe8cdb69cf2b475
|
|
@@ -8,7 +8,7 @@ When the harness needs another upstream Cordis package (e.g. `@cordisjs/plugin-h
|
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
vendor/<dir>/
|
|
11
|
-
package.json # from upstream;
|
|
11
|
+
package.json # from upstream; rescope the name, keep exports/type (publishable release member, no private flag)
|
|
12
12
|
tsconfig.json # extends ../../tsconfig.base.json (see configuration below)
|
|
13
13
|
src/ # the upstream src/ verbatim
|
|
14
14
|
README.md LICENSE # if upstream ships them
|
|
@@ -29,7 +29,7 @@ vendor/<dir>/
|
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
`package.json` invariants:
|
|
32
|
+
`package.json` invariants: rescope the `name` ([mapping](../rescope.md)) while keeping upstream's `exports`/`type`, point declaration metadata at `lib/types`, publish `.d.ts` and `.d.ts.map` declaration outputs, and list its cordis deps in `peerDependencies` (matching the upstream manifest). Vendored packages are publishable release members, so they must NOT set `private: true` and must set `publishConfig.access: public`; the `version` field follows the harness release sequence (see [vendor/README.md](../../vendor/README.md)). Transitive upstream deps must themselves be vendored or already present — vendoring one package often means vendoring its dependency tree (e.g. `@cordisjs/plugin-http` pulls `@cordisjs/fetch-file`).
|
|
33
33
|
|
|
34
34
|
Local relative imports/exports in vendored TypeScript source use explicit `.ts` specifiers after copying. This is a repo-local build difference from upstream: `rewriteRelativeImportExtensions` emits `.js` runtime imports while declarations keep explicit `.ts` specifiers that NodeNext/Node16 TypeScript consumers can resolve.
|
|
35
35
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[English](adding-a-vendored-package.md) | 中文
|
|
4
4
|
|
|
5
|
-
当 harness 需要引入另一个上游 Cordis 包(如 `@cordisjs/plugin-http`)时,应将其作为固定版本的源码 **vendor** 到 `vendor/` 下,而非作为 NPM 依赖添加——原因见[vendoring 决策](../../.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md)。[vendor/README.md](../../vendor/README.md) 介绍如何*更新*已有的 vendored 包;本指南是添加**新** vendored 包的逐文件清单。(已对照现有 vendored 集合验证;如有偏差,请在此修正。)
|
|
5
|
+
当 harness 需要引入另一个上游 Cordis 包(如 `@cordisjs/plugin-http`)时,应将其作为固定版本的源码 **vendor** 到 `vendor/` 下,而非作为 NPM 依赖添加——原因见[vendoring 决策](../../.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.zh.md)。[vendor/README.md](../../vendor/README.md) 介绍如何*更新*已有的 vendored 包;本指南是添加**新** vendored 包的逐文件清单。(已对照现有 vendored 集合验证;如有偏差,请在此修正。)
|
|
6
6
|
|
|
7
7
|
## 1. 复制源码
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
vendor/<dir>/
|
|
11
|
-
package.json # from upstream;
|
|
11
|
+
package.json # from upstream; rescope the name, keep exports/type (publishable release member, no private flag)
|
|
12
12
|
tsconfig.json # extends ../../tsconfig.base.json (see configuration below)
|
|
13
13
|
src/ # the upstream src/ verbatim
|
|
14
14
|
README.md LICENSE # if upstream ships them
|
|
@@ -29,7 +29,7 @@ vendor/<dir>/
|
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
`package.json`
|
|
32
|
+
`package.json` 的不变式:改写 `name` 的 scope([映射](../rescope.zh.md)),保留上游的 `exports`/`type`;声明元数据指向 `lib/types`;发布 `.d.ts` 与 `.d.ts.map` 声明输出;在 `peerDependencies` 中列出其 Cordis 依赖(与上游 manifest(元数据清单)一致)。vendored 包是可发布的 release member,因此不得设置 `private: true`,且必须设置 `publishConfig.access: public`;`version` 字段跟随 harness 发布序列(见 [vendor/README.md](../../vendor/README.md))。传递性上游依赖本身也必须被 vendor 或已存在于仓库中——vendor 一个包往往意味着 vendor 其整条依赖树(如 `@cordisjs/plugin-http` 会拉入 `@cordisjs/fetch-file`)。
|
|
33
33
|
|
|
34
34
|
vendored TypeScript 源码中的本地相对导入/导出在复制后使用显式 `.ts` 后缀。这是仓库本地构建与上游的差异:`rewriteRelativeImportExtensions` 输出 `.js` 运行时导入,而声明文件保留显式 `.ts` 后缀,使 NodeNext/Node16 的 TypeScript 消费方能够解析。
|
|
35
35
|
|
|
@@ -56,4 +56,4 @@ pnpm run typecheck
|
|
|
56
56
|
pnpm run build && pnpm run constraints
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
请运行[测试政策](../testing.md)所选择的行为检查。源码 `paths` 映射只在 `tsconfig.base.json` 存在一份,服务所有图。重要的隔离边界是 project-reference 图:vendored 源码必须通过其自身的 `vendor/<dir>/tsconfig.json` 被引用,而非被拉入某个聚合项目启用严格检查的 TypeScript 程序中([布局](../development.md#typescript-project-layout))。
|
|
59
|
+
请运行[测试政策](../testing.zh.md)所选择的行为检查。源码 `paths` 映射只在 `tsconfig.base.json` 存在一份,服务所有图。重要的隔离边界是 project-reference 图:vendored 源码必须通过其自身的 `vendor/<dir>/tsconfig.json` 被引用,而非被拉入某个聚合项目启用严格检查的 TypeScript 程序中([布局](../development.zh.md#typescript-project-layout))。
|
|
@@ -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/cookbook/adding-an-llm-adapter.md
|
|
5
|
-
adding-an-llm-adapter.md:
|
|
6
|
-
adding-an-llm-adapter.zh.md:
|
|
5
|
+
adding-an-llm-adapter.md: bbe4428155f2b2ed5279c5a159e9446f28068a5c
|
|
6
|
+
adding-an-llm-adapter.zh.md: 114745b7e07e807cbdd894ed69014455914ca68f
|
|
@@ -29,7 +29,7 @@ Registration is effect-based (HMR-safe); one adapter per provider route — dupl
|
|
|
29
29
|
- Allocate block `index`es in first-seen stream order; reuse the index for every delta of the same block.
|
|
30
30
|
- Errors have exactly two sanctioned paths: THROW from `stream()` (transport and protocol failures — use `LlmError` with a stable code), or end the stream with `finish {kind: 'error' | 'aborted'}` (provider in-band failures). Consumers handle both; pick per failure class and document it.
|
|
31
31
|
- Honor `options.signal` (pass it to fetch / your SDK).
|
|
32
|
-
- A `GenerateOptions` field your provider cannot honor (e.g. a `stop` list on a provider without stop sequences): throw `LlmError(..., '
|
|
32
|
+
- A `GenerateOptions` field your provider cannot honor (e.g. a `stop` list on a provider without stop sequences): throw `LlmError(..., 'UNSUPPORTED_OPTION')` rather than silently dropping it.
|
|
33
33
|
- If the provider requires response ids, signatures, or other native metadata on follow-up calls, emit the minimal lossless-JSON projection as `finish.replayState`. Validate it when rebuilding history. `LlmRuntime` passes it only when the historical provider route and target provider route are currently owned by the exact same adapter instance; your adapter decides whether same-model, cross-model, or cross-provider restoration is legal. Never infer native replay from provider/model names alone when state is absent.
|
|
34
34
|
|
|
35
35
|
Provider-specific thinking-mode toggles remain in the adapter's Config. Exact model metadata uses one provider-neutral capability seam: implement `resolveModel()` with provider/model identity and optional `context` and `reasoning` fields, declare a configured `defaultEffort` only when one exists, and honor the resolver's optional `AbortSignal`. Reasoning efforts are ordered opaque ids mapped to provider requests by the adapter. Preserve the adapter's authoritative selectable list, including an adapter-defined `off` when supported, without exposing final wire spellings or clamping unsupported values; an id need not equal its wire representation.
|
|
@@ -29,15 +29,15 @@ export function apply(ctx: Context, config: Config) {
|
|
|
29
29
|
- 按首次出现的流顺序分配块 `index`;同一个块的每次 delta 复用该 index。
|
|
30
30
|
- 错误有且仅有两条合法路径:从 `stream()` **抛出**(传输与协议故障——使用带稳定 code 的 `LlmError`),或以 `finish {kind: 'error' | 'aborted'}` 结束流(提供方带内故障)。消费方两者都处理;按故障类别选择路径并加以文档化。
|
|
31
31
|
- 遵守 `options.signal`(将其传递给 fetch 或你的 SDK)。
|
|
32
|
-
- 如果 `GenerateOptions` 中某个字段你的提供方无法支持(例如提供方不支持 stop sequences 时收到 `stop` 列表):抛出 `LlmError(..., '
|
|
32
|
+
- 如果 `GenerateOptions` 中某个字段你的提供方无法支持(例如提供方不支持 stop sequences 时收到 `stop` 列表):抛出 `LlmError(..., 'UNSUPPORTED_OPTION')`,而非静默丢弃。
|
|
33
33
|
- 如果提供方在后续调用中需要响应 ID、签名或其他原生元数据,请将其最小无损 JSON 投影作为 `finish.replayState` 发出。重建历史时验证该状态。只有历史提供方路由和目标提供方路由当前由完全相同的适配器实例拥有时,`LlmRuntime` 才会传递该状态;由适配器决定同模型、跨模型或跨提供方恢复是否合法。状态缺失时,切勿仅根据提供方/模型名称推断原生回放。
|
|
34
34
|
|
|
35
35
|
提供方特有的思考模式开关仍放在适配器的 Config 中。确切模型元数据使用一处提供方无关的能力 seam:实现 `resolveModel()`,返回提供方/模型身份以及可选的 `context` 和 `reasoning` 字段;仅当存在配置指定的默认值时才声明 `defaultEffort`;遵守解析模型时传入的可选 `AbortSignal`。推理(reasoning)强度是由适配器映射到提供方请求的有序不透明 ID。请保留适配器给出的权威可选列表,包括适配器在支持时定义的 `off`;不得暴露最终协议值的具体拼写,也不得自动调整不支持的值。ID 无需与其协议表示相同。
|
|
36
36
|
|
|
37
37
|
## 实现结构
|
|
38
38
|
|
|
39
|
-
让协议格式(wire format)类型、请求序列化、传输解析、分片转换和适配器类分别承担独立职责;[`llm-deepseek`](../../packages/llm/llm-deepseek/README.md) 是参考布局。
|
|
39
|
+
让协议格式(wire format)类型、请求序列化、传输解析、分片转换和适配器类分别承担独立职责;[`llm-deepseek`](../../packages/llm/llm-deepseek/README.zh.md) 是参考布局。
|
|
40
40
|
|
|
41
41
|
## 验证
|
|
42
42
|
|
|
43
|
-
遵循[仓库测试策略](../testing.md),该策略负责适配器覆盖、真实提供方检查和已发布入口要求。
|
|
43
|
+
遵循[仓库测试策略](../testing.zh.md),该策略负责适配器覆盖、真实提供方检查和已发布入口要求。
|
|
@@ -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/cookbook/extension-cookbook.md
|
|
5
|
-
extension-cookbook.md:
|
|
6
|
-
extension-cookbook.zh.md:
|
|
5
|
+
extension-cookbook.md: 0bbd1d0d531de755708da6c7a68b312675ba4b52
|
|
6
|
+
extension-cookbook.zh.md: 5067c57bef08af65102e011f6d4c4394e03a3f5f
|
|
@@ -30,16 +30,17 @@ export function apply(ctx: Context) {
|
|
|
30
30
|
}
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
This waterfall is the reorderable policy layer. Use `ctx.tools.guard()` when an invariant needs a monotonic final denial, `tools/execute` when a plugin must wrap the
|
|
33
|
+
This waterfall is the reorderable policy layer. Use `ctx.tools.guard()` when an invariant needs a monotonic final denial, `tools/execute` when a plugin must wrap the dispatch lifetime (timeouts/retries/metrics; only `exec.signal` is replaceable), `tools/post-execute` for explicit result transformation, and `tools/result` for contained observation of the immutable final outcome. The [adding-a-tool guide](adding-a-tool.md#execution-policy-and-observation) gives the selection rule.
|
|
34
34
|
|
|
35
35
|
## A UI plugin
|
|
36
36
|
|
|
37
|
-
A UI plugin renders from the `session/event` feed (the assistant token stream as `assistant/chunk`, plus turn/step boundaries and tool activity), and drives input back in via `agent.followup()` / `agent.steer()`. A browser plugin contributing a business row to the built-in Web Client instead registers a `ConversationNodeDefinition` and keyed Chat renderer; follow the [Conversation
|
|
37
|
+
A UI plugin renders from the `session/event` feed (the assistant token stream as `assistant/chunk`, plus turn/step boundaries and tool activity), and drives input back in via `agent.followup()` / `agent.steer()`. A browser plugin contributing a business row to the built-in Web Client instead registers a `ConversationNodeDefinition` and keyed Chat renderer; follow the [Conversation subsystem reference](../subsystems/conversation.md).
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
40
|
import type { Context } from '@deepseek-ai/cordis'
|
|
41
|
+
import { brandString } from '@deepseek-ai/dsh-brand'
|
|
41
42
|
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
|
42
|
-
import { SessionId } from '@deepseek-ai/dsh-session'
|
|
43
|
+
import type { SessionId } from '@deepseek-ai/dsh-session'
|
|
43
44
|
|
|
44
45
|
declare function render(text: string): void
|
|
45
46
|
declare function onUserInput(handler: (text: string) => void): void
|
|
@@ -53,7 +54,7 @@ export function apply(ctx: Context) {
|
|
|
53
54
|
render(event.data.chunk.text)
|
|
54
55
|
}
|
|
55
56
|
})
|
|
56
|
-
onUserInput(text => ctx.agents.get(SessionId('client-session'))?.followup(createUserMessage({
|
|
57
|
+
onUserInput(text => ctx.agents.get(brandString<SessionId>('client-session'))?.followup(createUserMessage({
|
|
57
58
|
content: [{ type: 'text', text }],
|
|
58
59
|
source: { kind: 'user' },
|
|
59
60
|
})))
|
|
@@ -90,13 +91,13 @@ export function apply(ctx: Context) {
|
|
|
90
91
|
|
|
91
92
|
## Runnable wirings
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
Shipped applications contribute profile layers through `packages/bundle/*/cordis.patch.yml`, and the product `dsh` launcher owns Web, ACP, SDK, and one-shot headless execution through named profiles. Optional user-facing overlays live under `apps/cli/config/examples/`; profile integration tests live under `apps/cli/tests/profiles/`, while package-specific Loader compositions stay with their package tests.
|
|
94
95
|
|
|
95
96
|
## The feature → mechanism map
|
|
96
97
|
|
|
97
98
|
Every product feature maps to a listener on a documented extension point — the microkernel claim made checkable ([microkernel Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md)). No row modifies the loop.
|
|
98
99
|
|
|
99
|
-
`system-prompt/assemble` is an expert cooperative whole-assembly transform: its returned assembly is authoritative, so listener authors own preserving active
|
|
100
|
+
`system-prompt/assemble` is an expert cooperative whole-assembly transform: its returned assembly is authoritative, so listener authors own preserving active PTC mode and structured-output protocol contributions. Prefer `ctx.tools.restrict()` for tool filtering that must stay aligned across presentation, lookup, and execution.
|
|
100
101
|
|
|
101
102
|
| Product feature | Plugin mechanism |
|
|
102
103
|
|---|---|
|
|
@@ -117,11 +118,11 @@ Every product feature maps to a listener on a documented extension point — the
|
|
|
117
118
|
| Subprocess sandbox (landlock / sandbox-exec) | use a `ctx.sandbox` backend through `dsh-bash-sandbox`; use `tools/pre-execute` for capability-level denial |
|
|
118
119
|
| Permission system / AskUserQuestion | return `ask` from `tools/pre-execute` and answer through `ctx.approval`; register a separate model-facing ask tool for ordinary user questions |
|
|
119
120
|
| Plan mode | [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md) — logged `plan/mode` state, the `plan:policy` guidance section, `/plan [message]` entry, `/plan off` direct exit, and the user-reviewed `exit_plan_mode` exit; enforcement stays on the independent sandbox/approval axes |
|
|
120
|
-
| Sub-agent delegation | the `ctx.subagents` provider registry (`dsh-subagent-spawn-in-process
|
|
121
|
+
| Sub-agent delegation | the `ctx.subagents` provider registry (`dsh-subagent-spawn-in-process`/`dsh-subagent-fork-in-process`/`dsh-subagent-acp`/`dsh-subagent-codex`/`dsh-subagent-claude-code`/`dsh-subagent-dsh-sdk`) + `dsh-tool-subagent` exposing one configured provider to the model |
|
|
121
122
|
| MCP | one plugin per server: discover tools → `ctx.tools.register()` |
|
|
122
123
|
| Skills | section + tool registration; `inject()` skill content on invocation |
|
|
123
124
|
| Memory | section provider + tool |
|
|
124
|
-
| Scheduled tasks (cron) | a plugin registers model-callable scheduling tools; timer fires → `followup(…, {source: {kind: '
|
|
125
|
+
| Scheduled tasks (cron) | a plugin registers model-callable scheduling tools; timer fires → `followup(…, {source: {kind: 'plugin', plugin: 'schedule'}})` when idle / `inject()` notification when busy |
|
|
125
126
|
| UI (GUI; CLI emits JSONL) | listen `session/event` (assistant chunks, boundaries, tool activity); input → `followup()` |
|
|
126
127
|
| Web Client Chat business node | register a `ConversationNodeDefinition` and `conversation.chat.node` keyed renderer |
|
|
127
128
|
| SessionTelemetryBackend / replayable trace | `session/event` → JSONL; replay = `sessions.create(id, { seed })` |
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
[English](extension-cookbook.md) | 中文
|
|
4
4
|
|
|
5
|
-
harness 扩展的参考模式。代码片段省略了 import 和辅助实现,无法直接复制运行。具体编写路径见[包检查清单](adding-a-package.md)、[第一个工具教程](../user/develop/basic/tool.md)、[工具参考](adding-a-tool.md)和 [LLM(大语言模型)适配器指南](adding-an-llm-adapter.md);系统与扩展点映射由[架构文档](../architecture.md)负责。
|
|
5
|
+
harness 扩展的参考模式。代码片段省略了 import 和辅助实现,无法直接复制运行。具体编写路径见[包检查清单](adding-a-package.zh.md)、[第一个工具教程](../user/develop/basic/tool.zh.md)、[工具参考](adding-a-tool.zh.md)和 [LLM(大语言模型)适配器指南](adding-an-llm-adapter.zh.md);系统与扩展点映射由[架构文档](../architecture.zh.md)负责。
|
|
6
6
|
|
|
7
7
|
## 工具插件
|
|
8
8
|
|
|
9
|
-
工具在 `ctx.tools` 上注册。带注解的 `defineTool` 示例(类型化的 `execute` 参数、结果构造、`run_in_background` 模式)见 [adding-a-tool.md](adding-a-tool.md)——该指南是工具定义的真源。`ctx.tools.register()` 也直接接受原始 JSON Schema `ToolDefinition`(MCP 来源的工具就是这样到达的);`defineTool` 是第一方工具使用的类型化辅助函数。
|
|
9
|
+
工具在 `ctx.tools` 上注册。带注解的 `defineTool` 示例(类型化的 `execute` 参数、结果构造、`run_in_background` 模式)见 [adding-a-tool.md](adding-a-tool.zh.md)——该指南是工具定义的真源。`ctx.tools.register()` 也直接接受原始 JSON Schema `ToolDefinition`(MCP 来源的工具就是这样到达的);`defineTool` 是第一方工具使用的类型化辅助函数。
|
|
10
10
|
|
|
11
11
|
<a id="a-hook-plugin-permission-gate-example"></a>
|
|
12
12
|
|
|
@@ -32,16 +32,17 @@ export function apply(ctx: Context) {
|
|
|
32
32
|
}
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
这个 waterfall(瀑布式事件)是可重排的策略层。当不变式需要单调的最终拒绝时使用 `ctx.tools.guard()
|
|
35
|
+
这个 waterfall(瀑布式事件)是可重排的策略层。当不变式需要单调的最终拒绝时使用 `ctx.tools.guard()`;当插件需要包裹分发生命周期时(超时/重试/指标;仅 `exec.signal` 可替换)使用 `tools/execute`;显式结果变换使用 `tools/post-execute`;对不可变最终结果的受限观察使用 `tools/result`。选择规则见[添加工具指南](adding-a-tool.zh.md#execution-policy-and-observation)。
|
|
36
36
|
|
|
37
37
|
## UI 插件
|
|
38
38
|
|
|
39
|
-
UI 插件从 `session/event` 事件流渲染(助手 token 流以 `assistant/chunk` 形式到达,加上轮次/步骤边界与工具活动),并通过 `agent.followup()` / `agent.steer()` 将输入驱动回去。如果浏览器插件要向内建 Web Client 贡献业务行,则应注册 `ConversationNodeDefinition` 与 keyed Chat renderer
|
|
39
|
+
UI 插件从 `session/event` 事件流渲染(助手 token 流以 `assistant/chunk` 形式到达,加上轮次/步骤边界与工具活动),并通过 `agent.followup()` / `agent.steer()` 将输入驱动回去。如果浏览器插件要向内建 Web Client 贡献业务行,则应注册 `ConversationNodeDefinition` 与 keyed Chat renderer;具体约定见 [Conversation 子系统参考](../subsystems/conversation.zh.md)。
|
|
40
40
|
|
|
41
41
|
```ts
|
|
42
42
|
import type { Context } from '@deepseek-ai/cordis'
|
|
43
|
+
import { brandString } from '@deepseek-ai/dsh-brand'
|
|
43
44
|
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
|
44
|
-
import { SessionId } from '@deepseek-ai/dsh-session'
|
|
45
|
+
import type { SessionId } from '@deepseek-ai/dsh-session'
|
|
45
46
|
|
|
46
47
|
declare function render(text: string): void
|
|
47
48
|
declare function onUserInput(handler: (text: string) => void): void
|
|
@@ -55,7 +56,7 @@ export function apply(ctx: Context) {
|
|
|
55
56
|
render(event.data.chunk.text)
|
|
56
57
|
}
|
|
57
58
|
})
|
|
58
|
-
onUserInput(text => ctx.agents.get(SessionId('client-session'))?.followup(createUserMessage({
|
|
59
|
+
onUserInput(text => ctx.agents.get(brandString<SessionId>('client-session'))?.followup(createUserMessage({
|
|
59
60
|
content: [{ type: 'text', text }],
|
|
60
61
|
source: { kind: 'user' },
|
|
61
62
|
})))
|
|
@@ -66,7 +67,7 @@ export function apply(ctx: Context) {
|
|
|
66
67
|
|
|
67
68
|
*协议驱动*将协议对端接入 `ctx.agents`;它可以服务于 UI 或自动化客户端。stdio 驱动拥有 stdout,通过工厂创建或恢复 agent(智能体),并将协议请求映射为 `followup()` 或 `cancel()`。底层提示词请求返回其持久入队回执;它不会通过关联 `MessageId` 与 `turn/end` 获得结果。整个 agent 的状态应单独发布。自动化方法可以从回执等待到下一次 idle,并概括这一显式拥有的区间;UI 通常则会持续观察开放式事件流。通过 `AgentHandle.dispose()` 拆除 agent,以使 dispose(资源释放)达到完全停稳。
|
|
68
69
|
|
|
69
|
-
[`packages/acp/acp`](../../packages/acp/acp) 是仅面向自动化的完整示例:它通过 ACP(Agent Client Protocol)JSON-RPC stdio 提供全新文本会话,发出已提交的助手文本,并为其拥有的 agent 注册一次性机器权限应答器。其 [README](../../packages/acp/acp/README.md) 定义确切的方法、事件顺序和生命周期约定。
|
|
70
|
+
[`packages/acp/acp`](../../packages/acp/acp) 是仅面向自动化的完整示例:它通过 ACP(Agent Client Protocol)JSON-RPC stdio 提供全新文本会话,发出已提交的助手文本,并为其拥有的 agent 注册一次性机器权限应答器。其 [README](../../packages/acp/acp/README.zh.md) 定义确切的方法、事件顺序和生命周期约定。
|
|
70
71
|
|
|
71
72
|
```ts
|
|
72
73
|
import type { Context } from '@deepseek-ai/cordis'
|
|
@@ -92,13 +93,15 @@ export function apply(ctx: Context) {
|
|
|
92
93
|
|
|
93
94
|
## 可运行的组装示例
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
交付应用通过 `packages/bundle/*/cordis.patch.yml` 提供 profile 层,产品 `dsh` 启动器通过具名 profile 负责 Web、ACP、SDK 与一次性 headless 执行。可选的用户 overlay 位于 `apps/cli/config/examples/`;profile 集成测试位于 `apps/cli/tests/profiles/`,包专属 Loader 组合则留在对应包的测试目录中。
|
|
97
|
+
|
|
98
|
+
<a id="the-feature--mechanism-map"></a>
|
|
96
99
|
|
|
97
100
|
## 功能→机制映射
|
|
98
101
|
|
|
99
|
-
每个产品功能都映射到一个文档化扩展点上的监听器——微内核声明由此可验证([微内核 Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md))。没有任何一行修改循环本身。
|
|
102
|
+
每个产品功能都映射到一个文档化扩展点上的监听器——微内核声明由此可验证([微内核 Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.zh.md))。没有任何一行修改循环本身。
|
|
100
103
|
|
|
101
|
-
`system-prompt/assemble` 是一个专家协作式的整体装配变换:其返回的装配结果具有权威性,因此监听器作者有责任保留活跃的
|
|
104
|
+
`system-prompt/assemble` 是一个专家协作式的整体装配变换:其返回的装配结果具有权威性,因此监听器作者有责任保留活跃的 PTC mode 和结构化输出协议的贡献。对于需要在展示、查找和执行之间保持对齐的工具过滤,优先使用 `ctx.tools.restrict()`。
|
|
102
105
|
|
|
103
106
|
| 产品功能 | 插件机制 |
|
|
104
107
|
|---|---|
|
|
@@ -107,7 +110,7 @@ export function apply(ctx: Context) {
|
|
|
107
110
|
| `/loop` | 在 `turn/end` 会话事件上 `followup()` 下一次迭代;或强制继续 |
|
|
108
111
|
| 动态工作流 | `ctx.workflowEngine` + worker-thread 引擎 + `workflow` 工具;结构化的进程内子任务通过作用域化的提示词/工具注册、单调工具守卫、最终 `tools/result` 提交(包括外层 `run_code`)和结构化输出执行的单调 `concludeTurn()` 标记来强制输出 |
|
|
109
112
|
| 排队消息 + steering | 核心 `Agent.followup()` / `Agent.steer()` |
|
|
110
|
-
| 上下文压缩(context compaction)(自动 + 手动) | `ctx.compaction` seam + `dsh-compaction-basic`;自动压力检查运行在串行 `agent/pre-step`,标准的溢出恢复机制运行在 `agent/request-error`,手动调用方使用同一个压缩服务([压缩 Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)) |
|
|
113
|
+
| 上下文压缩(context compaction)(自动 + 手动) | `ctx.compaction` seam + `dsh-compaction-basic`;自动压力检查运行在串行 `agent/pre-step`,标准的溢出恢复机制运行在 `agent/request-error`,手动调用方使用同一个压缩服务([压缩 Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md)) |
|
|
111
114
|
| 系统提示词可配置性 | `ctx.systemPrompt.section()`,支持排序与作用域局部覆盖 |
|
|
112
115
|
| AGENTS.md(根目录) | 一个读取该文件的 section 提供方 |
|
|
113
116
|
| AGENTS.md(子目录,按需触发)+ 文件变更通知 | 从 watcher / 工具结果监听器调用 `agent.inject()` |
|
|
@@ -118,12 +121,12 @@ export function apply(ctx: Context) {
|
|
|
118
121
|
| 单调终端轮次策略 | 从成功的终端工具调用 `ToolExecution.concludeTurn()`;同一响应中后续工具调用仍可由守卫阻止,循环在该步骤后停止 |
|
|
119
122
|
| 子进程沙箱(landlock / sandbox-exec) | 通过 `dsh-bash-sandbox` 使用 `ctx.sandbox` 后端;能力级别的拒绝使用 `tools/pre-execute` |
|
|
120
123
|
| 权限系统 / AskUserQuestion | 从 `tools/pre-execute` 返回 `ask` 并通过 `ctx.approval` 应答;为普通用户提问注册一个独立的面向模型的 ask 工具 |
|
|
121
|
-
| Plan mode | [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md):落日志的 `plan/mode` 状态、`plan:policy` 引导段、`/plan [message]` 入口、`/plan off` 直接退出,以及经用户评审的 `exit_plan_mode` 出口;强制约束留在独立的沙箱/审批轴上 |
|
|
122
|
-
| subagent 委派 | `ctx.subagents` 提供方注册表(`dsh-subagent-spawn-in-process
|
|
124
|
+
| Plan mode | [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.zh.md):落日志的 `plan/mode` 状态、`plan:policy` 引导段、`/plan [message]` 入口、`/plan off` 直接退出,以及经用户评审的 `exit_plan_mode` 出口;强制约束留在独立的沙箱/审批轴上 |
|
|
125
|
+
| subagent 委派 | `ctx.subagents` 提供方注册表(`dsh-subagent-spawn-in-process`/`dsh-subagent-fork-in-process`/`dsh-subagent-acp`/`dsh-subagent-codex`/`dsh-subagent-claude-code`/`dsh-subagent-dsh-sdk`)+ `dsh-tool-subagent` 向模型暴露一个已配置的提供方 |
|
|
123
126
|
| MCP | 每个服务器一个插件:发现工具 → `ctx.tools.register()` |
|
|
124
127
|
| skill(技能) | section + 工具注册;调用时通过 `inject()` 注入 skill 内容 |
|
|
125
128
|
| 记忆 | section 提供方 + 工具 |
|
|
126
|
-
| 定时任务(cron) | 插件注册面向模型的调度工具;定时器触发 → 空闲时 `followup(…, {source: {kind: '
|
|
129
|
+
| 定时任务(cron) | 插件注册面向模型的调度工具;定时器触发 → 空闲时 `followup(…, {source: {kind: 'plugin', plugin: 'schedule'}})`/忙碌时 `inject()` 通知 |
|
|
127
130
|
| UI(GUI;CLI(命令行界面)输出 JSONL) | 监听 `session/event`(助手分片、边界、工具活动);输入 → `followup()` |
|
|
128
131
|
| Web Client Chat 业务节点 | 注册 `ConversationNodeDefinition` 与 `conversation.chat.node` keyed renderer |
|
|
129
132
|
| 遥测 / 可回放 trace | `session/event` → JSONL;回放 = `sessions.create(id, { seed })` |
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write docs/cookbook/maintaining-dsh-code-review.md
|
|
5
5
|
maintaining-dsh-code-review.md: a8c2a66c065aaec5c03f0ab6965377d1d1eb14bd
|
|
6
|
-
maintaining-dsh-code-review.zh.md:
|
|
6
|
+
maintaining-dsh-code-review.zh.md: fca56ffeb35309660ac5284cb8e877eb8648405a
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](maintaining-dsh-code-review.md) | 中文
|
|
4
4
|
|
|
5
|
-
[`dsh-code-review`](../../.agents/skills/dsh-code-review/SKILL.md) skill(技能)由一名指定操作员通过私有的周期维护工具持续更新。本实操手册既是该操作员和接任者的入口,也帮助仓库贡献者理解为何 skill 更新会以小型周期 PR(Pull Request)的形式出现,而不是一次性审计。工作流本身由[人工评审 skill 维护 Agent Note](../../.agents/notes/proposed/process/2026-07-13-human-review-skill-maintenance.md)规定。
|
|
5
|
+
[`dsh-code-review`](../../.agents/skills/dsh-code-review/SKILL.md) skill(技能)由一名指定操作员通过私有的周期维护工具持续更新。本实操手册既是该操作员和接任者的入口,也帮助仓库贡献者理解为何 skill 更新会以小型周期 PR(Pull Request)的形式出现,而不是一次性审计。工作流本身由[人工评审 skill 维护 Agent Note](../../.agents/notes/proposed/process/2026-07-13-human-review-skill-maintenance.zh.md)规定。
|
|
6
6
|
|
|
7
7
|
## 维护者会收到什么
|
|
8
8
|
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write docs/cookbook/responding-to-pr-review-on-a-stack.md
|
|
5
5
|
responding-to-pr-review-on-a-stack.md: 6bb7be3daf8613666f02f21e96bf7b1ac8cb3606
|
|
6
|
-
responding-to-pr-review-on-a-stack.zh.md:
|
|
6
|
+
responding-to-pr-review-on-a-stack.zh.md: ca030741ece4c729fe21c3944d291ee4c322dcbb
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
1. 在行动之前先就事论事地审视每条评论:对照代码验证其论断——评审者指出了正确的症状,但仍可能误诊原因。
|
|
18
18
|
2. 将每个被接受的发现映射到引入该问题的 PR,并在那里修复。
|
|
19
19
|
3. 将修复后的层按顺序传播到每个受影响的子 PR:
|
|
20
|
-
- **Merge-forward:** 将修复后的父分支合并到其子分支,验证子分支,然后继续沿堆叠向上传播。依照[增量更新 base 的决策](../../.agents/notes/implemented/process/2026-07-26-incremental-pr-base-retargeting.md),保留每个正在处理的检查点。
|
|
20
|
+
- **Merge-forward:** 将修复后的父分支合并到其子分支,验证子分支,然后继续沿堆叠向上传播。依照[增量更新 base 的决策](../../.agents/notes/implemented/process/2026-07-26-incremental-pr-base-retargeting.zh.md),保留每个正在处理的检查点。
|
|
21
21
|
- **原生级联 rebase:** 使用 `gh stack rebase`,验证所有已改写的层,然后通过 `gh stack push` 发布;也可以使用 `gh stack sync`,该命令可能先发布,因此必须按照 [dsh-pre-push-checks](../../.agents/skills/dsh-pre-push-checks/SKILL.md) 在同步后立即验证。
|
|
22
22
|
4. 委派的修复需要信任但验证:subagent 的报告描述的是意图,不一定是实际落地的内容。请亲自在实际代码树上重新运行门禁;对于回归守卫,要证明它在未修复的代码上**失败**(引入回归、观察变红、再还原)——两种情况都通过的守卫什么也守不住。subagent 将问题重新定性为「已处理」时,这是一个需要亲自深入的信号。
|
|
23
23
|
5. 在评审线程中回复(`gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies`),而非发顶层评论;说明修复内容及当前承载修复的 commit 或 head。
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write docs/cordis-api/context.md
|
|
5
5
|
context.md: 320b23de1c8d19e2dacdf0ec9f2361037bcf8048
|
|
6
|
-
context.zh.md:
|
|
6
|
+
context.zh.md: b97fe51eb8afdd5c2235ac9cf8586c3ff68830d4
|