dsh-plugin-guide 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE.md +26 -0
- package/README.es.md +139 -0
- package/README.hi.md +138 -0
- package/README.md +165 -0
- package/README.pt.md +139 -0
- package/README.zh-CN.md +164 -0
- package/SKILL.md +69 -0
- package/cordis.patch.yml +4 -0
- package/guide/links.md +92 -0
- package/guide/plugin-dev-guide.md +429 -0
- package/guide/quick-reference.es.md +176 -0
- package/guide/quick-reference.hi.md +176 -0
- package/guide/quick-reference.md +176 -0
- package/guide/quick-reference.pt.md +176 -0
- package/guide/quick-reference.zh-CN.md +175 -0
- package/index.js +58 -0
- package/package.json +83 -0
- package/references/community-ecosystem.md +201 -0
- package/references/community-repo-deep-dive.md +695 -0
- package/references/cordis-paper-and-community.md +326 -0
- package/references/harness-repo.md +654 -0
- package/references/official-docs/AGENTS.md +149 -0
- package/references/official-docs/BENCHMARK.md +3 -0
- package/references/official-docs/CLAUDE.md +1 -0
- package/references/official-docs/CONTRIBUTING.i18n.yaml +6 -0
- package/references/official-docs/CONTRIBUTING.md +23 -0
- package/references/official-docs/CONTRIBUTING.zh.md +23 -0
- package/references/official-docs/LICENSE +21 -0
- package/references/official-docs/README.i18n.yaml +6 -0
- package/references/official-docs/README.md +35 -0
- package/references/official-docs/README.zh.md +74 -0
- package/references/official-docs/SNAPSHOT.md +16 -0
- package/references/official-docs/THIRD_PARTY_NOTICES.md +192 -0
- package/references/official-docs/docs/AGENTS.md +75 -0
- package/references/official-docs/docs/agent-lifecycle.i18n.yaml +6 -0
- package/references/official-docs/docs/agent-lifecycle.md +82 -0
- package/references/official-docs/docs/agent-lifecycle.zh.md +84 -0
- package/references/official-docs/docs/api-gateway.i18n.yaml +6 -0
- package/references/official-docs/docs/api-gateway.md +164 -0
- package/references/official-docs/docs/api-gateway.zh.md +164 -0
- package/references/official-docs/docs/architecture.i18n.yaml +6 -0
- package/references/official-docs/docs/architecture.md +129 -0
- package/references/official-docs/docs/architecture.zh.md +133 -0
- package/references/official-docs/docs/capability-seams.i18n.yaml +6 -0
- package/references/official-docs/docs/capability-seams.md +471 -0
- package/references/official-docs/docs/capability-seams.zh.md +473 -0
- package/references/official-docs/docs/config-catalog.i18n.yaml +6 -0
- package/references/official-docs/docs/config-catalog.md +3151 -0
- package/references/official-docs/docs/config-catalog.zh.md +3152 -0
- package/references/official-docs/docs/cookbook/adding-a-conversation-node.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/adding-a-conversation-node.md +233 -0
- package/references/official-docs/docs/cookbook/adding-a-conversation-node.zh.md +233 -0
- package/references/official-docs/docs/cookbook/adding-a-package.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/adding-a-package.md +118 -0
- package/references/official-docs/docs/cookbook/adding-a-package.zh.md +118 -0
- package/references/official-docs/docs/cookbook/adding-a-tool.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/adding-a-tool.md +94 -0
- package/references/official-docs/docs/cookbook/adding-a-tool.zh.md +96 -0
- package/references/official-docs/docs/cookbook/adding-a-vendored-package.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/adding-a-vendored-package.md +59 -0
- package/references/official-docs/docs/cookbook/adding-a-vendored-package.zh.md +59 -0
- package/references/official-docs/docs/cookbook/adding-an-llm-adapter.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/adding-an-llm-adapter.md +43 -0
- package/references/official-docs/docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
- package/references/official-docs/docs/cookbook/extension-cookbook.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/extension-cookbook.md +129 -0
- package/references/official-docs/docs/cookbook/extension-cookbook.zh.md +131 -0
- package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.md +64 -0
- package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
- package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.i18n.yaml +6 -0
- package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
- package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
- package/references/official-docs/docs/cordis-api/context.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-api/context.md +364 -0
- package/references/official-docs/docs/cordis-api/context.zh.md +366 -0
- package/references/official-docs/docs/cordis-api/events.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-api/events.md +207 -0
- package/references/official-docs/docs/cordis-api/events.zh.md +209 -0
- package/references/official-docs/docs/cordis-api/fiber.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-api/fiber.md +375 -0
- package/references/official-docs/docs/cordis-api/fiber.zh.md +377 -0
- package/references/official-docs/docs/cordis-api/inherited.md +39 -0
- package/references/official-docs/docs/cordis-api/registry.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-api/registry.md +152 -0
- package/references/official-docs/docs/cordis-api/registry.zh.md +154 -0
- package/references/official-docs/docs/cordis-api/service.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-api/service.md +102 -0
- package/references/official-docs/docs/cordis-api/service.zh.md +104 -0
- package/references/official-docs/docs/cordis-primer.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-primer.md +44 -0
- package/references/official-docs/docs/cordis-primer.zh.md +50 -0
- package/references/official-docs/docs/cordis-tutorial/01-first-plugin.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/01-first-plugin.md +95 -0
- package/references/official-docs/docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
- package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
- package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
- package/references/official-docs/docs/cordis-tutorial/03-services.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/03-services.md +98 -0
- package/references/official-docs/docs/cordis-tutorial/03-services.zh.md +98 -0
- package/references/official-docs/docs/cordis-tutorial/04-events.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/04-events.md +144 -0
- package/references/official-docs/docs/cordis-tutorial/04-events.zh.md +144 -0
- package/references/official-docs/docs/cordis-tutorial/05-config.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/05-config.md +84 -0
- package/references/official-docs/docs/cordis-tutorial/05-config.zh.md +84 -0
- package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
- package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
- package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.md +107 -0
- package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.zh.md +107 -0
- package/references/official-docs/docs/cordis-tutorial/index.i18n.yaml +6 -0
- package/references/official-docs/docs/cordis-tutorial/index.md +60 -0
- package/references/official-docs/docs/cordis-tutorial/index.zh.md +62 -0
- package/references/official-docs/docs/defensive-patterns.i18n.yaml +6 -0
- package/references/official-docs/docs/defensive-patterns.md +33 -0
- package/references/official-docs/docs/defensive-patterns.zh.md +33 -0
- package/references/official-docs/docs/development.i18n.yaml +6 -0
- package/references/official-docs/docs/development.md +171 -0
- package/references/official-docs/docs/development.zh.md +171 -0
- package/references/official-docs/docs/event-producer-consumer.i18n.yaml +6 -0
- package/references/official-docs/docs/event-producer-consumer.md +76 -0
- package/references/official-docs/docs/event-producer-consumer.zh.md +78 -0
- package/references/official-docs/docs/glossary.i18n.yaml +6 -0
- package/references/official-docs/docs/glossary.md +45 -0
- package/references/official-docs/docs/glossary.zh.md +45 -0
- package/references/official-docs/docs/graph-atlas.i18n.yaml +6 -0
- package/references/official-docs/docs/graph-atlas.md +24 -0
- package/references/official-docs/docs/graph-atlas.zh.md +26 -0
- package/references/official-docs/docs/i18n/README.i18n.yaml +6 -0
- package/references/official-docs/docs/i18n/README.md +60 -0
- package/references/official-docs/docs/i18n/README.zh.md +60 -0
- package/references/official-docs/docs/i18n/style-samples.md +87 -0
- package/references/official-docs/docs/i18n/terminology.md +214 -0
- package/references/official-docs/docs/i18n/translation-prompt.md +263 -0
- package/references/official-docs/docs/i18n/translation-rules.i18n.yaml +6 -0
- package/references/official-docs/docs/i18n/translation-rules.md +69 -0
- package/references/official-docs/docs/i18n/translation-rules.zh.md +69 -0
- package/references/official-docs/docs/module-graph.i18n.yaml +6 -0
- package/references/official-docs/docs/module-graph.md +1638 -0
- package/references/official-docs/docs/module-graph.zh.md +1640 -0
- package/references/official-docs/docs/persistence-catalog.i18n.yaml +6 -0
- package/references/official-docs/docs/persistence-catalog.md +944 -0
- package/references/official-docs/docs/persistence-catalog.zh.md +946 -0
- package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.i18n.yaml +6 -0
- package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
- package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
- package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.i18n.yaml +6 -0
- package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
- package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
- package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.i18n.yaml +6 -0
- package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
- package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
- package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.i18n.yaml +6 -0
- package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
- package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
- package/references/official-docs/docs/postmortem/README.i18n.yaml +6 -0
- package/references/official-docs/docs/postmortem/README.md +18 -0
- package/references/official-docs/docs/postmortem/README.zh.md +18 -0
- package/references/official-docs/docs/rescope.i18n.yaml +6 -0
- package/references/official-docs/docs/rescope.md +53 -0
- package/references/official-docs/docs/rescope.zh.md +53 -0
- package/references/official-docs/docs/subsystems/README.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/README.md +55 -0
- package/references/official-docs/docs/subsystems/README.zh.md +55 -0
- package/references/official-docs/docs/subsystems/approval.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/approval.md +170 -0
- package/references/official-docs/docs/subsystems/approval.zh.md +170 -0
- package/references/official-docs/docs/subsystems/attachment.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/attachment.md +115 -0
- package/references/official-docs/docs/subsystems/attachment.zh.md +115 -0
- package/references/official-docs/docs/subsystems/client-modules.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/client-modules.md +118 -0
- package/references/official-docs/docs/subsystems/client-modules.zh.md +118 -0
- package/references/official-docs/docs/subsystems/code-runtime.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/code-runtime.md +191 -0
- package/references/official-docs/docs/subsystems/code-runtime.zh.md +191 -0
- package/references/official-docs/docs/subsystems/commands.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/commands.md +187 -0
- package/references/official-docs/docs/subsystems/commands.zh.md +187 -0
- package/references/official-docs/docs/subsystems/compaction.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/compaction.md +238 -0
- package/references/official-docs/docs/subsystems/compaction.zh.md +238 -0
- package/references/official-docs/docs/subsystems/core.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/core.md +1070 -0
- package/references/official-docs/docs/subsystems/core.zh.md +1078 -0
- package/references/official-docs/docs/subsystems/credentials.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/credentials.md +133 -0
- package/references/official-docs/docs/subsystems/credentials.zh.md +133 -0
- package/references/official-docs/docs/subsystems/extensions.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/extensions.md +364 -0
- package/references/official-docs/docs/subsystems/extensions.zh.md +364 -0
- package/references/official-docs/docs/subsystems/feedback.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/feedback.md +266 -0
- package/references/official-docs/docs/subsystems/feedback.zh.md +266 -0
- package/references/official-docs/docs/subsystems/filesystem.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/filesystem.md +495 -0
- package/references/official-docs/docs/subsystems/filesystem.zh.md +495 -0
- package/references/official-docs/docs/subsystems/goal.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/goal.md +277 -0
- package/references/official-docs/docs/subsystems/goal.zh.md +277 -0
- package/references/official-docs/docs/subsystems/invariants.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/invariants.md +88 -0
- package/references/official-docs/docs/subsystems/invariants.zh.md +88 -0
- package/references/official-docs/docs/subsystems/jobs.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/jobs.md +290 -0
- package/references/official-docs/docs/subsystems/jobs.zh.md +290 -0
- package/references/official-docs/docs/subsystems/llm-streaming.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/llm-streaming.md +888 -0
- package/references/official-docs/docs/subsystems/llm-streaming.zh.md +894 -0
- package/references/official-docs/docs/subsystems/lsp.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/lsp.md +202 -0
- package/references/official-docs/docs/subsystems/lsp.zh.md +202 -0
- package/references/official-docs/docs/subsystems/permission-presets.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/permission-presets.md +131 -0
- package/references/official-docs/docs/subsystems/permission-presets.zh.md +131 -0
- package/references/official-docs/docs/subsystems/persistence.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/persistence.md +385 -0
- package/references/official-docs/docs/subsystems/persistence.zh.md +385 -0
- package/references/official-docs/docs/subsystems/plan.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/plan.md +87 -0
- package/references/official-docs/docs/subsystems/plan.zh.md +87 -0
- package/references/official-docs/docs/subsystems/sandbox.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/sandbox.md +218 -0
- package/references/official-docs/docs/subsystems/sandbox.zh.md +218 -0
- package/references/official-docs/docs/subsystems/schedule.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/schedule.md +186 -0
- package/references/official-docs/docs/subsystems/schedule.zh.md +186 -0
- package/references/official-docs/docs/subsystems/scope.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/scope.md +59 -0
- package/references/official-docs/docs/subsystems/scope.zh.md +59 -0
- package/references/official-docs/docs/subsystems/session-projection.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/session-projection.md +262 -0
- package/references/official-docs/docs/subsystems/session-projection.zh.md +262 -0
- package/references/official-docs/docs/subsystems/session-query.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/session-query.md +495 -0
- package/references/official-docs/docs/subsystems/session-query.zh.md +495 -0
- package/references/official-docs/docs/subsystems/session-reference.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/session-reference.md +108 -0
- package/references/official-docs/docs/subsystems/session-reference.zh.md +108 -0
- package/references/official-docs/docs/subsystems/session-telemetry.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/session-telemetry.md +194 -0
- package/references/official-docs/docs/subsystems/session-telemetry.zh.md +194 -0
- package/references/official-docs/docs/subsystems/session-title.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/session-title.md +204 -0
- package/references/official-docs/docs/subsystems/session-title.zh.md +204 -0
- package/references/official-docs/docs/subsystems/session.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/session.md +849 -0
- package/references/official-docs/docs/subsystems/session.zh.md +851 -0
- package/references/official-docs/docs/subsystems/settings.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/settings.md +310 -0
- package/references/official-docs/docs/subsystems/settings.zh.md +310 -0
- package/references/official-docs/docs/subsystems/shell.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/shell.md +303 -0
- package/references/official-docs/docs/subsystems/shell.zh.md +303 -0
- package/references/official-docs/docs/subsystems/skills.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/skills.md +331 -0
- package/references/official-docs/docs/subsystems/skills.zh.md +331 -0
- package/references/official-docs/docs/subsystems/spill.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/spill.md +117 -0
- package/references/official-docs/docs/subsystems/spill.zh.md +117 -0
- package/references/official-docs/docs/subsystems/storage.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/storage.md +229 -0
- package/references/official-docs/docs/subsystems/storage.zh.md +229 -0
- package/references/official-docs/docs/subsystems/subagent.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/subagent.md +734 -0
- package/references/official-docs/docs/subsystems/subagent.zh.md +736 -0
- package/references/official-docs/docs/subsystems/subprocess.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/subprocess.md +324 -0
- package/references/official-docs/docs/subsystems/subprocess.zh.md +324 -0
- package/references/official-docs/docs/subsystems/system-prompt.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/system-prompt.md +207 -0
- package/references/official-docs/docs/subsystems/system-prompt.zh.md +207 -0
- package/references/official-docs/docs/subsystems/terminal.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/terminal.md +184 -0
- package/references/official-docs/docs/subsystems/terminal.zh.md +184 -0
- package/references/official-docs/docs/subsystems/token-meter.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/token-meter.md +90 -0
- package/references/official-docs/docs/subsystems/token-meter.zh.md +90 -0
- package/references/official-docs/docs/subsystems/tools.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/tools.md +720 -0
- package/references/official-docs/docs/subsystems/tools.zh.md +720 -0
- package/references/official-docs/docs/subsystems/typert.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/typert.md +336 -0
- package/references/official-docs/docs/subsystems/typert.zh.md +336 -0
- package/references/official-docs/docs/subsystems/user-questions.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/user-questions.md +178 -0
- package/references/official-docs/docs/subsystems/user-questions.zh.md +178 -0
- package/references/official-docs/docs/subsystems/web-server.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/web-server.md +108 -0
- package/references/official-docs/docs/subsystems/web-server.zh.md +108 -0
- package/references/official-docs/docs/subsystems/web.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/web.md +199 -0
- package/references/official-docs/docs/subsystems/web.zh.md +199 -0
- package/references/official-docs/docs/subsystems/workflow.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/workflow.md +278 -0
- package/references/official-docs/docs/subsystems/workflow.zh.md +278 -0
- package/references/official-docs/docs/subsystems/workspace.i18n.yaml +6 -0
- package/references/official-docs/docs/subsystems/workspace.md +228 -0
- package/references/official-docs/docs/subsystems/workspace.zh.md +228 -0
- package/references/official-docs/docs/testing.i18n.yaml +6 -0
- package/references/official-docs/docs/testing.md +49 -0
- package/references/official-docs/docs/testing.zh.md +49 -0
- package/references/official-docs/docs/tool-catalog.i18n.yaml +6 -0
- package/references/official-docs/docs/tool-catalog.md +1873 -0
- package/references/official-docs/docs/tool-catalog.zh.md +1878 -0
- package/references/official-docs/docs/tool-execution-pipeline.i18n.yaml +6 -0
- package/references/official-docs/docs/tool-execution-pipeline.md +62 -0
- package/references/official-docs/docs/tool-execution-pipeline.zh.md +64 -0
- package/references/official-docs/docs/user/develop/basic/config.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/basic/config.md +106 -0
- package/references/official-docs/docs/user/develop/basic/config.zh.md +106 -0
- package/references/official-docs/docs/user/develop/basic/index.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/basic/index.md +144 -0
- package/references/official-docs/docs/user/develop/basic/index.zh.md +144 -0
- package/references/official-docs/docs/user/develop/basic/publish.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/basic/publish.md +183 -0
- package/references/official-docs/docs/user/develop/basic/publish.zh.md +183 -0
- package/references/official-docs/docs/user/develop/basic/tool.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/basic/tool.md +52 -0
- package/references/official-docs/docs/user/develop/basic/tool.zh.md +52 -0
- package/references/official-docs/docs/user/develop/framework/events.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/framework/events.md +143 -0
- package/references/official-docs/docs/user/develop/framework/events.zh.md +143 -0
- package/references/official-docs/docs/user/develop/framework/index.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/framework/index.md +137 -0
- package/references/official-docs/docs/user/develop/framework/index.zh.md +137 -0
- package/references/official-docs/docs/user/develop/framework/service.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/framework/service.md +148 -0
- package/references/official-docs/docs/user/develop/framework/service.zh.md +150 -0
- package/references/official-docs/docs/user/develop/practice/index.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/practice/index.md +155 -0
- package/references/official-docs/docs/user/develop/practice/index.zh.md +155 -0
- package/references/official-docs/docs/user/develop/practice/llm-adapter.i18n.yaml +6 -0
- package/references/official-docs/docs/user/develop/practice/llm-adapter.md +188 -0
- package/references/official-docs/docs/user/develop/practice/llm-adapter.zh.md +188 -0
- package/references/official-docs/docs/user/guide/index.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/index.md +30 -0
- package/references/official-docs/docs/user/guide/index.zh.md +30 -0
- package/references/official-docs/docs/user/guide/providers-custom-form.png +0 -0
- package/references/official-docs/docs/user/guide/providers-custom-form.zh.png +0 -0
- package/references/official-docs/docs/user/guide/providers-models-page.png +0 -0
- package/references/official-docs/docs/user/guide/providers-models-page.zh.png +0 -0
- package/references/official-docs/docs/user/guide/providers.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/providers.md +98 -0
- package/references/official-docs/docs/user/guide/providers.zh.md +98 -0
- package/references/official-docs/docs/user/guide/python-sdk.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/python-sdk.md +104 -0
- package/references/official-docs/docs/user/guide/python-sdk.zh.md +104 -0
- package/references/official-docs/docs/user/index.i18n.yaml +6 -0
- package/references/official-docs/docs/user/index.md +11 -0
- package/references/official-docs/docs/user/index.zh.md +11 -0
- package/references/official-docs/docs/web-styling.i18n.yaml +6 -0
- package/references/official-docs/docs/web-styling.md +25 -0
- package/references/official-docs/docs/web-styling.zh.md +25 -0
- package/references/official-docs/examples/AGENTS.md +20 -0
- package/references/official-docs/packages/AGENTS.md +27 -0
- package/references/official-docs/packages/README.md +69 -0
- package/references/official-docs/vendor/README.md +60 -0
- package/references/official-docs/website-docs.ts +524 -0
- package/references/sources.md +137 -0
- package/references/upstream-cordis.md +594 -0
- package/references/website-pages.md +668 -0
- package/scripts/archive-discussions.ps1 +154 -0
- package/scripts/download-community-articles.ps1 +188 -0
- package/scripts/download-community-repos.ps1 +232 -0
- package/scripts/download-sources.ps1 +195 -0
- package/scripts/gen-topic-snapshot.ps1 +91 -0
- package/scripts/install-skill.ps1 +63 -0
- package/scripts/sync-official-docs.ps1 +130 -0
- package/scripts/verify-kit.ps1 +191 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# 4. 事件
|
|
2
|
+
|
|
3
|
+
[English](04-events.md) | 中文
|
|
4
|
+
|
|
5
|
+
服务支持直接调用;**事件**让插件无需知道有哪些插件正在监听,就能发出通知。harness 使用事件处理工具结果、模型请求和审批决定等交互。
|
|
6
|
+
|
|
7
|
+
## 声明、发出与监听
|
|
8
|
+
|
|
9
|
+
创建 `stats.ts`,将它放在 `tmp/cordis-tutorial` 中。它是一项负责计数并在每次变化时发出通知的服务:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { Service, type Context } from '@deepseek-ai/cordis'
|
|
13
|
+
|
|
14
|
+
declare module '@deepseek-ai/cordis' {
|
|
15
|
+
interface Context {
|
|
16
|
+
stats: StatsService
|
|
17
|
+
}
|
|
18
|
+
interface Events {
|
|
19
|
+
'stats/report'(name: string, count: number): void
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class StatsService extends Service {
|
|
24
|
+
private counts = new Map<string, number>()
|
|
25
|
+
|
|
26
|
+
constructor(ctx: Context) {
|
|
27
|
+
super(ctx, 'stats')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
bump(name: string) {
|
|
31
|
+
const next = (this.counts.get(name) ?? 0) + 1
|
|
32
|
+
this.counts.set(name, next)
|
|
33
|
+
this.ctx.emit('stats/report', name, next)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const name = 'stats'
|
|
38
|
+
|
|
39
|
+
export function apply(ctx: Context) {
|
|
40
|
+
ctx.plugin(StatsService)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`interface Events` 合并与第 3 章的 `interface Context` 合并在事件系统中相互对应:它声明事件名称及其监听器签名,因此 `ctx.emit` 和 `ctx.on` 都具有完整类型。`namespace/action` 命名约定让扁平的事件命名空间保持易读。
|
|
45
|
+
|
|
46
|
+
创建 `reporter.ts`:
|
|
47
|
+
|
|
48
|
+
```ts ignore-check
|
|
49
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
50
|
+
import type {} from './stats.ts'
|
|
51
|
+
|
|
52
|
+
export const name = 'reporter'
|
|
53
|
+
export const inject = ['stats']
|
|
54
|
+
|
|
55
|
+
export function apply(ctx: Context) {
|
|
56
|
+
ctx.on('stats/report', (name, count) => {
|
|
57
|
+
console.log(`[stats] ${name} -> ${count}`)
|
|
58
|
+
})
|
|
59
|
+
ctx.stats.bump('tool_call')
|
|
60
|
+
ctx.stats.bump('tool_call')
|
|
61
|
+
ctx.stats.bump('prompt')
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`import type {} from './stats.ts'` 行不会在运行时导入任何内容;它的作用是让 TypeScript 看到声明合并。组合并运行:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
- name: './stats.ts'
|
|
69
|
+
- name: './reporter.ts'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
[stats] tool_call -> 1
|
|
74
|
+
[stats] tool_call -> 2
|
|
75
|
+
[stats] prompt -> 1
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
因为 `ctx.on()` 属于 effect,监听器会随插件一同消失,绝不需要手动维护 `removeListener`。
|
|
79
|
+
|
|
80
|
+
## 分发模式
|
|
81
|
+
|
|
82
|
+
`emit` 是 5 种分发模式之一。事件采用哪种模式是其约定的一部分,决定了监听器能否返回值、能否并发运行,以及能否彼此短路:
|
|
83
|
+
|
|
84
|
+
| 模式 | 调用 | 语义 |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| emit | `ctx.emit(name, ...args)` | 同步广播;不会等待或收集返回的 promise 与值。 |
|
|
87
|
+
| parallel | `await ctx.parallel(name, ...args)` | 所有监听器并发运行,并一同等待。 |
|
|
88
|
+
| serial | `await ctx.serial(name, ...args)` | 监听器按顺序运行并等待;第一个非 `null`/`false`/`undefined` 返回值胜出,并停止后续监听器。 |
|
|
89
|
+
| bail | `ctx.bail(name, ...args)` | serial 的同步版本。 |
|
|
90
|
+
| waterfall(瀑布式事件) | `ctx.waterfall(name, ...args, next)` | 环绕中间件,见下文。 |
|
|
91
|
+
|
|
92
|
+
每个 harness 事件都会在其所属[子系统页面](../subsystems/core.md)自动生成的参考文档中记录其模式。
|
|
93
|
+
|
|
94
|
+
## waterfall:转换或短路
|
|
95
|
+
|
|
96
|
+
waterfall 是实现拦截的模式。每个监听器都会收到参数和一个 `next()` continuation;它可以转换 `next()` 的返回值,也可以不调用 `next()` 就直接返回,从而短路链条的其余部分。Cordis 文档把后一种行为称为否决。创建 `waterfall-demo.ts`:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
100
|
+
|
|
101
|
+
declare module '@deepseek-ai/cordis' {
|
|
102
|
+
interface Events {
|
|
103
|
+
'demo/transform'(input: string, next: () => Promise<string>): Promise<string>
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const name = 'waterfall-demo'
|
|
108
|
+
|
|
109
|
+
export function apply(ctx: Context) {
|
|
110
|
+
// Listener 1: wrap the downstream result.
|
|
111
|
+
ctx.on('demo/transform', async (input, next) => {
|
|
112
|
+
const downstream = await next()
|
|
113
|
+
return downstream.toUpperCase()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
// Listener 2: short-circuit when it owns the decision.
|
|
117
|
+
ctx.on('demo/transform', async (input, next) => {
|
|
118
|
+
if (input.includes('blocked')) return '** blocked **'
|
|
119
|
+
return next()
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
void (async () => {
|
|
123
|
+
console.log(await ctx.waterfall('demo/transform', 'hello', async () => 'hello'))
|
|
124
|
+
console.log(await ctx.waterfall('demo/transform', 'blocked words', async () => 'blocked words'))
|
|
125
|
+
})()
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
让 `cordis.yml` 只指向该文件并运行:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
HELLO
|
|
133
|
+
** BLOCKED **
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
按顺序看第二行如何产生:监听器 1 先运行并调用 `next()`,从而调用监听器 2;监听器 2 看到 `blocked` 后直接返回而不调用 `next()`,因此最内层默认逻辑(传给 `ctx.waterfall` 的函数)从未运行;返回途中,监听器 1 再把替换消息转换为大写。
|
|
137
|
+
|
|
138
|
+
由此得到一项纪律:**只负责观察或标注的 waterfall 监听器必须调用 `next()`**;不调用就直接返回代表有意短路。如果日志监听器忘记调用 `next()`,会悄无声息地吞掉所有下游的默认行为。这是本仓库的常设规则([waterfall 语义](../cordis-primer.md#cordis-waterfall-semantics))。
|
|
139
|
+
|
|
140
|
+
harness 使用 waterfall 处理协作插件可以包装或回答的决策:[`agent/request`](../subsystems/core.md#agentrequest--waterfall) 允许插件替换模型调用配置,[`approval/request`](../subsystems/approval.md#approvalrequest--waterfall) 允许策略代替用户作答。
|
|
141
|
+
|
|
142
|
+
下一章:[配置](05-config.md):来自 `cordis.yml` 的插件选项。
|
|
143
|
+
|
|
144
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -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/cordis-tutorial/05-config.md
|
|
5
|
+
05-config.md: 17cccce2ec43be65477ce527800ee6a636ee5d96
|
|
6
|
+
05-config.zh.md: 87f1cb465d5f3e52a6f8e449cfb29818ba86dcb8
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# 5. Configuration
|
|
2
|
+
|
|
3
|
+
English | [中文](05-config.zh.md)
|
|
4
|
+
|
|
5
|
+
Each `cordis.yml` entry can carry a `config` block, and the plugin declares a schema that validates it before `apply` runs. Bad config fails the load with a precise error — the plugin never starts half-configured.
|
|
6
|
+
|
|
7
|
+
## A configurable plugin
|
|
8
|
+
|
|
9
|
+
Create `config-demo.ts` in `tmp/cordis-tutorial`:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
13
|
+
import Schema from '@deepseek-ai/schemastery'
|
|
14
|
+
|
|
15
|
+
export const name = 'config-demo'
|
|
16
|
+
|
|
17
|
+
export interface Config {
|
|
18
|
+
greeting: string
|
|
19
|
+
targets: string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const Config: Schema<Config> = Schema.object({
|
|
23
|
+
greeting: Schema.string().default('Hello'),
|
|
24
|
+
targets: Schema.array(String).default(['world']),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export function apply(ctx: Context, config: Config) {
|
|
28
|
+
for (const target of config.targets) {
|
|
29
|
+
console.log(`${config.greeting}, ${target}!`)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The exported `Config` is both a TypeScript interface and a runtime schema with the same name — consumers get the type, Cordis gets the validator. This repo uses [Schemastery](https://github.com/shigma/schemastery) for schemas; Cordis itself accepts any [Standard Schema](https://standardschema.dev/) validator, so a plain object exported as `Config` will not work.
|
|
35
|
+
|
|
36
|
+
Configure it:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- name: './config-demo.ts'
|
|
40
|
+
config:
|
|
41
|
+
targets: ['alpha', 'beta']
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Run:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Hello, alpha!
|
|
48
|
+
Hello, beta!
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`greeting` was omitted, so the schema default filled it in — `apply` always receives complete, validated config.
|
|
52
|
+
|
|
53
|
+
## Fail loud
|
|
54
|
+
|
|
55
|
+
Now feed it something invalid:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
- name: './config-demo.ts'
|
|
59
|
+
config:
|
|
60
|
+
targets: 'not-an-array'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
ValidationError: invalid config:
|
|
65
|
+
- $.targets expected array but got not-an-array (at targets)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The plugin's fiber goes to FAILED, and this tutorial's launcher exits with status 1 after printing the error. A plugin should also reject schema-valid config that names an unavailable resource or provider as soon as it can resolve that reference.
|
|
69
|
+
|
|
70
|
+
## Computed config values
|
|
71
|
+
|
|
72
|
+
The loader used in this repo supports a `!!js` tag for config values that must be computed at load time:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
- name: './config-demo.ts'
|
|
76
|
+
config:
|
|
77
|
+
greeting: !!js process.env.DEMO_GREETING ?? 'Hello'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`!!js` works only inside `config` and in an entry's `disabled` field. `disabled: !!js ...` evaluates against the loader context at every mount decision (this repo's extension), so a row can gate itself on platform or environment; the other metadata (`name`, `id`, `inject`, ...) stays static, where an expression is ordinary truthy data. See [loader configuration](../cordis-primer.md#loader-configuration).
|
|
81
|
+
|
|
82
|
+
Next: [Composition and HMR](06-composition-and-hmr.md) — treating `cordis.yml` as the application.
|
|
83
|
+
|
|
84
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# 5. 配置
|
|
2
|
+
|
|
3
|
+
[English](05-config.md) | 中文
|
|
4
|
+
|
|
5
|
+
`cordis.yml` 中的每个 Cordis 配置项都可以携带 `config` 块,插件则声明一个 schema,在运行 `apply` 前验证该块。错误配置会导致加载失败,并给出准确的错误:插件绝不会在配置不完整时启动。
|
|
6
|
+
|
|
7
|
+
## 可配置插件
|
|
8
|
+
|
|
9
|
+
创建 `config-demo.ts`,并将其放在 `tmp/cordis-tutorial` 中:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
13
|
+
import Schema from '@deepseek-ai/schemastery'
|
|
14
|
+
|
|
15
|
+
export const name = 'config-demo'
|
|
16
|
+
|
|
17
|
+
export interface Config {
|
|
18
|
+
greeting: string
|
|
19
|
+
targets: string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const Config: Schema<Config> = Schema.object({
|
|
23
|
+
greeting: Schema.string().default('Hello'),
|
|
24
|
+
targets: Schema.array(String).default(['world']),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export function apply(ctx: Context, config: Config) {
|
|
28
|
+
for (const target of config.targets) {
|
|
29
|
+
console.log(`${config.greeting}, ${target}!`)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
导出的 `Config` 既是 TypeScript 接口,也是同名的运行时 schema:消费方获得类型,Cordis 获得验证器。本仓库使用 [Schemastery](https://github.com/shigma/schemastery) 定义 schema;Cordis 本身接受任意 [Standard Schema](https://standardschema.dev/) 验证器,因此将普通对象导出为 `Config` 无法工作。
|
|
35
|
+
|
|
36
|
+
对其进行配置:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- name: './config-demo.ts'
|
|
40
|
+
config:
|
|
41
|
+
targets: ['alpha', 'beta']
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
运行:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Hello, alpha!
|
|
48
|
+
Hello, beta!
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
未提供 `greeting`,因此 schema 默认值会将其补齐:`apply` 始终会收到完整且经过验证的配置。
|
|
52
|
+
|
|
53
|
+
## 明确报错
|
|
54
|
+
|
|
55
|
+
现在向它传入无效内容:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
- name: './config-demo.ts'
|
|
59
|
+
config:
|
|
60
|
+
targets: 'not-an-array'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
ValidationError: invalid config:
|
|
65
|
+
- $.targets expected array but got not-an-array (at targets)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
插件的 fiber 进入 FAILED 状态,本教程的启动器打印错误后以状态码 1 退出。如果某个插件的配置通过了 schema 验证,但其中指定的资源或提供方不可用,该插件也应当在能解析该引用时立即拒绝。
|
|
69
|
+
|
|
70
|
+
## 计算得到的配置值
|
|
71
|
+
|
|
72
|
+
本仓库使用的 loader 支持 `!!js` 标签,用于必须在加载时计算的配置值:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
- name: './config-demo.ts'
|
|
76
|
+
config:
|
|
77
|
+
greeting: !!js process.env.DEMO_GREETING ?? 'Hello'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`!!js` 仅在 `config` 与条目 `disabled` 字段内有效。`disabled: !!js ...` 在每次挂载决策时基于 loader 上下文求值(本仓库的扩展),可以按平台或环境门控一行;其余元数据(`name`、`id`、`inject` 等)保持静态,其中的表达式是普通真值数据。详见 [loader 配置](../cordis-primer.md#loader-configuration)。
|
|
81
|
+
|
|
82
|
+
下一章:[组合与 HMR(热模块替换)](06-composition-and-hmr.md):将 `cordis.yml` 视为应用。
|
|
83
|
+
|
|
84
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -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/cordis-tutorial/06-composition-and-hmr.md
|
|
5
|
+
06-composition-and-hmr.md: 2b53aa28be99851e77a71de76337f2beb4003e8d
|
|
6
|
+
06-composition-and-hmr.zh.md: cd4afa1d5465a5442bfd6b771ebcd61c46fe2983
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# 6. Composition and HMR
|
|
2
|
+
|
|
3
|
+
English | [中文](06-composition-and-hmr.zh.md)
|
|
4
|
+
|
|
5
|
+
Every capability built so far is a plugin, and `cordis.yml` selects the application's plugin tree. This chapter changes that composition, hot-reloads a plugin, and diagnoses a plugin that never loads.
|
|
6
|
+
|
|
7
|
+
## Entries are more than a name
|
|
8
|
+
|
|
9
|
+
A config entry accepts metadata beyond `name` and `config`:
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
- id: greeter # stable identity for this entry
|
|
13
|
+
name: './greeter.ts'
|
|
14
|
+
- id: consumer
|
|
15
|
+
name: './consumer.ts'
|
|
16
|
+
disabled: true # keep the entry, skip mounting it
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`id` gives the entry a stable identity so the loader can tell an edit to an existing entry apart from a removal plus an addition. `disabled: true` unmounts a plugin without deleting its entry — flip it back and the plugin (and everything PENDING on its services) loads again.
|
|
20
|
+
|
|
21
|
+
Groups nest a sub-list of entries that load and unload as one unit, and `isolate` gives a group its own instance of a service name — two groups can each see a differently configured `shell` provider without affecting each other. The [Cordis primer](../cordis-primer.md) and the [service isolation example](../user/develop/framework/service.md#service-isolation) cover the details.
|
|
22
|
+
|
|
23
|
+
## Hot module replacement
|
|
24
|
+
|
|
25
|
+
Because unloading releases effects ([chapter 2](02-lifecycle-and-effects.md)) and loading follows dependencies ([chapter 3](03-services.md)), HMR can replace a running plugin by unloading and loading it. The `@deepseek-ai/cordis-plugin-hmr` plugin watches your files and does exactly that on save.
|
|
26
|
+
|
|
27
|
+
In `tmp/cordis-tutorial`, write `cordis.yml`:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
- id: logger
|
|
31
|
+
name: '@deepseek-ai/cordis-plugin-logger-console'
|
|
32
|
+
- id: timer
|
|
33
|
+
name: '@deepseek-ai/cordis-plugin-timer'
|
|
34
|
+
- id: hmr
|
|
35
|
+
name: '@deepseek-ai/cordis-plugin-hmr'
|
|
36
|
+
config:
|
|
37
|
+
root: ['.']
|
|
38
|
+
- id: hello
|
|
39
|
+
name: './hello.ts'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Two support plugins joined the list: HMR logs through the Cordis logger service, so without a console exporter you would not see its messages, and it `inject`s the `timer` service for debouncing — without `@deepseek-ai/cordis-plugin-timer` it sits in PENDING forever, silently. That silence is the subject of the next section.
|
|
43
|
+
|
|
44
|
+
HMR reads Node's loader internals through the Loader's native helper. Run Cordis under tsx:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
node --import tsx ../../vendor/cordis/bin.js
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Now edit `hello.ts` — change the log message — and save:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
hello from my first plugin
|
|
54
|
+
2026-07-22 15:44:36 [I] hmr watching [ '.' ]
|
|
55
|
+
2026-07-22 15:44:39 [I] hmr reload plugin at hello.ts
|
|
56
|
+
hello from my EDITED plugin
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The old instance unloaded (all its effects unwound), the new code loaded, `apply` ran again. Stop the process with Ctrl-C. Editing `cordis.yml` itself is also picked up: the loader diffs entries by `id` and mounts, unmounts, or reconfigures only what changed. This is why the entries above carry explicit `id`s — an entry without one gets a generated id on every read, so after any config-file edit it counts as removed-plus-added and remounts even if its own lines did not change.
|
|
60
|
+
|
|
61
|
+
## Diagnosing a plugin that never loads
|
|
62
|
+
|
|
63
|
+
The flip side of dependency-driven loading: a plugin whose `inject` names a service nobody provides waits forever, printing nothing. No error — PENDING is a legitimate state, since the provider may be mounted later.
|
|
64
|
+
|
|
65
|
+
You can see the states directly. Every context can enumerate the plugin registry; create `diagnose.ts`:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { FiberState, type Context } from '@deepseek-ai/cordis'
|
|
69
|
+
|
|
70
|
+
export const name = 'diagnose'
|
|
71
|
+
|
|
72
|
+
export function apply(ctx: Context) {
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
for (const runtime of ctx.registry.values()) {
|
|
75
|
+
for (const fiber of runtime.fibers) {
|
|
76
|
+
if (fiber.state === FiberState.PENDING) {
|
|
77
|
+
console.log(`${fiber.name} is PENDING — a required service is missing`)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, 500)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
And a plugin with an unsatisfiable dependency, `needs-timer.ts`:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
89
|
+
|
|
90
|
+
export const name = 'needs-timer'
|
|
91
|
+
export const inject = ['timer']
|
|
92
|
+
|
|
93
|
+
export function apply(ctx: Context) {
|
|
94
|
+
console.log('needs-timer loaded')
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
- name: './needs-timer.ts'
|
|
100
|
+
- name: './diagnose.ts'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Run it (plain `node --import tsx ../../vendor/cordis/bin.js`; stop with Ctrl-C):
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
needs-timer is PENDING — a required service is missing
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`inject: ['timer']` has no provider. Add `- name: '@deepseek-ai/cordis-plugin-timer'` to the list and the plugin loads. When a plugin does nothing and reports nothing, inspect its fiber state. Iterating without the PENDING filter also shows the loader's own plugins (Loader, Include) as ACTIVE fibers because plugins mount the config file itself.
|
|
110
|
+
|
|
111
|
+
Next: [Into the harness](07-into-the-harness.md) — the same patterns against real harness services.
|
|
112
|
+
|
|
113
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# 6. 组合与 HMR(热模块替换)
|
|
2
|
+
|
|
3
|
+
[English](06-composition-and-hmr.md) | 中文
|
|
4
|
+
|
|
5
|
+
到目前为止构建的每项能力都是插件,`cordis.yml` 则选择应用的插件树。本章会改变这种组合、热重载一个插件,并诊断始终无法加载的插件。
|
|
6
|
+
|
|
7
|
+
## Cordis 配置项不只有名称
|
|
8
|
+
|
|
9
|
+
Cordis 配置项除了 `name` 和 `config`,还接受其他元数据:
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
- id: greeter # stable identity for this entry
|
|
13
|
+
name: './greeter.ts'
|
|
14
|
+
- id: consumer
|
|
15
|
+
name: './consumer.ts'
|
|
16
|
+
disabled: true # keep the entry, skip mounting it
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`id` 为 Cordis 配置项提供稳定标识,使 loader 能区分修改现有 Cordis 配置项与先删除再添加。`disabled: true` 会卸载插件而不删除其 Cordis 配置项;改回原值后,插件以及所有因依赖其服务而处于 PENDING 的插件都会再次加载。
|
|
20
|
+
|
|
21
|
+
组可以嵌套一份 Cordis 配置项子列表,并将其作为一个单元加载和卸载;`isolate` 则为一个组提供某项服务名称的独立实例,因此两个组可以各自看到配置不同的 `shell` 提供方,互不影响。[Cordis 入门](../cordis-primer.md)和[服务隔离示例](../user/develop/framework/service.md#service-isolation)介绍了详细内容。
|
|
22
|
+
|
|
23
|
+
## 热模块替换
|
|
24
|
+
|
|
25
|
+
卸载会释放 effect([第 2 章](02-lifecycle-and-effects.md)),加载则遵循依赖关系([第 3 章](03-services.md)),因此 HMR 可以先卸载、再加载,以替换正在运行的插件。`@deepseek-ai/cordis-plugin-hmr` 插件会监视文件,并在保存时执行这一过程。
|
|
26
|
+
|
|
27
|
+
在 `tmp/cordis-tutorial` 中编写 `cordis.yml`:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
- id: logger
|
|
31
|
+
name: '@deepseek-ai/cordis-plugin-logger-console'
|
|
32
|
+
- id: timer
|
|
33
|
+
name: '@deepseek-ai/cordis-plugin-timer'
|
|
34
|
+
- id: hmr
|
|
35
|
+
name: '@deepseek-ai/cordis-plugin-hmr'
|
|
36
|
+
config:
|
|
37
|
+
root: ['.']
|
|
38
|
+
- id: hello
|
|
39
|
+
name: './hello.ts'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
列表中增加了两个辅助插件:HMR 通过 Cordis logger 服务记录日志,因此没有控制台导出器时看不到其消息;它还会 `inject` `timer` 服务来实现去抖,如果没有 `@deepseek-ai/cordis-plugin-timer`,它就会永远停在 PENDING,而且不发出任何提示。下一节就讨论这种静默状态。
|
|
43
|
+
|
|
44
|
+
HMR 通过 Loader 的原生辅助工具读取 Node 的 loader 内部结构。请在 tsx 下运行 Cordis:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
node --import tsx ../../vendor/cordis/bin.js
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
现在编辑 `hello.ts`,修改日志消息并保存:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
hello from my first plugin
|
|
54
|
+
2026-07-22 15:44:36 [I] hmr watching [ '.' ]
|
|
55
|
+
2026-07-22 15:44:39 [I] hmr reload plugin at hello.ts
|
|
56
|
+
hello from my EDITED plugin
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
旧实例先卸载(其所有 effect 都会回卷),新代码随后加载,`apply` 再次运行。按 Ctrl-C 停止进程。编辑 `cordis.yml` 本身也会触发更新:loader 按 `id` 比较 Cordis 配置项,只挂载、卸载或重新配置发生变化的部分。这就是上述 Cordis 配置项显式携带 `id` 的原因:不带该字段的 Cordis 配置项在每次读取时都会获得一个新生成的 id,所以只要配置文件发生任何编辑,即使自身文本未变,它也会被视为先删除再添加并重新挂载。
|
|
60
|
+
|
|
61
|
+
## 诊断始终无法加载的插件
|
|
62
|
+
|
|
63
|
+
依赖驱动加载也有另一面:如果插件的 `inject` 指定了无人提供的服务,它就会一直等待,不输出任何内容。这不是错误,因为 PENDING 是合法状态,提供方可能稍后才挂载。
|
|
64
|
+
|
|
65
|
+
你可以直接查看这些状态。每个上下文都能枚举插件注册表;创建 `diagnose.ts`:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { FiberState, type Context } from '@deepseek-ai/cordis'
|
|
69
|
+
|
|
70
|
+
export const name = 'diagnose'
|
|
71
|
+
|
|
72
|
+
export function apply(ctx: Context) {
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
for (const runtime of ctx.registry.values()) {
|
|
75
|
+
for (const fiber of runtime.fibers) {
|
|
76
|
+
if (fiber.state === FiberState.PENDING) {
|
|
77
|
+
console.log(`${fiber.name} is PENDING — a required service is missing`)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, 500)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
再创建一个依赖无法满足的插件 `needs-timer.ts`:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
89
|
+
|
|
90
|
+
export const name = 'needs-timer'
|
|
91
|
+
export const inject = ['timer']
|
|
92
|
+
|
|
93
|
+
export function apply(ctx: Context) {
|
|
94
|
+
console.log('needs-timer loaded')
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
- name: './needs-timer.ts'
|
|
100
|
+
- name: './diagnose.ts'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
运行它(直接执行 `node --import tsx ../../vendor/cordis/bin.js`,按 Ctrl-C 停止):
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
needs-timer is PENDING — a required service is missing
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`inject: ['timer']` 没有提供方。向列表添加 `- name: '@deepseek-ai/cordis-plugin-timer'` 后,插件就会加载。如果插件既不执行任何操作,也不报告任何内容,请检查其 fiber 状态。不加 PENDING 过滤条件进行迭代时,还会看到 loader 自身的插件(Loader、Include)处于 ACTIVE,因为配置文件本身也是通过插件挂载的。
|
|
110
|
+
|
|
111
|
+
下一章:[进入 harness](07-into-the-harness.md):把相同模式用于真实的 harness 服务。
|
|
112
|
+
|
|
113
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -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/cordis-tutorial/07-into-the-harness.md
|
|
5
|
+
07-into-the-harness.md: 2d3c23f9f7f7fc6bd6cabd4e7e68ebfc46e20665
|
|
6
|
+
07-into-the-harness.zh.md: 45dc0ee6f07ab3b0275499cd4ab0c436eebdddef
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# 7. Into the harness
|
|
2
|
+
|
|
3
|
+
English | [中文](07-into-the-harness.zh.md)
|
|
4
|
+
|
|
5
|
+
This chapter registers a model-callable tool with the harness's `tools` service, executes it through the harness tool pipeline, and observes the result event. It remains keyless and does not call a model.
|
|
6
|
+
|
|
7
|
+
## A tool plugin
|
|
8
|
+
|
|
9
|
+
Create `greet-tool.ts` in `tmp/cordis-tutorial`:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
13
|
+
import { defineTool } from '@deepseek-ai/dsh-tools'
|
|
14
|
+
import { CallId } from '@deepseek-ai/dsh-llm'
|
|
15
|
+
|
|
16
|
+
export const name = 'greet-tool'
|
|
17
|
+
export const inject = ['tools']
|
|
18
|
+
|
|
19
|
+
export function apply(ctx: Context) {
|
|
20
|
+
ctx.tools.register(defineTool({
|
|
21
|
+
name: 'greet',
|
|
22
|
+
description: 'Greet the named person.',
|
|
23
|
+
parameters: {
|
|
24
|
+
name: { type: 'string', required: true, description: 'Who to greet' },
|
|
25
|
+
},
|
|
26
|
+
output: {
|
|
27
|
+
schema: { type: 'string' },
|
|
28
|
+
render: (_args, value) => [{ type: 'text', text: value }],
|
|
29
|
+
},
|
|
30
|
+
async execute(args) {
|
|
31
|
+
return `Hello, ${args.name}!`
|
|
32
|
+
},
|
|
33
|
+
}))
|
|
34
|
+
|
|
35
|
+
// Drive one call through the real execution pipeline, standing in for
|
|
36
|
+
// the model. CallId brands the correlation id a provider would issue.
|
|
37
|
+
void (async () => {
|
|
38
|
+
const result = await ctx.tools.execute({
|
|
39
|
+
callId: CallId('demo-1'),
|
|
40
|
+
name: 'greet',
|
|
41
|
+
arguments: { name: 'Cordis' },
|
|
42
|
+
signal: new AbortController().signal,
|
|
43
|
+
})
|
|
44
|
+
console.log('tool replied:', JSON.stringify(result.content))
|
|
45
|
+
})()
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Every pattern here is from the earlier chapters: `inject: ['tools']` ([chapter 3](03-services.md)) holds the plugin until the tool registry exists; `ctx.tools.register(...)` attaches the registration disposer to the plugin ([chapter 2](02-lifecycle-and-effects.md)), so unloading unregisters the tool. `defineTool` converts the `parameters` spec to the JSON Schema shown to the model, infers the type of `args`, and validates model-supplied arguments before `execute` runs. The tool returns the canonical value declared by `output.schema`; `output.render` separately produces the Native and durable result content.
|
|
50
|
+
|
|
51
|
+
## An observer plugin
|
|
52
|
+
|
|
53
|
+
Create `tool-logger.ts` — a separate plugin that watches every tool call in the app through the harness's `tools/result` event:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
57
|
+
import type {} from '@deepseek-ai/dsh-tools'
|
|
58
|
+
|
|
59
|
+
export const name = 'tool-logger'
|
|
60
|
+
export const inject = ['tools']
|
|
61
|
+
|
|
62
|
+
export function apply(ctx: Context) {
|
|
63
|
+
ctx.on('tools/result', (exec, result) => {
|
|
64
|
+
const text = result.content
|
|
65
|
+
.map(block => (block.type === 'text' ? block.text : ''))
|
|
66
|
+
.join('')
|
|
67
|
+
console.log(`[tool-logger] ${exec.name} -> ${text}`)
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `import type {} from '@deepseek-ai/dsh-tools'` line pulls in the package's declaration merges so `'tools/result'` and its payload are typed — the same move as chapter 4's `stats.ts` import, at package scale.
|
|
73
|
+
|
|
74
|
+
## Compose and run
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
- name: '@deepseek-ai/dsh-system-prompt'
|
|
78
|
+
- name: '@deepseek-ai/dsh-tools'
|
|
79
|
+
- name: './tool-logger.ts'
|
|
80
|
+
- name: './greet-tool.ts'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`@deepseek-ai/dsh-tools` injects the `systemPrompt` service because tools contribute schemas to the system prompt, so the composition lists its provider too. Without it, the tools plugin remains PENDING as described in [chapter 6](06-composition-and-hmr.md).
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
node --import tsx ../../vendor/cordis/bin.js
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
[tool-logger] greet -> Hello, Cordis!
|
|
91
|
+
tool replied: [{"type":"text","text":"Hello, Cordis!"}]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The logger fired first: `tools/result` is emitted as part of result materialization, before `execute`'s promise resolves to the caller. Neither of your plugins knows the other exists — the registry service and the event connect them.
|
|
95
|
+
|
|
96
|
+
## From here to a full agent
|
|
97
|
+
|
|
98
|
+
A real agent is this composition plus more plugins: an LLM adapter, the agent loop, persistence, an entry point. Compare [examples/headless-agent/cordis.yml](../../examples/headless-agent/cordis.yml) — you can read every entry in it now. Add your `greet-tool.ts` to a copy of that file.
|
|
99
|
+
|
|
100
|
+
Where to go next:
|
|
101
|
+
|
|
102
|
+
- [Build a tool](../user/develop/basic/tool.md) — more of `defineTool`, including presentation and richer schemas.
|
|
103
|
+
- [Three-layer capability design](../user/develop/practice/index.md) — how the harness structures replaceable capabilities.
|
|
104
|
+
- The generated `cordis-surface` regions on the [subsystem pages](../subsystems/core.md) — everything you can inject and listen to, each on its owning page.
|
|
105
|
+
- [Architecture](../architecture.md) — the system map these plugins live in.
|
|
106
|
+
|
|
107
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|