怎么给 DeepSeek Harness 写个插件
æä¹ç» DeepSeek Harness å个æä»¶
ppshuX 2026-08-15 0 é 读10åéæä¹ç» DeepSeek Harness å个æä»¶
仿å°ä¸è¡æ¥å¿å¼å§ï¼æ
text_statsæ³¨åææ¨¡åå¯ä»¥ä¸»å¨è°ç¨ç Toolã
2026 å¹´ 8 æ 15 æ¥ï¼æç»å弿ºç DeepSeek Harness åäºä¸ä¸ªå¾å°çæä»¶ï¼ç»è®¡ä¸æ®µæåçå符æ°ååè¯æ°ã
æå䏿¬¡æµè¯æ¶ï¼ææ²¡æåè¯æ¨¡åå·¥å ·å«ä»ä¹ï¼åªé®å®ï¼
请帮æç»è®¡ä¸é¢è¿å¥è¯æå¤å°ä¸ªå符åå¤å°ä¸ªåè¯ï¼
Everything is a Plugin
DSH èªå·±éæ©äº text_statsï¼ä¼ å
¥åæï¼åæç»æäº¤å模åï¼22 个å符ï¼4 个åè¯ã
è¿å°±æ¯æ¬æçç®æ ãåç¡®å°è¯´ï¼æä»¬è¦åçæ¯ä¸ä¸ª Tool ç±»åç Pluginï¼Plugin è´è´£æè½åè£
è¿ DSHï¼text_stats Tool è´è´£ç»è®¡æåã宿åä¼çä¸å è½½æ¥å¿ãçå® Tool call å Trajectory ä¸ç±»è¯æ®ï¼å®ä»¬åå«éªè¯ä¸åç¯èã
1. è¿æ¬¡è¦åç Pluginï¼å°åºæ¯ä»ä¹ï¼
DeepSeek 宿¹æ Harness çè®¾è®¡æ¦æ¬ä¸º Everything is a Pluginã宿¹ä¸ææç¨ç»åºçå®ä¹å¾å
·ä½ï¼Plugin æ¯ä¸ä¸ªå¯¼åº apply 彿°ç TypeScript 模åãDSH å è½½æ¨¡åæ¶è°ç¨ apply(ctx)ï¼æä»¶åéè¿ ctx 注åè½åã
æ¬æä¸»è¦åè䏤份宿¹ææ¡£ï¼
å æä¸¤ä¸ªå®¹ææ··æ·çè¯åå¼ã
- Plugin æ¯è£
é
åå
ãDSH å¯å¨æ¶å è½½å®ï¼å¹¶æ§è¡å®å¯¼åºç
apply(ctx)ã - Tool æ¯ä¸é¡¹å ·ä½è½åãPlugin æ Tool 注åè¿ DSH åï¼æ¨¡åæè½åç°å¹¶è°ç¨å®ã
æ¬ç¯ä¼åä¸ä¸ª Tool ç±»åç Pluginï¼åè®©å®æ³¨å text_stats Toolãå
³ç³»å¦ä¸ï¼
DSH å¯å¨
â å è½½ Plugin
â æ§è¡ apply(ctx)
â Plugin 注å text_stats
â æ¨¡åéè¿ Tool call è°ç¨ text_stats
è¿ä¹è§£éäºä¸ºä»ä¹å颿¢è¦ç plugin loadedï¼åè¦ç Tool callï¼
- ç»ç«¯åºç°
plugin loadedï¼åªè¯æ DSH æ¾å°äº Pluginï¼å¹¶æ§è¡äºapply()ã - 对è¯åºç°
Tool call · text_statsï¼æè¯æè¿ä¸ª Plugin æä¾çè½åå·²ç»æ³¨åæåï¼å¯ä»¥è¢«æ¨¡å使ç¨ã
Tool call 䏿¯ææ Plugin çéç¨éªæ¶æ¹æ³ã 妿 Plugin çå¬äºä»¶ï¼å°±åºè¯¥è§¦åäºä»¶æ£æ¥ååºï¼å¦æå®æä¾ Serviceï¼å°±åºè¯¥è°ç¨ Serviceï¼å¦æå®åªè´è´£æ¥å¿ï¼æ£æ¥æ¥å¿å³å¯ãæ¬æç Tool callï¼æ¯å 为æä»¬åçæ°å¥½æ¯ Tool ç±»åç Pluginã
æä»¬ä¼å
åä¸ä¸ªåªæå°æ¥å¿ç Pluginï¼ç¡®è®¤å è½½é¾è·¯æ²¡é®é¢ï¼éåå¨åä¸ä¸ª Plugin éæ³¨å text_stats Toolãè¿æ ·åºéæ¶å®¹æå®ä½ï¼ä¸ä¼æâæä»¶æ²¡å è½½âåâå·¥å
·æ²¡æ³¨åâæ··å¨ä¸èµ·ã
2. å ææºç ç DSH è·èµ·æ¥
è¿æ¬¡éè¦ä»æºç è¿è¡ Harnessï¼å 为æä»¬è¦è®©å®å è½½æ¬å° TypeScript æä»¶ã䏿¯ä¸ºäºä¿®æ¹ DSH æ ¸å¿ä»£ç ã
æ¬æåºå®å°æå®é
è·éçæäº¤ 47f9438ãè¿ä¸ªæäº¤çæ ¹ package.json æ 记为 0.1.0-rc.5ï¼è¦æ± Node.js ^22.19.0 || >=24.0.0ï¼å¹¶å£°æ pnpm 11.7.0ãDSH ä»å¤äº Developer Previewï¼åºå®æäº¤è½åå°ä¸»åæ¯å¿«éåå带æ¥çå¹²æ°ã
å å¨ PowerShell æ£æ¥ç¯å¢ï¼
node -v
git --version
corepack --version
çä¸å°çæ¬å·æ¶å
è¡¥é½å¯¹åºç¯å¢ãNode.js å»ºè®®ç´æ¥ä½¿ç¨å®æ¹è¦æ±ççæ¬ï¼å¦æ corepack pnpm æ æ³æ§è¡ï¼å¯ä»¥è¿è¡ corepack enableï¼åéæ°æå¼ç»ç«¯ã
æ¥çå éä»åºå¹¶åå°å®æµæäº¤ï¼
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd .\deepseek-harness
git checkout 47f9438
git rev-parse --short HEAD
git checkout ååºç° detached HEAD æç¤ºå¾æ£å¸¸ï¼è¿éæ¯å¨å¤ç°åºå®çæ¬ï¼ä¸æ¯å¨è¿ä¸ªåæ¯ç»§ç»å¼å DSHã
å®è£ ãæ£æ¥ãæå»ºä¾æ¬¡æ§è¡ï¼
corepack pnpm install
corepack pnpm run typecheck
corepack pnpm run build
å®è£
è¿ç¨ä¸å¯è½åºç° Linux ä¸ç¨å
䏿¯æ Windowsãworkspace 循ç¯ä¾èµç WARNãè¦åæåæ¬èº«ä¸çäºå¤±è´¥ï¼ä»¥å½ä»¤æ¯å¦æ£å¸¸ç»æãåç» typecheck å build è½å¦å®æä¸ºåã
å ä¸è¦åæä»¶ï¼å¯å¨åç Web UIï¼
corepack pnpm dsh web
ç»ç«¯æå° http://127.0.0.1:3080 åï¼å¨æµè§å¨æå¼è¿ä¸ªå°åã确认页é¢å¯ä»¥è¿å
¥ï¼ååå°ç»ç«¯æ Ctrl+C 忢æå¡ã
æåæ å¿ï¼ åç Web UI è½æå¼ï¼è¯´ææºç ãä¾èµåæå»ºé¾è·¯é½æ£å¸¸ãåé¢è¥åºéï¼èå´å°±ç¼©å°å°äºæä»¬ç Pluginã
æå°æéï¼ typecheck æ build æ¥éæ¶å
æ ¸å¯¹ git rev-parse --short HEAD å Node.js çæ¬ï¼ä¸è¦å¸¦ç失败继ç»å¯å¨ã
3. åä¸ä¸ªåªä¼æå°æ¥å¿çæå° Plugin
å¨ä»åºæ ¹ç®å½åå»ºä¸´æ¶æä»¶ç®å½ï¼
New-Item -ItemType Directory -Path .\scratch-plugin\src -Force
ç¨ VS Code æå¼å½åä»åºï¼
code .
å¦æç³»ç»ä¸è®¤è¯ codeï¼ç´æ¥ä» VS Code çâæå¼æä»¶å¤¹âéæ© deepseek-harness å³å¯ã
å建 scratch-plugin/src/my-plugin.tsï¼
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(_ctx: Context) {
console.log('[hello-plugin] plugin loaded!')
}
è¿éå 认è¯ä¸ä¸ªä¸è¥¿ï¼
nameæ¯ Plugin èªå·±çååãapply()æ¯ DSH å è½½æä»¶æ¶è°ç¨çå ¥å£ãctxæ¯æä»¶è¿æ¥ Harness è½åçä¸ä¸æï¼ç¬¬ä¸çè¿æ²¡ç¨å°ï¼æä»¥åæ_ctxã
æè¿å¨ scratch-plugin/tsconfig.json å äºä¸é¢çé
ç½®ï¼
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"noEmit": true,
"composite": false,
"incremental": false,
"declaration": false,
"declarationMap": false
},
"include": ["src/**/*.ts"]
}
è¿ä¸ªæä»¶æ¹ä¾¿ VS Code ç»§æ¿ä»åºç TypeScript é ç½®å¹¶æ£æ¥æä»¶ä»£ç ãDSH ç宿¹æå°æç¨æ²¡æè¦æ±å®ï¼Plugin loader ä¹ä¸é å®å®ä½æ¨¡åï¼ä¸æ³å¤çç¼è¾å¨æç¤ºæ¶ï¼å¯ä»¥å è·³è¿ã
æåå建 scratch-plugin/cordis.ymlã宿åçç®å½åºè¯¥æ¯ï¼
scratch-plugin/
ââ cordis.yml
ââ tsconfig.json
ââ src/
ââ my-plugin.ts
4. ç¨ cordis.yml æ Plugin æè¿ Web UI
å å¨ä»åºæ ¹ç®å½å徿件æä»¶çç»å¯¹è·¯å¾ï¼
(Get-Item .\scratch-plugin\src\my-plugin.ts).FullName
æè¾åºæ¿æ¢å° cordis.yml ç nameï¼
- insert:
- id: hello
name: 'C:/ä½ çè·¯å¾/deepseek-harness/scratch-plugin/src/my-plugin.ts'
宿¹æç¨å½åè¦æ±è¿é使ç¨ç»å¯¹è·¯å¾ãWindows è·¯å¾å¯ä»¥åæä¸é¢çæ£ææ å½¢å¼ï¼é¿å YAML 转ä¹å¸¦æ¥çå°æ°ãä¸è¦ç §æä½è çµèçç¨æ·ååç®å½ã
æçåå§å®éªæªå¾é使ç¨äº file:///C:/... å½¢å¼ï¼å¹¶ä¸å¨æäº¤ 47f9438 䏿åå è½½ã为äºå宿¹æç¨ä¿æä¸è´ï¼è¯»è
å¤ç°æ¶ä¼å
使ç¨ä¸é¢çç»å¯¹è·¯å¾åæ³ã
带çè¿å±é ç½®å¯å¨ Web UIï¼
corepack pnpm dsh web --patch ./scratch-plugin/cordis.yml
çå°ä¸é¢ä¸¤è¡ï¼æå° Plugin å°±å è½½æåäºï¼
[hello-plugin] plugin loaded!
dsh web: http://127.0.0.1:3080
注æï¼è¿æ¶åªè¿äºâå è½½å
³âãplugin loaded åªè¯æ my-plugin.ts 被 DSH å è½½ãapply() å·²æ§è¡ï¼è¿ä¸ªçæ¬è¿æ²¡ææ³¨å任使¨¡åå¯ä»¥è°ç¨ç Toolã
--patch 伿 cordis.yml ä½ä¸ºæåä¸å±é
ç½®å å å° Web profileãæä»¬æ²¡ææ¹ DSH æ ¸å¿æºç ï¼åªå¨å¯å¨æ¶æå
¥èªå·±ç模åã
æå°æéï¼ æ²¡åºç°æ¥å¿æ¶å æ£æ¥ YAML 缩è¿åç»å¯¹è·¯å¾ãä¿®æ¹ Plugin åè¦åæ¢å¹¶éæ°å¯å¨å½ä»¤ï¼åçº¯å·æ°æµè§å¨ä¸ä¼éæ°å è½½ç»ç«¯è¿ç¨ã
5. æ Plugin å级æ text_stats Tool
ç°å¨å¾ Plugin è¿ä¸ªè£
é
åå
éæ¾å
¥ç¬¬ä¸é¡¹è½åï¼text_stats Toolãæ¿æ¢ my-plugin.tsãè¿æ®µä»£ç æ¯ç¬¬ä¸çé¿ï¼ä½æ¯ä¸é¨å齿æç¡®ç¨éï¼å¯ä»¥ç´æ¥å¤å¶ï¼
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'text-stats-tool'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register(
defineTool({
name: 'text_stats',
description:
'Count the number of characters and whitespace-separated words in a piece of text.',
parameters: {
text: {
type: 'string',
required: true,
description: 'The text to analyze',
},
},
output: {
schema: {
type: 'object',
additionalProperties: false,
properties: {
characters: {
type: 'integer',
required: true,
},
words: {
type: 'integer',
required: true,
},
},
},
render: (_args, value) => [
{
type: 'text',
text: `characters: ${value.characters}\nwords: ${value.words}`,
},
],
},
async execute(args) {
const characters = Array.from(args.text).length
const trimmed = args.text.trim()
const words = trimmed ? trimmed.split(/\s+/).length : 0
return {
characters,
words,
}
},
}),
)
}
å æä½å ä¸ªå ³é®ç¹ï¼
inject = ['tools']ï¼ç Tool Registry 就绪ååå è½½è¿ä¸ª Pluginãctx.tools.register(...)ï¼ææ°è½åç»è®°è¿ DSHãnameådescriptionï¼åè¯æ¨¡åå·¥å ·å«ä»ä¹ãè½è§£å³ä»ä¹é®é¢ãparametersï¼è§å®è°ç¨æ¶å¿ é¡»ä¼ å ¥å符串textï¼ä¸åè¦æ±çåæ°ä¼è¢«æ¦ä¸ãexecute()ï¼è¿éæä¼çæ£è¿è¡ TypeScript ç»è®¡ä»£ç ãoutputï¼å 声æè¿åå¼ç»æï¼åéè¿renderæç»æäº¤ç»æ¨¡åé 读ã
宿¹ææ¡£ä¹å¼ºè°äºè¿æ¡é¾è·¯ï¼defineTool æ ¹æ® parameters æ¨å¯¼å¹¶æ ¡éªåæ°ï¼execute è¿å output.schema 声æçå¼ï¼output.render åæç»æè½¬æ¢ä¸ºæ¨¡åå¯ç¨çå
容ã
è¿ä¸ª Tool ç»è®¡çæ¯ Unicode ç ç¹æ°éï¼ç©ºæ ¼ä¹ç®å符ï¼âåè¯âæç©ºç½åéãå®é忬æçè±æéªè¯å¥ï¼ä¸æ¯ä¸æåè¯å¨ï¼ä¹ä¸ä¼æå¸¦ç»å符å·çå形彿ä¸ä¸ªè§è§å符ã
ä¿å代ç ï¼åæ¢æ§è¿ç¨ï¼åéæ°å¯å¨ï¼
corepack pnpm dsh web --patch ./scratch-plugin/cordis.yml
6. å æç¡®æå® Toolï¼æé¤æ³¨åé®é¢
å è½½æ¥å¿å·²ç»è¯æ Plugin è½è¿ DSHï¼ä½æç»çæ¬çèè´£æ¯æ³¨å text_statsãå æ¤è¿è¦éè¿ä¸æ¬¡çå® Tool call éªè¯å®æä¾çè½åï¼èä¸è½åå¨ plugin loadedã
ç¬¬ä¸æ¬¡æµè¯æç¡®è¦æ±ä½¿ç¨ text_statsï¼å
æé¤æ³¨åé®é¢ï¼ä¸èéªæ¨¡åä¼ä¸ä¼èªä¸»éæ©ãæå·¥å
·åååè¿æç¤ºè¯ï¼
è¯·ä½¿ç¨ text_stats å·¥å
·ç»è®¡ä¸é¢è¿æ®µæåï¼
hello deepseek harness
è¿æ¬¡å®é
åºç°äº Tool call · text_statsï¼è¾å
¥åè¾åºå¦ä¸ï¼
IN
{
"text": "hello deepseek harness"
}
OUT
characters: 22
words: 3
è¿ä¸æ¥éªè¯çæ¯ Plugin æä¾çè½åï¼Tool 已注åãæ¨¡åè½åèµ· Tool callãexecute() è¿åäºé¢æç»æã
妿坹è¯åªææ¨¡åèªå·±è®¡ç®ççæ¡ï¼æ²¡æ Tool call · text_statsï¼å
åå°ç»ç«¯ç¡®è®¤ Plugin å·²éå¯ï¼åæ£æ¥ injectãctx.tools.register å Tool åç§°ãä¸è¦æ¥çè¿å
¥ä¸ä¸æ¥ã
7. ä¸ç¹å Toolï¼ç模åä¼ä¸ä¼èªå·±é
æ°å»ºä¸ä¸ªä¼è¯ï¼è¿æ¬¡åªæè¿°ä»»å¡ï¼
请帮æç»è®¡ä¸é¢è¿å¥è¯æå¤å°ä¸ªå符åå¤å°ä¸ªåè¯ï¼
Everything is a Plugin
å¼å¤´å±ç¤ºçç»ææ¥èªè¿æ¬¡æµè¯ãæç¤ºè¯é没æ text_statsï¼æ¨¡åä»ç¶éæ©äºå®ï¼
Tool call · text_stats · Everything is a Plugin
characters: 22
words: 4
è¿æ¯æ¾å¼è°ç¨å¤è¯æäºä¸å±ï¼æ¨¡åçå°äº Tool çåç§°ãæè¿°ååæ°ï¼å¹¶å¤æå®éåå½åä»»å¡ã
æªå¾ä¸ä½¿ç¨çæ¯æ¬æ¬¡å®éªé ç½®çæ¨¡åãæ¨¡åæ ç¾ä¸æ¯æ¬æçå®è£ è¦æ±ï¼å¤ç°æ¶ä½¿ç¨ä½ å·²ç»å¨ DSH 䏿£ç¡®é ç½®ãè½å¤å®æ Tool call çæ¨¡åå³å¯ãAPI Key åªå¡«å¨èªå·±çé ç½®çé¢ï¼ä¸è¦åè¿ Pluginãæªå¾ææäº¤è®°å½ã
8. æåç Trajectoryï¼ç¡®è®¤è°ç¨é¾æ²¡æèè¡¥
è天åºå·²ç»æ¾ç¤º Tool callï¼åæå¼ä¸æ¹ç Trajectoryãéæ© text_stats è¿ä¸æ¡è®°å½ï¼å¯ä»¥çå°ï¼
Status: Completed- Payload ä¸çåå§
text - Result ä¸ç
charactersåwords - Tool schema 䏿§è¡èæ¶
å°è¿éï¼æ´æ¡é¾è·¯å¯ä»¥å¤æ ¸ï¼
ç¨æ·æåºä»»å¡
â æ¨¡åéæ© text_stats
â Harness è°ç¨ execute()
â Tool è¿åç»è®¡ç»æ
â æ¨¡åç»ç»æç»åç
Trajectory æ¯è¿æ¬¡å®éªææä»·å¼çè¯æ®ãè天åçåªè½è¯´ææ¨¡å说äºä»ä¹ï¼Trajectory è½ç¡®è®¤å®å®é è°ç¨äºåªä¸ªå·¥å ·ãä¼ äºä»ä¹ãæ¿å°äºä»ä¹ã
9. è·é以åï¼æä¹çè§£âä¸åçæä»¶âï¼
è¿æ¬¡åªåäºä¸ä¸ªå åè¡ç Toolï¼ä½å®æ¹å£å·å·²ç»è½å°ä»£ç ä¸ï¼Plugin éè¿ ctx æ¥å
¥ Harnessï¼ctx.tools æä¾ Tool Registryï¼æ¨¡åå¨éè¦æ¶éæ©æä»¬ç»è®°çè½åã
æ¬ææ æåå¨è¿éã宿¹æç¨è¿æä¾èªå¨æ¸ çãæä»¶é ç½®ãæå¡ä¸ä¾èµãäºä»¶åçå½å¨æçå 容ï¼ç¬¬ä¸æ¬¡å®è·µä¸éè¦ä¸èµ·å¡è¿æ¥ã
å
³éå®éªæ¶ï¼å¨è¿è¡ DSH çç»ç«¯æ Ctrl+Cãscratch-plugin å¯ä»¥ççç»§ç»æ¹ï¼ä¹å¯ä»¥å¨ç¡®è®¤ä¸åéè¦ååç¬å½æ¡£ã
æ¬æ¬¡éå ³æ ååæä¸ä¸ªå±çº§ï¼
- å è½½è¯æ®ï¼ç»ç«¯åºç°
[hello-plugin] plugin loaded!ï¼è¯æ Plugin 被å è½½ã - è½åè¯æ®ï¼å¯¹è¯ä¸åºç°çå®ç
Tool call · text_statsï¼è¯æå®æ³¨åç Tool å¯ä»¥ä½¿ç¨ã - æ§è¡è®°å½ï¼Trajectory çè¾å ¥åç»æä¸èå¤©çæ¡ä¸è´ï¼è¯æè°ç¨è¿ç¨å¯ä»¥å¤æ ¸ã
䏿¡é½æ»¡è¶³ï¼ä½ 就宿äºä¸ä¸ªçæ£å¯ç¨ç DeepSeek Harness Tool ç±»å Pluginã
Aitishiku.com