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,150 @@
|
|
|
1
|
+
# 服务与依赖
|
|
2
|
+
|
|
3
|
+
[English](service.md) | 中文
|
|
4
|
+
|
|
5
|
+
服务是一个插件向其他插件公开的能力。inject 声明插件需要哪些服务。
|
|
6
|
+
|
|
7
|
+
## 什么是服务
|
|
8
|
+
|
|
9
|
+
在 Harness 中,`tools`、`llm`、`agents` 都是服务。服务是挂载在 `ctx` 上的命名能力:
|
|
10
|
+
|
|
11
|
+
```ts ignore-check
|
|
12
|
+
ctx.tools // ToolRuntime service
|
|
13
|
+
ctx.llm // LLM service
|
|
14
|
+
ctx.agents // Agent service
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
任何插件都可以提供服务,供其他插件使用。
|
|
18
|
+
|
|
19
|
+
## 使用服务
|
|
20
|
+
|
|
21
|
+
声明 `inject` 来使用已有服务:
|
|
22
|
+
|
|
23
|
+
```ts ignore-check
|
|
24
|
+
export const inject = ['tools']
|
|
25
|
+
|
|
26
|
+
export function apply(ctx: Context) {
|
|
27
|
+
// ctx.tools exists and is ready here.
|
|
28
|
+
ctx.tools.register(/* ... */)
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
框架保证:在 `apply` 执行时,`inject` 声明的服务已经全部就绪。如果服务还没准备好,你的插件会等着,不会执行。
|
|
33
|
+
|
|
34
|
+
## 提供服务
|
|
35
|
+
|
|
36
|
+
### 使用 Service 基类
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { Service, type Context } from '@deepseek-ai/cordis'
|
|
40
|
+
|
|
41
|
+
export default class MetricsService extends Service {
|
|
42
|
+
static inject = ['llm'] // A service may depend on other services.
|
|
43
|
+
|
|
44
|
+
constructor(ctx: Context) {
|
|
45
|
+
super(ctx, 'metrics') // 'metrics' is the service name.
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Public service method.
|
|
49
|
+
record(event: string, value: number) {
|
|
50
|
+
// ...
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
加载这个插件后,消费方就可以通过 `ctx.metrics` 访问它:
|
|
56
|
+
|
|
57
|
+
```ts ignore-check
|
|
58
|
+
export const inject = ['metrics']
|
|
59
|
+
|
|
60
|
+
export function apply(ctx: Context) {
|
|
61
|
+
ctx.metrics.record('tool_call', 1)
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 类型声明
|
|
66
|
+
|
|
67
|
+
使用 TypeScript 声明合并让 `ctx.metrics` 有正确类型:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { Service, type Context } from '@deepseek-ai/cordis'
|
|
71
|
+
|
|
72
|
+
declare module '@deepseek-ai/cordis' {
|
|
73
|
+
interface Context {
|
|
74
|
+
metrics: MetricsService
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default class MetricsService extends Service {
|
|
79
|
+
constructor(ctx: Context) {
|
|
80
|
+
super(ctx, 'metrics')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
record(event: string, value: number) { /* ... */ }
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 依赖的行为
|
|
88
|
+
|
|
89
|
+
### 必需依赖与可选依赖
|
|
90
|
+
|
|
91
|
+
```ts ignore-check
|
|
92
|
+
// Required: the plugin does not load while the service is absent.
|
|
93
|
+
export const inject = ['tools']
|
|
94
|
+
|
|
95
|
+
// Optional: omit inject and query with ctx.get() at the use site.
|
|
96
|
+
export function apply(ctx: Context) {
|
|
97
|
+
const metrics = ctx.get('metrics')
|
|
98
|
+
metrics?.record('plugin_loaded', 1)
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 服务消失时的行为
|
|
103
|
+
|
|
104
|
+
如果应用运行期间某项必需服务消失(例如其提供方卸载):
|
|
105
|
+
|
|
106
|
+
1. 依赖它的插件会自动 dispose(资源释放)
|
|
107
|
+
2. 当服务重新出现时,插件自动重新加载
|
|
108
|
+
|
|
109
|
+
这可以防止插件调用已不存在的服务。
|
|
110
|
+
|
|
111
|
+
<a id="service-isolation"></a>
|
|
112
|
+
|
|
113
|
+
## 服务隔离
|
|
114
|
+
|
|
115
|
+
`cordis.yml` 支持服务隔离——同一个服务可以有多个实例,不同插件组看到不同实例:
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
- id: group-a
|
|
119
|
+
name: '@deepseek-ai/cordis-plugin-group'
|
|
120
|
+
group: true
|
|
121
|
+
isolate:
|
|
122
|
+
shell: true
|
|
123
|
+
config:
|
|
124
|
+
- name: '@deepseek-ai/dsh-bash-local'
|
|
125
|
+
config:
|
|
126
|
+
timeoutMs: 5000
|
|
127
|
+
- name: './src/plugin-a.ts'
|
|
128
|
+
|
|
129
|
+
- id: group-b
|
|
130
|
+
name: '@deepseek-ai/cordis-plugin-group'
|
|
131
|
+
group: true
|
|
132
|
+
isolate:
|
|
133
|
+
shell: true
|
|
134
|
+
config:
|
|
135
|
+
- name: '@deepseek-ai/dsh-bash-local'
|
|
136
|
+
config:
|
|
137
|
+
timeoutMs: 60000
|
|
138
|
+
- name: './src/plugin-b.ts'
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`plugin-a` 和 `plugin-b` 各自看到自己组内的 Bash 实例,互不影响。
|
|
142
|
+
|
|
143
|
+
## Harness 内置服务
|
|
144
|
+
|
|
145
|
+
服务名、公开方法和源码位置由仓库自动生成到各服务的[子系统页面](../../../subsystems/core.md)。开发插件时应以这些生成区块和服务的 TypeScript 接口为准,不要维护另一份静态清单。
|
|
146
|
+
|
|
147
|
+
## 下一步
|
|
148
|
+
|
|
149
|
+
- [事件系统](./events.md) — 插件间松耦合通信
|
|
150
|
+
- [能力分层](../practice/) — 将服务用作能力接口
|
|
@@ -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/user/develop/practice/index.md
|
|
5
|
+
index.md: cc6bd7a234305f6fa193341f15354b40855f72e9
|
|
6
|
+
index.zh.md: aed13b00f9bc74946aace614953bed30705c8281
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Three-role capability design
|
|
2
|
+
|
|
3
|
+
English | [中文](index.zh.md)
|
|
4
|
+
|
|
5
|
+
This page has two parts: a concept reference for the three-role capability pattern, followed by an advanced tutorial that builds one capability. Complete the [basic plugin path](../basic/) and [services tutorial](../framework/service.md) first.
|
|
6
|
+
|
|
7
|
+
## Concept reference
|
|
8
|
+
|
|
9
|
+
When a capability is general enough to need replaceable providers, such as Bash execution, Harness separates three roles: a **Service Definition**, a **Service Provider**, and a **Consumer**. Put the roles in separate packages when they need to evolve or be replaced independently; a package may otherwise own more than one role. The complete capability is its seam. No individual role is a seam.
|
|
10
|
+
|
|
11
|
+
## Bash example
|
|
12
|
+
|
|
13
|
+
The Bash execution capability consists of:
|
|
14
|
+
|
|
15
|
+
- **Service Definition** (`dsh-shell`) — defines the Cordis service and Bash request and result types
|
|
16
|
+
- **Service Provider** (`dsh-bash-local`) — executes commands on the local machine
|
|
17
|
+
- **Consumer** (`dsh-tool-bash`) — exposes the capability as a model-callable tool
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
21
|
+
│ dsh-shell │────▶│ dsh-bash-local │ │ dsh-tool-bash│
|
|
22
|
+
│(definition) │ │ (provider) │ │(consumer/tool)│
|
|
23
|
+
└─────────────┘ └──────────────────┘ └──────────────┘
|
|
24
|
+
▲ │
|
|
25
|
+
└────────────────────────────────────────────┘
|
|
26
|
+
inject: ['shell']
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Benefits of the split
|
|
30
|
+
|
|
31
|
+
### Replace providers
|
|
32
|
+
|
|
33
|
+
One Service Definition can have multiple providers selected through `cordis.yml`:
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
# Local execution
|
|
37
|
+
- name: '@deepseek-ai/dsh-bash-local'
|
|
38
|
+
|
|
39
|
+
# Replace this row with another package that provides the same service.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The Service Definition and tool remain unchanged while the provider changes.
|
|
43
|
+
|
|
44
|
+
### Evolve independently
|
|
45
|
+
|
|
46
|
+
- The Service Definition changes rarely after callers depend on its contract.
|
|
47
|
+
- Service Providers can improve performance and security independently.
|
|
48
|
+
- Consumers can change how they present the capability to the model.
|
|
49
|
+
|
|
50
|
+
### Decouple dependencies
|
|
51
|
+
|
|
52
|
+
- The Service Provider depends on the Service Definition.
|
|
53
|
+
- The Consumer depends on the Service Definition.
|
|
54
|
+
- The Service Provider and Consumer **do not depend on each other**.
|
|
55
|
+
|
|
56
|
+
The [capability-seam reference](../../../capability-seams.md) owns the current built-in families and package links.
|
|
57
|
+
|
|
58
|
+
## Tutorial: develop a three-role capability
|
|
59
|
+
|
|
60
|
+
### Step 1: write the Service Definition
|
|
61
|
+
|
|
62
|
+
```ts ignore-check
|
|
63
|
+
// packages/my-cap/my-cap/src/index.ts
|
|
64
|
+
import { Service, type Context } from '@deepseek-ai/cordis'
|
|
65
|
+
|
|
66
|
+
declare module '@deepseek-ai/cordis' {
|
|
67
|
+
interface Context {
|
|
68
|
+
myCap: MyCapService
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export abstract class MyCapService extends Service {
|
|
73
|
+
constructor(ctx: Context) {
|
|
74
|
+
super(ctx, 'myCap')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Execute the capability. */
|
|
78
|
+
abstract execute(request: MyCapRequest): Promise<MyCapResult>
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface MyCapRequest {
|
|
82
|
+
input: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface MyCapResult {
|
|
86
|
+
output: string
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Step 2: write a Service Provider
|
|
91
|
+
|
|
92
|
+
```ts ignore-check
|
|
93
|
+
// packages/my-cap/my-cap-local/src/index.ts
|
|
94
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
95
|
+
import { MyCapService, type MyCapRequest, type MyCapResult } from '@deepseek-ai/dsh-my-cap'
|
|
96
|
+
|
|
97
|
+
class MyCapLocal extends MyCapService {
|
|
98
|
+
async execute(request: MyCapRequest): Promise<MyCapResult> {
|
|
99
|
+
// Local provider behavior.
|
|
100
|
+
return { output: request.input.toUpperCase() }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const name = 'my-cap-local'
|
|
105
|
+
|
|
106
|
+
export function apply(ctx: Context) {
|
|
107
|
+
ctx.plugin(MyCapLocal)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step 3: write a consumer
|
|
112
|
+
|
|
113
|
+
```ts ignore-check
|
|
114
|
+
// packages/my-cap/tool-my-cap/src/index.ts
|
|
115
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
116
|
+
import { defineTool } from '@deepseek-ai/dsh-tools'
|
|
117
|
+
|
|
118
|
+
export const name = 'tool-my-cap'
|
|
119
|
+
export const inject = ['tools', 'myCap']
|
|
120
|
+
|
|
121
|
+
export function apply(ctx: Context) {
|
|
122
|
+
ctx.tools.register(defineTool({
|
|
123
|
+
name: 'my_cap',
|
|
124
|
+
description: 'Execute my capability.',
|
|
125
|
+
parameters: {
|
|
126
|
+
input: { type: 'string', required: true },
|
|
127
|
+
},
|
|
128
|
+
output: {
|
|
129
|
+
schema: { type: 'string' },
|
|
130
|
+
render: (_args, value) => [{ type: 'text', text: value }],
|
|
131
|
+
},
|
|
132
|
+
async execute(args) {
|
|
133
|
+
const result = await ctx.myCap.execute({ input: args.input })
|
|
134
|
+
return result.output
|
|
135
|
+
},
|
|
136
|
+
}))
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Compose them in cordis.yml
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
- name: '@deepseek-ai/dsh-my-cap-local'
|
|
144
|
+
- name: '@deepseek-ai/dsh-tool-my-cap'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Design points
|
|
148
|
+
|
|
149
|
+
- **Do not split preemptively** — use separate packages only when the roles need to evolve independently. A simple tool plugin does not.
|
|
150
|
+
- **The Service Definition owns Request/Result types** — Service Providers and Consumers depend only on the Service Definition package.
|
|
151
|
+
- **Explicit > implicit** — resolve defaults in an explicit `resolve(request): Spec` step rather than hiding `?? default` expressions inside `run()`.
|
|
152
|
+
|
|
153
|
+
## Next steps
|
|
154
|
+
|
|
155
|
+
- [LLM adapter](./llm-adapter.md) — implement an LLM provider
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# 能力的三种角色设计
|
|
2
|
+
|
|
3
|
+
[English](index.md) | 中文
|
|
4
|
+
|
|
5
|
+
本文分为两部分:先参考三种角色能力模式的概念,再通过高级教程构建一项能力。请先完成[基础插件路径](../basic/)和[服务教程](../framework/service.md)。
|
|
6
|
+
|
|
7
|
+
## 概念参考
|
|
8
|
+
|
|
9
|
+
当一项能力足够通用,需要支持可替换的提供方时(例如 Bash 执行),harness 会区分三种角色:**Service Definition**、**Service Provider** 和 **Consumer**。角色需要独立演进或替换时,将它们放入不同包;否则一个包可以承担多个角色。完整能力构成其 seam。任何单一角色都不是 seam。
|
|
10
|
+
|
|
11
|
+
## 以 Bash 为例
|
|
12
|
+
|
|
13
|
+
以 Bash 执行能力为例:
|
|
14
|
+
|
|
15
|
+
- **Service Definition** (`dsh-shell`):定义 Cordis 服务以及 Bash 请求和结果类型
|
|
16
|
+
- **Service Provider** (`dsh-bash-local`):在本地计算机上执行命令
|
|
17
|
+
- **Consumer** (`dsh-tool-bash`):将该能力公开为模型可调用的工具
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
21
|
+
│ dsh-shell │────▶│ dsh-bash-local │ │ dsh-tool-bash│
|
|
22
|
+
│(definition) │ │ (provider) │ │(consumer/tool)│
|
|
23
|
+
└─────────────┘ └──────────────────┘ └──────────────┘
|
|
24
|
+
▲ │
|
|
25
|
+
└────────────────────────────────────────────┘
|
|
26
|
+
inject: ['shell']
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 拆分的好处
|
|
30
|
+
|
|
31
|
+
### 提供方可替换
|
|
32
|
+
|
|
33
|
+
同一个 Service Definition 可以有多个提供方,可通过 `cordis.yml` 选择:
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
# Local execution
|
|
37
|
+
- name: '@deepseek-ai/dsh-bash-local'
|
|
38
|
+
|
|
39
|
+
# Replace this row with another package that provides the same service.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
更换提供方时,Service Definition 和工具均保持不变。
|
|
43
|
+
|
|
44
|
+
### 独立演进
|
|
45
|
+
|
|
46
|
+
- 调用方开始依赖 Service Definition 的约定后,Service Definition 很少改动。
|
|
47
|
+
- Service Provider 可以独立优化性能和安全性。
|
|
48
|
+
- Consumer 可以调整能力向模型呈现的方式。
|
|
49
|
+
|
|
50
|
+
### 依赖解耦
|
|
51
|
+
|
|
52
|
+
- Service Provider 依赖 Service Definition。
|
|
53
|
+
- Consumer 依赖 Service Definition。
|
|
54
|
+
- Service Provider 和 Consumer **互不依赖**。
|
|
55
|
+
|
|
56
|
+
当前内置系列及其包链接由[能力 seam 参考](../../../capability-seams.md)负责。
|
|
57
|
+
|
|
58
|
+
## 教程:开发三种角色的能力
|
|
59
|
+
|
|
60
|
+
### 第一步:编写 Service Definition
|
|
61
|
+
|
|
62
|
+
```ts ignore-check
|
|
63
|
+
// packages/my-cap/my-cap/src/index.ts
|
|
64
|
+
import { Service, type Context } from '@deepseek-ai/cordis'
|
|
65
|
+
|
|
66
|
+
declare module '@deepseek-ai/cordis' {
|
|
67
|
+
interface Context {
|
|
68
|
+
myCap: MyCapService
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export abstract class MyCapService extends Service {
|
|
73
|
+
constructor(ctx: Context) {
|
|
74
|
+
super(ctx, 'myCap')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Execute the capability. */
|
|
78
|
+
abstract execute(request: MyCapRequest): Promise<MyCapResult>
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface MyCapRequest {
|
|
82
|
+
input: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface MyCapResult {
|
|
86
|
+
output: string
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 第二步:编写 Service Provider
|
|
91
|
+
|
|
92
|
+
```ts ignore-check
|
|
93
|
+
// packages/my-cap/my-cap-local/src/index.ts
|
|
94
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
95
|
+
import { MyCapService, type MyCapRequest, type MyCapResult } from '@deepseek-ai/dsh-my-cap'
|
|
96
|
+
|
|
97
|
+
class MyCapLocal extends MyCapService {
|
|
98
|
+
async execute(request: MyCapRequest): Promise<MyCapResult> {
|
|
99
|
+
// Local provider behavior.
|
|
100
|
+
return { output: request.input.toUpperCase() }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const name = 'my-cap-local'
|
|
105
|
+
|
|
106
|
+
export function apply(ctx: Context) {
|
|
107
|
+
ctx.plugin(MyCapLocal)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 第三步:编写消费方
|
|
112
|
+
|
|
113
|
+
```ts ignore-check
|
|
114
|
+
// packages/my-cap/tool-my-cap/src/index.ts
|
|
115
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
116
|
+
import { defineTool } from '@deepseek-ai/dsh-tools'
|
|
117
|
+
|
|
118
|
+
export const name = 'tool-my-cap'
|
|
119
|
+
export const inject = ['tools', 'myCap']
|
|
120
|
+
|
|
121
|
+
export function apply(ctx: Context) {
|
|
122
|
+
ctx.tools.register(defineTool({
|
|
123
|
+
name: 'my_cap',
|
|
124
|
+
description: 'Execute my capability.',
|
|
125
|
+
parameters: {
|
|
126
|
+
input: { type: 'string', required: true },
|
|
127
|
+
},
|
|
128
|
+
output: {
|
|
129
|
+
schema: { type: 'string' },
|
|
130
|
+
render: (_args, value) => [{ type: 'text', text: value }],
|
|
131
|
+
},
|
|
132
|
+
async execute(args) {
|
|
133
|
+
const result = await ctx.myCap.execute({ input: args.input })
|
|
134
|
+
return result.output
|
|
135
|
+
},
|
|
136
|
+
}))
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 在 cordis.yml 中组合
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
- name: '@deepseek-ai/dsh-my-cap-local'
|
|
144
|
+
- name: '@deepseek-ai/dsh-tool-my-cap'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 设计要点
|
|
148
|
+
|
|
149
|
+
- **不要预防性拆分**:只有角色需要独立演进时,才使用不同包。简单的工具插件无需拆分。
|
|
150
|
+
- **Service Definition 拥有 Request/Result 类型**:Service Provider 和 Consumer 只依赖 Service Definition 包。
|
|
151
|
+
- **显式优于隐式**:实现应通过显式的 `resolve(request): Spec` 步骤处理默认值,而不是在 `run()` 中隐藏 `?? default`。
|
|
152
|
+
|
|
153
|
+
## 下一步
|
|
154
|
+
|
|
155
|
+
- [LLM(大语言模型)适配器](./llm-adapter.md):实现一个 LLM 提供方
|
|
@@ -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/user/develop/practice/llm-adapter.md
|
|
5
|
+
llm-adapter.md: 882e82d880ac622cf886c6c24e75a1987e1c6702
|
|
6
|
+
llm-adapter.zh.md: 27c480af2a19a68ac35900a2ce1b5e9dbdc85bf8
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# LLM adapters
|
|
2
|
+
|
|
3
|
+
English | [中文](llm-adapter.zh.md)
|
|
4
|
+
|
|
5
|
+
This guide connects a new LLM provider to Harness.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
An LLM adapter extends `LlmAdapter` and implements `stream()`, translating Harness's provider-neutral request into a provider API call and translating the response back into Harness chunks.
|
|
10
|
+
|
|
11
|
+
## Minimal implementation
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
15
|
+
import Schema from '@deepseek-ai/schemastery'
|
|
16
|
+
import { LlmAdapter, type GenerateOptions, type StreamChunk } from '@deepseek-ai/dsh-llm'
|
|
17
|
+
|
|
18
|
+
class MyAdapter extends LlmAdapter {
|
|
19
|
+
private apiKey: string
|
|
20
|
+
|
|
21
|
+
constructor(apiKey: string) {
|
|
22
|
+
super()
|
|
23
|
+
this.apiKey = apiKey
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
|
|
27
|
+
// 1. Convert options.messages to the provider format.
|
|
28
|
+
// 2. Call the streaming API.
|
|
29
|
+
// 3. Convert the response into StreamChunk values.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface Config {
|
|
34
|
+
apiKey: string
|
|
35
|
+
providers: string[]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const Config: Schema<Config> = Schema.object({
|
|
39
|
+
apiKey: Schema.string().required(),
|
|
40
|
+
providers: Schema.array(Schema.string()).required(),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export const name = 'my-llm-adapter'
|
|
44
|
+
export const inject = ['llm']
|
|
45
|
+
|
|
46
|
+
export function apply(ctx: Context, config: Config) {
|
|
47
|
+
const adapter = new MyAdapter(config.apiKey)
|
|
48
|
+
ctx.llm.registerAdapter(config.providers, adapter)
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## StreamChunk protocol
|
|
53
|
+
|
|
54
|
+
`stream()` yields chunks using this protocol:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { CallId, type StreamChunk } from '@deepseek-ai/dsh-llm'
|
|
58
|
+
|
|
59
|
+
async function* exampleChunks(): AsyncIterable<StreamChunk> {
|
|
60
|
+
// 1. Start each content block with block-start.
|
|
61
|
+
yield { type: 'block-start', index: 0, blockType: 'text' }
|
|
62
|
+
|
|
63
|
+
// 2. Stream text through text-delta.
|
|
64
|
+
yield { type: 'text-delta', index: 0, text: 'Hello' }
|
|
65
|
+
yield { type: 'text-delta', index: 0, text: ' world' }
|
|
66
|
+
|
|
67
|
+
// 3. End each content block with block-end and the complete block.
|
|
68
|
+
yield {
|
|
69
|
+
type: 'block-end',
|
|
70
|
+
index: 0,
|
|
71
|
+
block: { type: 'text', text: 'Hello world' },
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 4. Tool-call block.
|
|
75
|
+
yield { type: 'block-start', index: 1, blockType: 'tool-call' }
|
|
76
|
+
yield {
|
|
77
|
+
type: 'tool-call-delta',
|
|
78
|
+
index: 1,
|
|
79
|
+
id: CallId('call-123'),
|
|
80
|
+
name: 'bash',
|
|
81
|
+
argumentsDelta: '{"command":"ls"}',
|
|
82
|
+
}
|
|
83
|
+
yield {
|
|
84
|
+
type: 'block-end',
|
|
85
|
+
index: 1,
|
|
86
|
+
block: {
|
|
87
|
+
type: 'tool-call',
|
|
88
|
+
id: CallId('call-123'),
|
|
89
|
+
name: 'bash',
|
|
90
|
+
arguments: '{"command":"ls"}',
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 5. Token usage.
|
|
95
|
+
yield { type: 'usage', usage: { inputTokens: 100, outputTokens: 50 } }
|
|
96
|
+
|
|
97
|
+
// 6. Finish reason.
|
|
98
|
+
yield { type: 'finish', reason: { kind: 'stop' } }
|
|
99
|
+
// Alternatively, { kind: 'tool-calls' } requests tool execution.
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Key rules
|
|
104
|
+
|
|
105
|
+
- Every `block-start` has a matching `block-end`.
|
|
106
|
+
- `index` increases from 0 and identifies content-block order.
|
|
107
|
+
- A `tool-call-delta` carries raw JSON text in `argumentsDelta`, either all at once or over multiple chunks.
|
|
108
|
+
- `finish` is the final chunk.
|
|
109
|
+
- Emit `usage` before `finish`.
|
|
110
|
+
|
|
111
|
+
## GenerateOptions
|
|
112
|
+
|
|
113
|
+
`stream()` receives the exported `GenerateOptions` type. It includes the model, adapter-owned reasoning-effort id, conversation history, system prompt, tool schemas, generation parameters, stop sequences, and abort signal; treat the TypeScript type exported by `@deepseek-ai/dsh-llm` as authoritative. Map supported fields to the provider API. If the provider cannot honor a field, throw `LlmError` with a stable code instead of silently dropping it.
|
|
114
|
+
|
|
115
|
+
Override `resolveModel(provider, model, signal?)` to return exact provider/model identity plus optional `context` and `reasoning` metadata in one lookup. Reasoning metadata contains ordered opaque ids and display names plus an optional configured default; preserve the adapter's authoritative selectable list, including `off` when its upstream capability API returns it, instead of promoting those values into a core enum. Honor the optional signal for asynchronous lookup so cancellation and disposal reach quiescence. The service validates the aggregate and rejects unsupported explicit efforts before `stream()`; omitting `reasoning` means that model has no selectable reasoning-effort capability.
|
|
116
|
+
|
|
117
|
+
## Register an adapter
|
|
118
|
+
|
|
119
|
+
```ts ignore-check
|
|
120
|
+
ctx.llm.registerAdapter(['my-provider'], adapter)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The first argument lists provider routes handled by the adapter. `GenerateOptions.provider` selects the registered adapter, while `GenerateOptions.model` passes an adapter-owned model id without lifecycle registration. Override `listModels()` when the adapter can advertise model choices to selectors.
|
|
124
|
+
|
|
125
|
+
## Use it from cordis.yml
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
- id: my-llm
|
|
129
|
+
name: './src/my-llm-adapter.ts'
|
|
130
|
+
config:
|
|
131
|
+
apiKey: !!js process.env.MY_API_KEY
|
|
132
|
+
providers:
|
|
133
|
+
- my-provider
|
|
134
|
+
|
|
135
|
+
- id: agent-loop
|
|
136
|
+
name: '@deepseek-ai/dsh-agent-loop'
|
|
137
|
+
config:
|
|
138
|
+
agents:
|
|
139
|
+
- id: main
|
|
140
|
+
provider: my-provider
|
|
141
|
+
model: my-model-v1
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Reference implementations
|
|
145
|
+
|
|
146
|
+
The repository contains complete implementations:
|
|
147
|
+
|
|
148
|
+
- `packages/llm/llm-deepseek/` — DeepSeek API adapter using the OpenAI-compatible format
|
|
149
|
+
- `packages/llm/llm-pi-ai/` — Pi AI adapter using a different API format
|
|
150
|
+
|
|
151
|
+
Compare the two shipped adapters to see the same harness contract implemented over different provider SDKs.
|
|
152
|
+
|
|
153
|
+
## Error handling
|
|
154
|
+
|
|
155
|
+
Adapters throw transport and protocol failures as `LlmError` values with stable codes. The agent loop preserves the error and code for diagnostics and policy; it does not convert an ordinary `Error` automatically. Every provider HTTP request must also merge `attributionHeaders()` and forward `options.signal`.
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import {
|
|
159
|
+
attributionHeaders,
|
|
160
|
+
LlmAdapter,
|
|
161
|
+
LlmError,
|
|
162
|
+
type GenerateOptions,
|
|
163
|
+
type StreamChunk,
|
|
164
|
+
} from '@deepseek-ai/dsh-llm'
|
|
165
|
+
|
|
166
|
+
class HttpAdapter extends LlmAdapter {
|
|
167
|
+
constructor(private readonly endpoint: string) {
|
|
168
|
+
super()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
|
|
172
|
+
const response = await fetch(this.endpoint, {
|
|
173
|
+
method: 'POST',
|
|
174
|
+
headers: {
|
|
175
|
+
'content-type': 'application/json',
|
|
176
|
+
...attributionHeaders(),
|
|
177
|
+
},
|
|
178
|
+
body: JSON.stringify({ model: options.model, messages: options.messages }),
|
|
179
|
+
...options.signal ? { signal: options.signal } : {},
|
|
180
|
+
})
|
|
181
|
+
if (!response.ok) {
|
|
182
|
+
throw new LlmError(`Provider API error: ${response.status}`, 'PROVIDER_HTTP_ERROR')
|
|
183
|
+
}
|
|
184
|
+
// A real adapter parses the response and emits the complete chunk sequence.
|
|
185
|
+
yield { type: 'finish', reason: { kind: 'stop' } }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|