DeepSeek Harness 可组合的插件运行时&一切皆插件
DeepSeek Harness å¯ç»åçæä»¶è¿è¡æ¶ï¼ä¸åçæä»¶
Cosolar 2026-08-14 94 é 读29å鿬æç»å
deepseek-harnessä»åºæºç ä¸å®æ¹docs/cordis-tutorial/æç¨ç¼åï¼å¹¶å¨æåä¸ç« ä¸ Claude CodeãCodex 以å AgentScopeï¼é¿éï¼ åæ·±åº¦å¯¹æ¯ã读å®ä½ åºè½ï¼çè§£ Harness ç设计å²å¦ãè·éä»âHello æä»¶âå°âçå®ç¼ç Agentâç宿´é¾è·¯ãçæcordis.ymlç»åä¸ HMRï¼å¹¶æ¸ æ¥å®ä¸å ¶ä»ä¸»æµæ¡æ¶çåºå«ã
ä¸ãDeepSeek Harness æ¯ä»ä¹
1.1 ä¸å¥è¯å®ä¹
DeepSeek Harness æ¯ DeepSeek 宿¹åºåç Agentï¼æºè½ä½ï¼è¿è¡æ¡æ¶ãå®ä¸æ¯ä¸ä¸ªâåæ»ç婿âï¼èæ¯ä¸ä¸ªå¯ç»åçæä»¶è¿è¡æ¶ï¼ä½ ç¨ä¸ä»½ YAML é
ç½®æä»¶ï¼cordis.ymlï¼æâä¼è¯ç®¡çãç³»ç»æç¤ºè¯ãå·¥å
·ãLLM éé
å¨ãæä»¶è®¿é®ãåè¿ç¨ãæ²ç®±ãä¹è³ agent ä¸»å¾ªç¯æ¬èº«âçå
¨é¨è½ååæç§¯æ¨ä¸æ ·æ¼èµ·æ¥ã
å®çåºå±æ¯ä¸ä¸ªå为 Cordis çå¾®åæä»¶æ¡æ¶ï¼æºç vendored å¨ vendor/cordis/ï¼ãCordis æä¾ä¸ä¸ªå
±äº«ç Contextï¼ä¸ä¸æï¼ï¼æ¯ä¸ªè½å齿¯ä¸ä¸ªæè½½å° ctx ä¸çæä»¶ã
ä¸å¥è¯å®ä½ï¼
Claude Code æ¯â产åâï¼DeepSeek Harness æ¯âæ¡æ¶âï¼AgentScope æ¯âå¼ååºâã åè ç»ä½ ä¸ä¸ªå¼ç®±å³ç¨çç¼ç 婿ï¼Harness ç»ä½ ä¸å¥å¯ä»¥èªç±æ¼è£ ãèªæç®¡ãå¯åµå ¥èªå·±äº§åç Agent 弿ï¼è AgentScope ç»ä½ ä¸å¥ä»¥ Python 为主çâæå»ºæºè½ä½åºç¨çåºâï¼ä¾§é夿ºè½ä½ä¸å·¥ç¨åå·¥å ·é¾ã
1.2 å¤ç»´åº¦æè§£ï¼å®å°åºæ¯ä»ä¹
è¦çæ£çè§£ Harnessï¼éè¦ä»äºä¸ªç»´åº¦åæ¶çå®ï¼
| 维度 | 宿¯ä»ä¹ | åä¾ï¼å®ä¸æ¯ä»ä¹ï¼ |
|---|---|---|
| 交ä»å½¢æ | ä¸å¥æ¡æ¶ + ä¸ç»å®æ¹æä»¶ + ä¸ä¸ª CLI/ACP å ¥å£ | ä¸ä¸ªå°éãå¼ç®±å³ç¨ç产å |
| å æ ¸èå¼ | åºäº Cordis çæä»¶è¿è¡æ¶ï¼ä¸åçæä»¶ | ä¸ä¸ªç¡¬ç¼ç é»è¾çåä½ç¨åº |
| ç»åæ¹å¼ | 声æå¼ cordis.yml é
置驱å¨ãæ id è£
é
| å½ä»¤å¼ä»£ç é new å®ä¾ |
| è½åè¾¹ç | æ½è±¡æå¡ï¼Service Definitionï¼+ 坿¿æ¢ Provider + æ¶è´¹è | æå®ç°ç»èåæ»å¨è°ç¨æ¹ |
| éç¨èå´ | å¯èªæç®¡ãå¯åµå ¥èªæäº§åãå¯é¿æä¼è¯ | ä» ç»ç«¯äº¤äºç婿 |
1.3 设计æè·¯ï¼ä¸ºä»ä¹è¿ä¹è®¾è®¡ï¼æ ¸å¿åæï¼
DeepSeek Harness éåâä¸åçæä»¶âç设计æè·¯ãæä»¬éç¨æä»¶å¼å¼æ¾æ¶ææ¥æå»º Agent Harnessï¼æ¨¡åãå·¥å ·ãæè½ãä¼è¯ãæ²ç®±ãåå¨ã循ç¯ãè°åº¦ãUI çææ Agent è½ååç±æä»¶ç»åèæï¼å¯èªç±æ¿æ¢ãçµæ´»éç»ã
Harness çè®¾è®¡ä¸æ¯â为äºå¯ææè坿æâï¼èæ¯å´ç»å 个æç¡®çå·¥ç¨ç®æ ä¸çº¦æååºçç³»ç»æ§åèãä¸é¢éæ¡åæã
æè·¯ä¸ï¼ç¨âä¸åçæä»¶âæ¶é¤ç¡¬ç¼ç ç循ç¯é»è¾
ç»å¤§å¤æ°ç¼ç 婿ç agent 主循ç¯ï¼call model â run tools â repeatï¼æ¯åæ»å¨æ ¸å¿éçãHarness çåç´è§å³å®æ¯ï¼æ´ä¸ªä»åºåªæ dsh-agent-loop ä¸ä¸ªå
å
å«å
·ä½å¾ªç¯é»è¾ï¼packages/core/agent-loop/README.md æç¡®å¦æ¤ï¼ï¼å
¶ä½å
¨æ¯æ½è±¡æå¡ææ©å±ç¹æä»¶ã
è®¾è®¡å¨æºï¼
- 循ç¯åªæè¿°â驱å¨åè®®âï¼ä¸æºå¸¦å
·ä½è½åãhooksãsandboxãplan modeãretryãsubagentãcompaction çè¡ä¸ºå
¨é¨éè¿çå¬
agent/*ãtools/*ãsession/*äºä»¶å®ç°ï¼èéæ¹å¾ªç¯ä»£ç ã - è¿å¸¦æ¥âè¡ä¸ºå¨æ©å±ç¹ä¸ãä¸å¨å¾ªç¯éâç硬约æââ
AGENTS.mdåè¯ï¼âPlugins, not loop changes: new behavior goes on documented extension points; changingagent-looprequires updating docs/architecture.md.â - åºå±åçï¼å½å¾ªç¯æä¸ºå¯ä¸ä¸ç¨³å®ç驱å¨è ï¼ææå¯åè¡ä¸ºé½è¢«æ¨å°äºä»¶è®¢é ä¾§ï¼äºæ¯è½åçå¢å =æä»¶çæè½½/å¸è½½ï¼ä¸ä¸»å¾ªç¯å½»åºè§£è¦ã
æè·¯äºï¼è½ååå±çâä¸è§è²â模åï¼capability-seamï¼
æ¯ä¸ªè½åè¢«å»æææä¸ä¸ªç¸äºç¬ç«æ¼åçè§è²ï¼è§ docs/glossary.md#capability-seamï¼ï¼
- Service Definitionï¼æå¡å®ä¹ï¼ï¼æ¥æ
ctx.<key>ä¸è¯æ±è¡¨ç±»åç CordisServiceï¼æ¯æ½è±¡ç±»æå ·ä½æ³¨å表ï¼å¦ShellExecutorãWebRuntimeï¼ï¼ç»ä¸æ¯ TypeScriptinterfaceââå 为å®è¦ä½ä¸ºç宿å¡è¢«æè½½ã - Service Providerï¼æå¡æä¾è
ï¼ï¼ä¸ç§æå¤ç§å®ç°ï¼å¦
dsh-shell-local/dsh-shell-pwshã - Consumerï¼æ¶è´¹è
ï¼ï¼æ³¨å
¥è¯¥æå¡ãé¢åæ¨¡åæ´é²å·¥å
·çæä»¶ï¼å¦
dsh-tool-bashã
è®¾è®¡å¨æºï¼
- è§è²ç¬ç«æ¼åï¼å½åªæ provider éè¦æ¢ï¼æ¬å°âæ²ç®±âE2Bï¼æ¶ï¼å®ä¹åæ¶è´¹è 代ç ä¸è¡é½ä¸ç¨å¨ãè¿æâååâéå¶å¨æçªçè¾¹çå ã
- 以 shell 为ä¾ï¼
dsh-shellï¼å®ä¹ï¼âdsh-shell-local/dsh-shell-pwshï¼providerï¼æå¹³å°disabledï¼+dsh-bash-sandboxï¼æ²ç®± policyï¼ãLLM åçï¼dsh-llmï¼å®ä¹ï¼âdsh-llm-deepseekï¼åçï¼/dsh-llm-pi-aiï¼å¤ provider åªçï¼ã - Swappable capabilityï¼seam æ¯â宿´è½åâï¼ä¸æ¯å个è§è²ââææ¡£ç¹å«å¼ºè°âreserve the term for that meaningâï¼å 为误ææä¸è§è²å½è½åï¼ä¼å¯¼è´æ¶è´¹è ç´æ¥ä¾èµå®ç°èç ´å坿¿æ¢æ§ã
æè·¯ä¸ï¼æ³¨åå³å¯ä½ç¨ï¼effectï¼ï¼æçå½å¨æäº¤ç»æ¡æ¶
AGENTS.md éå¾ï¼âRegistrations are effects: every contribution goes through ctx.effect() / ctx.on(); a registry's register() returns the disposer.â
è®¾è®¡å¨æºï¼
- æä»¶ä¸ææèªå·±èµæºçâæé¤è´£ä»»â ã任使³¨åï¼
ctx.tools.registerãctx.onãåæä»¶ãæå¡å®ä¾ï¼é½éçå¨è°ç¨å®çæä»¶ä¸ï¼æä»¶å¸è½½æ¶èªå¨æ¤éã ctx.plugin(child)让ä¸ä¸ªæä»¶æå¦ä¸ä¸ªæä»¶æä¸ºâåâï¼ç¶åä¸èµ· disposeï¼éå½å¸è½½ã- åºå±åçï¼èµæºæææ = æä»¶çå½å¨æï¼èéæå¨
if忝ãè¿ä»æºå¶ä¸æ¶çäºâå¿è®°ç§»é¤çå¬å¨/å ³é宿¶å¨âè¿ç±»èµæºæ³æ¼ââdocs/defensive-patterns.mdæâDispose must reach quiescenceâå为头å·ç¼ºé·ç±»è§åï¼æé¤è¦å¼æ¥ await å°çæ£éæ¢ï¼è䏿¯åªåä¸ä¸ª killã
æè·¯åï¼ä¾èµæ³¨å ¥æ¯âæç»è·è¸ªâï¼èé䏿¬¡æ§æ£æ¥
æ¶è´¹æ¹å inject: ['tools']ï¼Cordis ä¼è®©æä»¶ä¿æ PENDING ç´å° ctx.tools åå¨ï¼ä¸è¿è¡æè¥æå¡æ¶å¤±ï¼provider 被å¸è½½/çæ¿æ¢ï¼ï¼ä¾èµæ¹éä¹å¸è½½ï¼æå¡æ¢å¤ååå è½½ã
è®¾è®¡å¨æºï¼
- é
ç½®å¯æ¿æ¢æå¡ï¼å¸è½½
dsh-shell-localãæè½½å¦ä¸ä¸ªshellproviderï¼ææinject: ['shell']çæä»¶èªå¨éå¯ç¨æ°å®ç°ââè¿å°±æ¯âæ¡æ¶çº§çæ¿æ¢âçç©çåºç¡ã - é¡ºåºæ å
³ï¼
cordis.ymléæä»¶è¡åºä¸å½±åæ£ç¡®æ§ï¼åªå½±å就绪å åãå½»åºç§»é¤ææå¡åï¼ä¾èµæ¹ä¿æ PENDINGï¼æ¢ä¸å´©æºä¹ä¸ä¼åè¿è¡ã - åºå±åçï¼ä¾èµå¾æ¯è¿è¡æ¶å¨ææ»¡è¶³çï¼èéæå»ºæéæç»å®ï¼å æ¤ç»åï¼compositionï¼æ¬èº«æ¯æ°æ®ï¼YAMLï¼ï¼ä¸æ¯ä»£ç ã
æè·¯äºï¼â模åå¯è§ ⺠已记å½âç审计约æ
AGENTS.md 硬约æï¼âModel-visible ⺠logged: anything that reaches a model request must be reconstructable from the session log; a new model-visible input requires a session event.â
è®¾è®¡å¨æºï¼
- ä»»ä½é达模åçè¾å ¥ï¼å·¥å ·ç»æãç³»ç»æç¤ºè¯åçãåéï¼é½å¿ 须对åºä¸æ¡ä¼è¯äºä»¶ï¼ä½¿å¾ä¼è¯æ¥å¿å³çç¸ï¼source of truthï¼ ââå¯ä»¥åæ¾ã审计ãforkãresumeã
- ä¼è¯æ¯ä¸çå
¬æ°ï¼
sessionï¼JSONL/SQLite æä¹ åãæå½±ãè¡ç¼ï¼ãsession-queryï¼SQLite å ¨ææ£ç´¢ï¼ãcompactionï¼å缩+å·¥å ·ç»æè£åªï¼å ±åæ¯æé¿æè®°å¿ä¸åè§ã - åºå±åçï¼æâå¯é建æ§âä¸åä¸ºæ¶æä¸åéï¼èéä¾èµå¼åè èªè§ãè¿ä½¿å¾è°è¯ä¸ä¸ªé误åç = 鿾飿¡ä¼è¯äºä»¶æµï¼è䏿¯çæµæ¨¡å彿¶âçå°äºä»ä¹âã
æè·¯å ï¼æ¾å¼ä¼äºéå¼ï¼éåææ¥ï¼ç»ä¸éé»
AGENTS.md å¤é¡¹è§åï¼
- âMisconfiguration fails loud at load when self-contained, otherwise at the earliest resolvable point; never silently skip a missing referent.â
- âNo hardcoded tunables in plugins: deployment-varying choices are validated
Configfields changeable from cordis.yml.â - 跨边çä¸éæ id ç¨
Branded<B>åçç±»åï¼é裸stringï¼åªå¨æ ¡éªè¾¹çï¼configãæ¨¡å/å·¥å · JSONãæä»¶ãworkerãè¿ç¨ã线ï¼åè¿è¡æ¶æ ¡éªï¼åè¿ç¨ç±»åè¾¹çä¿¡ä»» TypeScriptã
è®¾è®¡å¨æºï¼
- å¯é¨ç½²æ§æ¥èªâå¯å项齿¯å¯æ ¡éªç Configâï¼èé代ç é
?? defaultçéèé»è®¤å¼ï¼é£æ¯å议常é/å®å ¨ä¸åéæåºå®çï¼ã - å¯è¯ææ§æ¥èªâ缺å¼ç¨å°±ææ¥âï¼é¿å âæä»¶æ²¡ååºå´ä¸ç¥é为ä»ä¹âï¼è§æç¨ç¬¬ä¹ç« è¯æå¨ï¼ã
- åºå±åçï¼æâé¨ç½²å·®å¼âä¸âå®å ¨ä¸åéâ两类ååå离ââåè è¿ Config å schema æ ¡éªï¼åè åæ»ä¸ä¸å¯è¢«é ç½®ç»è¿ã
æè·¯ä¸ï¼å®å ¨æ¯åå±çï¼èéåç¹
docs/defensive-patterns.md ç»åºå
·ä½è§åï¼
- çæå½ä»¤æ¿å°çæ¯æ¸
æ´è¿çç¯å¢ï¼ä¸¢å¼
*KEY*/*SECRET*/*TOKEN*/*PASSWORD*ï¼ï¼é²æ¢ harness åæ®æ³æ¼è¿è¾åºæ spill æä»¶ã - 临æ¶/spill æä»¶ç¨ç§æï¼0700ï¼ç®å½ãéæºåãç¬å owner-only æå¼ï¼
'wx'ã0o600ï¼ï¼é¿å å¯é¢æµè·¯å¾å¯¼è´ç symlink ç«äºä¸æ³é²ã - æ²ç®±æ¯ä¸çè½åï¼
sandboxï¼bwrap/Landlock/Seatbeltï¼ï¼æ§è¡ä¸æä»¶ç³»ç»è®¿é®é½å¯å¥æ²ç®± policyã
è®¾è®¡å¨æºï¼æâæ§è¡ä¸å¯ä¿¡è¾åºâå½å¤´çå¨èï¼ä»ç¯å¢ãæä»¶ãè¿ç¨ä¸å±åæ¶è®¾é²ï¼èéä¾èµâç¨æ·å«è·å¥æªå½ä»¤âç约å®ã
1.3.1 ä¸åçæä»¶è®¾è®¡
1.3.2 å¤ç§è¿è¡æ¨¡å¼
é对ä¸åç使ç¨åºæ¯ï¼DeepSeek Harness æä¾åç§æ¨¡å¼ï¼æ¯ç§æ¨¡å¼ä¼é»è®¤å è½½ä¸åçæä»¶éåï¼
- æ 忍¡å¼ï¼æä¾å®æ´çå·¥å ·ç»åï¼
- PTC 模å¼ï¼ç¨åºåå·¥å ·è°ç¨ï¼Programmatic Tool Callingï¼ï¼ç±æ¨¡åçæç䏿®µä»£ç æ¥ç»åå¤è½®å·¥å ·è°ç¨ï¼
- æç®æ¨¡å¼ï¼ä» ä¿çä¸ä¸ª shell å·¥å ·ä¸ä¸ä¸ªæä»¶ç¼è¾å·¥å ·ï¼ç¨äºæå°ç¯å¢ä¸ç模ååºåæµè¯ï¼
- åé æ¨¡å¼ï¼å¯ä»¥æ£æ¥å½åè¿è¡æ¶ãå¨å åä¸è¯éª Cordis æä»¶ï¼å¹¶æ®æ¤ç»ååå使°ç模å¼ã
1.4 è¿ä¸ä¸ªæè·¯å¦ä½æ¶æä¸ºä¸ä¸ªç³»ç»
æä»¥ä¸ä¸ç¹ä¸²èµ·æ¥ï¼Harness ç设计主线æ¯ï¼
ç¨æä»¶è¿è¡æ¶ï¼Cordisï¼æ¿è½½ä¸åè½åï¼ç¨âæ½è±¡æå¡ + 坿¿æ¢ providerâé离ååï¼ç¨ effect æçå½å¨æäº¤ç»æ¡æ¶ï¼ç¨æ³¨å ¥çå¨ææ»¡è¶³å®ç°é 置驱å¨çç»åï¼ç¨äºä»¶æè¡ä¸ºæ¨å°æ©å±ç¹ï¼ç¨ä¼è¯æ¥å¿ä½ä¸ºå¯é建ççç¸ï¼ç¨æ¾å¼æ ¡éªä¸å®å ¨åå±å®ä½é¨ç½²ä¸æ§è¡è¾¹çã
å®å æ¤åç°åºä¸ Claude Code / Codexï¼äº§åï¼ãAgentScopeï¼Python å¼ååºï¼æªç¶ä¸åçååï¼åè å ³å¿âç¨æ·å¼ç®±å³ç¨âï¼åè å ³å¿âç ç©¶è å¿«éæå¤æºè½ä½âï¼è Harness å ³å¿çæ¯ âå¹³å°/产åå·¥ç¨å¸å¦ä½å¯é å°èªæç®¡å¹¶é¿ææ¼åä¸ä¸ª Agent åºåº§â ãè¿ä¹æ¯ä¸ºä»ä¹å®çå·¥ç¨çºªå¾æä¸¥ï¼100% è¦ççé¨ç¦ãtype-equiv ææ¡£åæ¥ãåçç±»åã声æå¼ surfaceï¼ï¼å 为åºåº§çå¯é æ§æ¯ä¸å±ä¸åçåæã
äºãæ ¸å¿å¿æºæ¨¡åï¼ä¸åçæä»¶
第ä¸ç« åçäºâ为ä»ä¹è¿ä¹è®¾è®¡âï¼ä¸æ¡æè·¯ + è®¾è®¡å¨æºï¼ï¼æ¬ç« åçâå®å®é æä¹è·èµ·æ¥âï¼å¹¶ç¨ä¸å¼ æ´ä½æ¶æå¾æè¿ä¸æ¡æè·¯è½å°ç©çç»æä¸ãå¦æä½ è·³è¿äºç¬¬ä¸ç« ï¼åªéè®°ä½ä¸å¥è¯ï¼Harness éæ²¡æâåæ»ç婿âï¼ææè½å齿¯æå¨å ±äº«
ctxä¸çæä»¶ã
DeepSeek Harness åºäºå ·ææ¶ç©ºå¯ç»åæ§ç Cordis æä»¶ç³»ç»æå»ºãCordis å æ¡æ¶åªè´è´£æä»¶çå è½½ä¸å¸è½½ä»¥åä¾èµå ³ç³»ï¼Agent Harness çææå ·ä½ç»ä»¶é½æ¯ä¸åç Cordis æä»¶ãæä»¶éè¿ Cordis æå¡ä¸äºä»¶å½¼æ¤åä½ï¼å¹¶å¯ä»¥å¨é ç½®å±èªç±ç»åã
å¼åè æ éæ¹å¨ DeepSeek Harness çæºç æ¬èº«ï¼å°±è½ä»¥æä»¶çæ¹å¼ç¬ç«éæ©ãæ¿æ¢ææ©å±å ¶ä¸çä»»ä¸è½åãè¿å°±æ¯ DeepSeek Harness æéè¦ç设计ååï¼ä¸åçæä»¶ã
æ´ä¸ªä»åºéµå¾ªä¸æ¡éå¾ï¼è§ AGENTS.mdï¼ï¼
Everything is a plugin. ä¸åçæ¯æä»¶ã
è¿æå³çï¼
- å·¥å
·æ¯æä»¶ï¼
dsh-toolsï¼ - 大è¯è¨æ¨¡åéé
卿¯æä»¶ï¼
dsh-llm+ DeepSeek providerï¼ - æä»¶ç³»ç»è®¿é®æ¯æä»¶ï¼
dsh-fsï¼ - shell / åè¿ç¨ / ç»ç«¯æ¯æä»¶ï¼
dsh-shell/dsh-subprocess/dsh-terminalï¼ - è¿ agent 主循ç¯ï¼agent-loopï¼æ¬èº«é½æ¯å¯æ¿æ¢çæä»¶ï¼
dsh-agent-loopï¼
æææä»¶å
±äº«åä¸ä¸ª ctxï¼éè¿ä¸ç§æºå¶åä½ï¼
| æºå¶ | å ³é®å | ä½ç¨ |
|---|---|---|
| ä¾èµæ³¨å ¥ | inject: ['tools'] | æä»¶å£°æå®ä¾èµææå¡ï¼Cordis å¨è¯¥æå¡å°±ç»ªååå¯å¨å® |
| 注å / effect | ctx.effect() / ctx.on() | æä»¶è´¡ç®è½åï¼æ³¨åå·¥å ·ãçå¬äºä»¶ï¼ï¼å¸è½½æ¶èªå¨æ¤é |
| äºä»¶ | ctx.on(event, cb) / ctx.waterfall() | è§£è¦çæä»¶é´éä¿¡ |
å ³é®è®¾è®¡ï¼æ³¨åæ¯âå¯ä½ç¨âï¼effectï¼ ãæ¯ä¸ªè´¡ç®é½éè¿
ctx.effect()å®æï¼æä»¶å¸è½½æ¶è´¡ç®èªå¨æ¤éãè¿æ¯ Cordis çå½å¨æç®¡ççæ ¸å¿ï¼ä¹æ¯å®åºå«äºâæå¨ç®¡çå ¨å±åä¾âç±»æ¡æ¶ï¼å¦å¾å¤ Python agent åºï¼çæ ¹æ¬ç¹ã
2.1 æ´ä½æ¶æå¾ï¼åºäºæºç ï¼
ä¸å¾ä¾æ® packages/bundle/base/cordis.patch.ymlï¼base bundle ç 45+ 个 id è¡ï¼ä¸ packages/core/agent-loop/README.mdï¼agent-loop 注å
¥ç 5 个æå¡ï¼ç»å¶ï¼åæ çå®ç»åå
³ç³»ï¼èé示æã
graph TB
subgraph RUNTIME["Cordis è¿è¡æ¶ (vendor/cordis)"]
ROOT["æ ¹ Context\n(å
񄧮 ctx)"]
LOADER["Loader æä»¶\n读 cordis.yml / --profile è¡¥ä¸å±"]
HMR["@cordis-plugin-hmr\næä»¶åæ´çéè½½"]
TIMER["@cordis-plugin-timer"]
end
subgraph CORE["æ ¸å¿èæ¢ (packages/core + base bundle)"]
AGENTLOOP["dsh-agent-loop\n(ctx.agentLoop)\nå¯ä¸å
·ä½å¾ªç¯é©±å¨"]
AGENT["dsh-agent\n(ctx.agents å·¥å)"]
TOOLS["dsh-tools\n(ctx.tools 注å表)"]
LLM["dsh-llm\n(ctx.llm æ½è±¡ + DeepSeek provider)"]
SYSPROMPT["dsh-system-prompt\n(ctx.systemPrompt)"]
SESSION["dsh-session\n(ctx.session æä¹
å/æå½±)"]
end
subgraph DRIVE["agent-loop 注å
¥ç 5 个æ¥å£æå¡(æ¥èª README)"]
AGENTLOOP -.注å
¥.-> AGENT
AGENTLOOP -.注å
¥.-> SESSION
AGENTLOOP -.注å
¥.-> LLM
AGENTLOOP -.注å
¥.-> TOOLS
AGENTLOOP -.注å
¥.-> SYSPROMPT
end
subgraph EXEC["æ§è¡ / æ²ç®±è½å (Provider æä»¶)"]
SHELL["dsh-shell-local / dsh-shell-pwsh"]
SUBPROC["dsh-subprocess-local"]
SANDBOX["dsh-sandbox-local\n+ sandbox-policy"]
FS["dsh-tool-fs / fs-search\n(dsh-fs-sandbox)"]
TERMINAL["terminal / code-runtime"]
end
subgraph MODEL["模å / æ£ç´¢è½å"]
WEB["dsh-web (web_search)"]
DEEPSEEK["dsh-llm-deepseek\n(åçéé
å¨)"]
PIAI["dsh-llm-pi-ai\n(å¤ provider åªç)"]
RETRY["dsh-llm-retry"]
end
subgraph ORCH["ç¼æ / åä»»å¡è½å"]
SUBAGENT["dsh-subagent\n(spawn / fork provider)"]
WORKFLOW["dsh-workflow\n(worker-thread)"]
JOBS["dsh-jobs-local"]
TODO["dsh-tool-todo"]
GOAL["dsh-goal / command-goal"]
end
subgraph SESS["ä¼è¯ / 人æºåä½"]
PERSIST["session-persistence-jsonl"]
QUERY["session-query-sqlite\n(å
¨ææ£ç´¢, å¯é)"]
PROJ["session-projection"]
COMPACT["compaction-basic\n+ tool-result-pruner"]
APPROVAL["user-approval + permission-presets"]
INTERACT["interaction / commands / plan-mode"]
end
subgraph EXT["æ©å± / äºæä½"]
SKILL["dsh-skill + tool-skill"]
HOOKS["hooks-claude-code / hooks-codex\n(Hook äºæä½æ¡¥æ¥)"]
ACP["dsh-acp\n(èªå¨ååè®®æå¡å¨)"]
EXTENSIONS["extensions\n(agent èªä¿®æ¹æä»¶)"]
BUNDLE["dsh-bundle\n(--profile è¡¥ä¸å±)"]
end
%% é
置驱å¨å è½½
LOADER -->|"æ id è£
é
\næå¡å°±ç»ªå³æ¿æ´»"| CORE
LOADER --> EXEC
LOADER --> MODEL
LOADER --> ORCH
LOADER --> SESS
LOADER --> EXT
HMR --> LOADER
%% å·¥å
·æ³¨å: è½åæä»¶æå·¥å
·æ³¨åè¿ ctx.tools
SHELL --> TOOLS
FS --> TOOLS
WEB --> TOOLS
SUBAGENT --> TOOLS
WORKFLOW --> TOOLS
TODO --> TOOLS
SKILL --> TOOLS
%% 模åé¾è·¯
DEEPSEEK --> LLM
PIAI --> LLM
RETRY --> LLM
%% ä¼è¯é¾è·¯
PERSIST --> SESSION
QUERY --> SESSION
PROJ --> SESSION
COMPACT --> SESSION
%% äºä»¶æ»çº¿(è§£è¦æä»¶éä¿¡)
EVENTS{{"äºä»¶æ»çº¿\nagent/* · tools/result · agent/request\napproval/request · session/event"}}
AGENTLOOP --> EVENTS
TOOLS --> EVENTS
SHELL --> EVENTS
APPROVAL --> EVENTS
SANDBOX --> EVENTS
INTERACT --> EVENTS
%% å
¥å£
ENTRY["CLI (pnpm dsh)\n/ ACP / JSON-RPC å
¥å£"]
ENTRY --> ROOT
BUNDLE --> LOADER
2.2 å¾ä¸å ³ç³»å¯¹ç §æºç 说æ
1. âä¸åçæä»¶âçç©çå½¢æ
- å¯å¨å¨ =
node --import tsx ../../vendor/cordis/bin.jsï¼å®åªå建 rootContextå¹¶æè½½ Loaderã - Loader 读å
cordis.ymlæ--profileè¡¥ä¸å±ï¼dsh-bundleï¼ãbase bundle å¨packages/bundle/base/cordis.patch.ymléç¨ 45+ 个idè¡å£°æäºå ¨é¨é»è®¤æä»¶ï¼è¡åºæ å ³ï¼æ¿æ´»ç±âæå¡å¯ç¨æ§â驱å¨ï¼ã - æ¯ä¸è¡å°±æ¯ä¸ä¸ªæä»¶ï¼
idï¼å¦agent-loopãtoolsãllm-deepseekï¼æ¯ stable æ è¯ï¼åç»è¡¥ä¸å±æidè¦çå®ã
2. agent-loop æ¯å¯ä¸çâå ·ä½å¾ªç¯â
- æ®
dsh-agent-loop/README.mdï¼æ´ä¸ª harness åªæè¿ä¸ä¸ªå å å«å ·ä½å¾ªç¯é»è¾ï¼å ¶ä»å ¨æ¯æ½è±¡æå¡ææ©å±ç¹æä»¶ã - 宿³¨å
¥å¹¶ä¾èµ 5 个æ¥å£æå¡ï¼
agentsãsessionsãllmãtoolsãsystemPromptï¼å¾ä¸è线ï¼ãè¿ 5 ä¸ªé½æ¯ctxä¸çæå¡ï¼å ·ä½ provider å¯çæ¿æ¢ã - âcall model â run tools â repeatâä¹å¤çææè¡ä¸ºï¼hooksãsandboxãplanãretryãsubagentãcompactionï¼é½éè¿çå¬
agent/*ãtools/*ãsession/*äºä»¶å®ç°ââè¿å°±æ¯å¾ä¸çäºä»¶æ»çº¿ã
3. å·¥å ·æ¯â注åâèéâ硬ç¼ç â
bashãfsãwebãsubagentãworkflowãtodoãskillçæ§è¡/ç¼ææä»¶ï¼éè¿ctx.tools.register(...)ï¼effectï¼æå·¥å ·æè¿dsh-tools注å表ï¼åç± agent-loop å¨tools/resultçäºä»¶éæ¶è´¹ã两æä»¶äºä¸ç¥å¯¹æ¹åå¨ã
4. Provider 坿¿æ¢ä¸è§è²
- 以 shell 为ä¾ï¼
dsh-shellï¼å®ä¹ï¼âdsh-shell-local/dsh-shell-pwshï¼providerï¼æå¹³å°disabledï¼+dsh-bash-sandboxï¼æ²ç®± policyï¼ãLLM åçï¼dsh-llmï¼å®ä¹ï¼âdsh-llm-deepseekï¼åçï¼/dsh-llm-pi-aiï¼å¤ provider åªçï¼ã
5. èªä¿®æ¹ä¸äºæä½
extensions让 agent è¿è¡æ¶è£ è½½/å¸è½½æä»¶ï¼hooks-claude-code/hooks-codexæ¡¥æ¥å¤é¨ Hookï¼acpæ´é²èªå¨ååè®®æå¡å¨ãè¿äºé½å¨ base bundle ä¹å¤ï¼æéå å ã
å¾ä¸
dsh-agent-loopç 5 æ¡èçº¿æ³¨å ¥ãdsh-toolsç 7+ æ¡å·¥å ·æ³¨åã--profileè¡¥ä¸å±è£ é ï¼åç´æ¥æ¥èªpackages/bundle/base/cordis.patch.ymlä¸packages/core/agent-loop/README.mdçæºç äºå®ã
ä¸ãç¯å¢åå¤ï¼5 åéï¼
3.1 ä½ éè¦å ç¥éçèæ¯ï¼æ°æå¿ 读ï¼
æ¬æç¤ºä¾ç¨ TypeScript åæä»¶ï¼ä½ä¸éè¦ä½ ç²¾é TSãåªè¦çè§£ä¸é¢åç¹å³å¯ï¼
- ESM ä¸
importï¼ä»£ç ç¨import { x } from 'pkg'å¼å ¥ä¾èµï¼æ¬æææç¸å¯¹å¯¼å ¥é½å¸¦.tsåç¼ï¼å¦'./hello.ts'ï¼ï¼è¿æ¯ Cordis loader ç约å®ã - workspace å
åï¼
@deepseek-ai/cordisã@deepseek-ai/dsh-toolsçæ¯ä»åºå é¨ç npm å åï¼pnpm workspace è§£æï¼ï¼ä¸æ¯ä»ç½ç»ä¸è½½çãimport type { Context } from '@deepseek-ai/cordis'å°±æ¯ä» Cordis åç±»åã cordis.ymlæ¯ YAML åè¡¨ï¼æ¯ä¸ª- name: ...æ¯ä¸é¡¹æä»¶ï¼ç¼©è¿ç¨ä¸¤ä¸ªç©ºæ ¼ï¼ä¸è¦æ··ç¨ Tabãctxæ¯ä»ä¹ï¼è´¯ç©¿å ¨æçctxæ¯ Cordis çå ±äº«ä¸ä¸æï¼æææä»¶éè¿å®æ³¨åè½åä¸çå¬äºä»¶ãä½ å¯ä»¥æå®å½æâæ´ä¸ªè¿è¡æ¶çæ»æ¥çº¿æ¿âã
3.2 ç¯å¢åç½®æ¡ä»¶
åç½®æ¡ä»¶ï¼è¯¦è§ docs/development.mdï¼ï¼
- Node.js 22.19+ æ 24+ï¼CI è¦ç 22.19 / 24 / 26ï¼
- pnpmï¼å¯ç¨ Corepackï¼
corepack enableï¼ï¼ä»åºéå®pnpm@11.7.0 - Git 2.26+
- å¯éï¼DeepSeek API Keyï¼
DEEPSEEK_API_KEYï¼ï¼ä» çå®è·æ¨¡åæ¶éè¦ï¼æ¬æç¨ç¬¬ä¸è³ç¬¬åç« ï¼å« HMR ä¸å·¥å ·ç®¡çº¿ï¼å®å ¨æ å¯é¥å¯è¿è¡
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run typecheck # éªè¯ç¯å¢å°±ç»ª
å建æç¨ä¸´æ¶ç®å½ï¼tmp/ 已被 git 忽ç¥ï¼ä¸ä¼è¢«æäº¤ï¼ï¼
mkdir -p tmp/cordis-tutorial
cd tmp/cordis-tutorial
åç»ææç¤ºä¾é½ä»è¿åä¸ä¸ªç®å½è¿è¡ï¼
node --import tsx ../../vendor/cordis/bin.js
è¿ä¸ªåæä»¶å¯å¨å¨ä¼ï¼â åå»ºæ ¹ Contextï¼â¡ æè½½ Loader æä»¶ï¼â¢ ä»å½åç®å½è¯»å ./cordis.yml å¹¶å è½½éé¢ååºçæ¯ä¸ªæä»¶ãæ éä»»ä½æå»ºæ¥éª¤ï¼--import tsx 让 Node ç´æ¥è· TSï¼ã
åã卿ï¼ä½ ç第ä¸ä¸ªæä»¶
4.1 åæä»¶
å¨ tmp/cordis-tutorial ä¸å建 hello.tsï¼
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello'
export function apply(ctx: Context) {
console.log('hello from my first plugin')
}
- æä»¶éè¿å½å导åº
apply彿°è¢« loader æè½½ã ctxæ¯ Cordis ä¸ä¸æï¼æä»¶éè¿å®æ³¨åææè´¡ç®ãnameæ¯å¯éæ¾ç¤ºåï¼ç¨äºè¯æä¿¡æ¯ã
4.2 ç»ååºç¨
å建 cordis.ymlï¼
- name: './hello.ts'
è¿æ¯ä¸ä¸ªé
置项å表ãname æ¯æ¨¡åæå®ç¬¦ï¼ç¸å¯¹è·¯å¾æ npm å
åï¼ã
4.3 è¿è¡
node --import tsx ../../vendor/cordis/bin.js
è¾åºï¼
hello from my first plugin
4.4 ä¸ç§æä»¶å½¢æ
import { Service, type Context } from '@deepseek-ai/cordis'
// 1. 彿°æä»¶ï¼æå¸¸ç¨ï¼
export function apply(ctx: Context) {}
// 2. 对象æä»¶ï¼å¸¦ apply æ¹æ³ç对象
export const objectPlugin = { name: 'obj', apply(ctx: Context) {} }
// 3. ç±»æä»¶ï¼Service åç±»ï¼éè¦å
¬å¼æå¡æ¶ç¨ï¼è§ç¬¬å
ç« ï¼
export class MyService extends Service {
constructor(ctx: Context) { super(ctx, 'myService') }
}
æ°æå»ºè®®ï¼å¨éè¦å ¬å¼æå¡ä¹åï¼ä¸å¾ä½¿ç¨å½æ°å½¢æã
4.5 容éè¡ä¸ºï¼æ°æå¿ ç¥ï¼
- è¥æä»¶
applyæé â è¿ç¨ç´æ¥å´©æºå¹¶æ¥éï¼ä¸ä¼éé»è·³è¿ï¼ã - è¥
cordis.ymléçæ¨¡åè·¯å¾/å åæ¼éï¼è§£æå¤±è´¥ï¼â Cordis åªéè¿ logger æ¥åï¼ä¸ä¼å´©æºãæ°æä»¶âæ²¡ååºâæ¶ï¼å æ£æ¥æ¼åã
äºãçå½å¨æä¸ effectï¼èµæºèªå¨åæ¶ï¼
Cordis æä»¶å¯è½å ä¿®æ¹é
ç½®ãçéè½½ãæ¾å¼èµæºéæ¾ææéæå¡æ¶å¤±èå¸è½½ãéè¿ Cordis API 建ç«ç注åå±äº effectï¼ä¼å¨æå±æä»¶å¸è½½æ¶æ¤éï¼å¨è¿äº API ä¹å¤ç®¡ççèµæºå¿
é¡»å
è£
å¨ ctx.effect() ä¸ã
å建 lifecycle.tsï¼
import type { Context } from '@deepseek-ai/cordis'
export const name = 'lifecycle-demo'
function heartbeat(ctx: Context) {
console.log('heartbeat plugin loading')
ctx.effect(() => {
const timer = setInterval(() => console.log('tick'), 200)
return () => {
clearInterval(timer)
console.log('heartbeat cleaned up')
}
})
}
export function apply(ctx: Context) {
const fiber = ctx.plugin(heartbeat)
ctx.effect(() => {
const timer = setTimeout(async () => {
await fiber.dispose()
console.log('disposed')
process.exit(0)
}, 700)
return () => clearTimeout(timer)
})
}
è¿è¡åè¾åºï¼
heartbeat plugin loading
tick / tick / tick
heartbeat cleaned up
disposed
ä¸ç¹å ³é®ï¼
ctx.plugin(heartbeat)æä¸ä¸ªæ¥èªä»£ç ç彿°æè½½ä¸ºæä»¶ï¼ä¸ YAML loader 为æ¯ä¸ªé 置项åçå®å ¨ä¸è´ãè°ç¨è¿å fiberââå·²å è½½æä»¶å®ä¾çè¿è¡æ¶å¥æã- effect 主ä½å¨å è½½æé´è¿è¡ï¼è¿åç disposer å¨å¸è½½æé´è¿è¡ãçå½å¨æä¸æä»¶ä¸è´çèµæºï¼ä½ ç»ä¸éè¦æå¨è°ç¨ disposerã
fiber.dispose()ä¼ç该æä»¶æææ¸ çï¼å«å¼æ¥ disposerï¼å®æåæç»æï¼å¹¶éå½å¸è½½å®æè½½çåæä»¶ã
Fiber ç¶ææº
æ¯ä¸ªå·²å è½½æä»¶å®ä¾é½æ fiberï¼å¨ä»¥ä¸ç¶æé´è½¬æ¢ï¼
PENDING â LOADING â ACTIVE â UNLOADING â DISPOSED
â FAILED
- PENDINGï¼å·²å£°æï¼ä½æéæå¡å°ä¸å¯ç¨ï¼è§ç¬¬å ç« ï¼ã
- LOADING / ACTIVEï¼
applyæ£å¨è¿è¡ï¼å·²å®æã - FAILEDï¼
applyæé ç½®æ ¡éªæå¼å¸¸ã - UNLOADING / DISPOSEDï¼disposer æ£å¨è¿è¡ï¼å·²æé¤ã
å·²ç»æ¯ effect çæä½ï¼ä½ å¾å°éè¦æå ctx.effect()ï¼
ctx.on(event, listener)ï¼çå¬å¨éæä»¶å¸è½½èªå¨ç§»é¤ãctx.plugin(child)ï¼åæä»¶éç¶æä»¶ä¸å disposeã- æå¡æ³¨åãharness 注å表ï¼å¦
ctx.tools.register(...)ï¼çè¿å disposer é½éçå¨è°ç¨æä»¶ä¸ï¼èªå¨æ¤éã
é¡ºåºæ³¨æï¼disposer ææ³¨åéåºå¯å¨ï¼ä½å¤ä¸ªå¼æ¥ disposer å¹¶åè¿è¡ï¼è¥æé¤å¿ é¡»æé¡ºåºï¼è¯·ææ¥éª¤æ¾è¿åä¸ä¸ª disposer å 便¬¡ awaitsã
å ãæå¡ï¼Serviceï¼ï¼è½åçæ³¨å䏿¶è´¹
æå¡æ¯æä»¶æä¾ãå
¶ä»æä»¶éè¿ ctx æ¶è´¹çå
·åè½åãå¨ harness ä¸ï¼ctx.toolsãctx.llmãctx.agents 齿¯æå¡ãæ¶è´¹æ¹åªæå® 'tools' è¿æ ·çè½ååï¼èä¸å¯¼å
¥æä¾æ¹ââå æ¤é
ç½®å¯ä»¥éæ©æä¾æ¹ï¼æ 鿹卿¶è´¹æ¹ä»£ç ã
6.1 æä¾æå¡
greeter.tsï¼
import { Service, type Context } from '@deepseek-ai/cordis'
declare module '@deepseek-ai/cordis' {
interface Context {
greeter: GreeterService
}
}
export class GreeterService extends Service {
constructor(ctx: Context) {
super(ctx, 'greeter')
}
greet(who: string) {
return `Hello, ${who}!`
}
}
export const name = 'greeter'
export function apply(ctx: Context) {
ctx.plugin(GreeterService)
}
两é¨åååï¼
- è¿è¡æ¶ï¼
super(ctx, 'greeter')以åç§°greeter注åå®ä¾ï¼ctx.greeteréå¤å¯è®¿é®ï¼æ³¨åå±äº effectï¼å¸è½½æ¶ç§»é¤ã - ç¼è¯æ¶ï¼
declare moduleç¨ TS 声æåå¹¶ægreeterå å ¥Contextæ¥å£ï¼ä½¿æ¶è´¹æ¹è·å¾ç±»åå®å ¨ï¼æ æ¤å£°æè¿è¡æ¶ä»å·¥ä½ï¼ä½å¤±å»ç±»åï¼ã
6.2 æ¶è´¹æå¡ï¼injectï¼
consumer.tsï¼
import type { Context } from '@deepseek-ai/cordis'
export const name = 'consumer'
export const inject = ['greeter']
export function apply(ctx: Context) {
console.log(ctx.greeter.greet('world'))
}
inject ååºè¯¥æä»¶éè¦çæå¡ãCordis ä¼è®©æä»¶ä¿æ PENDING ç´å°æ¯é¡¹æå¡é½åå¨ï¼å æ¤å¨ apply å
å¯ä¿è¯ ctx.greeter 已就绪ââå è½½é¡ºåºæ å
³ç´§è¦ã
- name: './greeter.ts'
- name: './consumer.ts'
è¾åº Hello, world!ã交æ¢ä¸¤è¡é¡ºåºè¾åºä¸åï¼è¥å½»åºç§»é¤ greeter.tsï¼ææ¼éå
åï¼ï¼æ¶è´¹æ¹ä¼ä¿æ PENDING / å¯å¨å¤±è´¥ââ宿¢ä¸å´©æºãä¹ä¸ä¼å¨ä¾èµç¼ºå¤±æ¶åè¿è¡ï¼èæ¯æç¡®åå¨çå¾
ç¶æï¼è¯æå¨è§ç¬¬ä¹ç« ï¼ã
æ¯è¯åºåï¼æ¬ä¾
export const name = 'consumer'æ¯æä»¶æ¾ç¤ºåï¼inject: ['greeter']éçgreeteræ¯æå¡åï¼ç±super(ctx, 'greeter')注åï¼ãäºè å½å空é´ä¸åââæä»¶å¯ä»»æååï¼ä½æ³¨å ¥å¿ 须精确å¹é æå¡åï¼å¦åæ°¸è¿ PENDINGã
6.3 inject æ¯æç»è·è¸ªï¼èé䏿¬¡æ§æ£æ¥
è¥è¿è¡æé´æéæå¡æ¶å¤±ï¼å¦æä¾æ¹è¢«å¸è½½ãçæ¿æ¢ï¼ï¼æ¯ä¸ªä¾èµæä»¶ä¼éä¹å¸è½½ï¼æå¡æ¢å¤ååå è½½ãç»å effectï¼è¿é²æ¢æ¶è´¹æ¹ä¿ç对ä¸å¯ç¨æå¡çå¼ç¨ã乿£æ¯é
ç½®è½æ¿æ¢æå¡çåå ï¼å¸è½½ dsh-shell-localãæè½½å¦ä¸ä¸ª shell æä¾æ¹ï¼ææ inject: ['shell'] çæä»¶ä¼éå¯å¹¶ç¨æ°å®ç°ã
6.4 å¯éä¾èµ
inject æ¯ç¡¬æ§ä¾èµã缺失ä»å¯å·¥ä½æ¶è·³è¿ inject å¹¶æ¢æµï¼
export function apply(ctx: Context) {
const greeter = ctx.get('greeter')
console.log(greeter?.greet('maybe') ?? 'no greeter available')
}
ååï¼æ©å±æä»¶ä¾èµ Service Definitionï¼æ½è±¡æå¡ï¼ èéå ·ä½ providerãè¿æ · LLM éé å¨ãæ§è¡å¨çé½è½çæ¿æ¢ãäºä¸å½±åãæå¡åå ±ç¨æå¹³å½å空é´ï¼èªææå¡è¯·å åç¼ï¼harness å·²å ç¨
toolsãllmçï¼ã
ä¸ãäºä»¶ç³»ç»ï¼è§£è¦éä¿¡ä¸æ¦æª
æå¡æ¯æç´æ¥è°ç¨ï¼äºä»¶è®©æä»¶æ éç¥éè°å¨çå¬å°±è½å¹¿æãharness ç¨äºä»¶å¤çå·¥å
·ç»æã模å请æ±ã审æ¹å³å®ç交äºã
7.1 声æãååºãçå¬
stats.tsï¼è®¡æ°æå¡ï¼ï¼
import { Service, type Context } from '@deepseek-ai/cordis'
declare module '@deepseek-ai/cordis' {
interface Context { stats: StatsService }
interface Events {
'stats/report'(name: string, count: number): void
}
}
export class StatsService extends Service {
private counts = new Map<string, number>()
constructor(ctx: Context) { super(ctx, 'stats') }
bump(name: string) {
const next = (this.counts.get(name) ?? 0) + 1
this.counts.set(name, next)
this.ctx.emit('stats/report', name, next)
}
}
reporter.tsï¼
import type { Context } from '@deepseek-ai/cordis'
import type {} from './stats.ts'
export const name = 'reporter'
export const inject = ['stats']
export function apply(ctx: Context) {
ctx.on('stats/report', (name, count) => {
console.log(`[stats] ${name} -> ${count}`)
})
ctx.stats.bump('tool_call'); ctx.stats.bump('tool_call'); ctx.stats.bump('prompt')
}
import type {} from './stats.ts' 让 TS çå°å£°æåå¹¶ï¼è¿è¡æ¶æ å¯ä½ç¨ï¼ãè¾åºï¼
[stats] tool_call -> 1
[stats] tool_call -> 2
[stats] prompt -> 1
ctx.on() å±äº effectï¼çå¬å¨éæä»¶æ¶å¤±ï¼ç»ä¸éæå¨ removeListenerã
注æ
declare module '@deepseek-ai/cordis' { interface Events { ... } }è¿å¤å£°æåå¹¶ï¼å®æ'stats/report'åå ¶ç¾ååå ¥ Cordis çå ¨å±äºä»¶è¡¨ï¼äºæ¯ctx.emit/ctx.onå¨ç¼è¯æå°±æ£æ¥äºä»¶åä¸åæ°ç±»åãæ¼å声æåå¹¶ï¼äºä»¶ä»æ¯åæ³çstringäºä»¶ï¼ä½å¤±å»ç±»åä¿æ¤ââè¿æ¯åºäº Cordis å¼åæ¶æå¸¸è¸©çåã
7.2 äºç§å忍¡å¼
| æ¨¡å¼ | è°ç¨ | è¯ä¹ |
|---|---|---|
| emit | ctx.emit(name, ...) |
Aitishiku.com