diff --git a/.agents/skills/dsh-arch-diagram/SKILL.md b/.agents/skills/dsh-arch-diagram/SKILL.md new file mode 100644 index 0000000000..86306a3faf --- /dev/null +++ b/.agents/skills/dsh-arch-diagram/SKILL.md @@ -0,0 +1,158 @@ +--- +name: dsh-arch-diagram +description: Regenerate the DeepSeek Harness "System overview" architecture PNGs (English + Chinese) that the top-level README embeds. Reflects the current state of packages/* and docs/architecture.md. Use when the codebase adds/removes/renames services and the README diagram must be refreshed. +--- + +# dsh-arch-diagram + +Produces `assets/arch-en.png` and `assets/arch-zh.png` in this repo — the two hero images embedded at the top of `README.md` and `README.zh.md`. + +The pipeline is HTML + Chrome headless, so text quality, layout, and connector geometry are **deterministic** — every rerun produces the same output regardless of model. + +Aesthetic is locked to the DeepSeek brand: light blue gradient background, brand-blue Cordis bar, sans-serif everywhere, no serif / no italic / no hand-drawn feel. + +--- + +## When to use + +- User asks to "regenerate" or "refresh" the Harness architecture diagram +- User points out `packages/` has changed (new services, renames) and the README diagram is stale +- User just added a new `packages//` or a new `ctx.*` service and wants the diagram to reflect it + +## When NOT to use + +- User wants a different diagram (Code Mode, Workflow fanout, agent lifecycle) — those belong in `docs/` and need their own skill +- User wants a different visual aesthetic (dark mode, hand-drawn, editorial-serif) — this skill is locked to DeepSeek brand + +--- + +## Workflow + +### 1. Enumerate current services from the repo + +The diagram is grounded in two lists that live in the docs: + +- **Default Services** — from `packages/core/*` and `docs/architecture.md`'s "Default Services" table. As of last refresh: `ctx.sessions`, `ctx.systemPrompt`, `ctx.tools`, `ctx.agents`, `ctx.agentLoop`. +- **Capability Services** — from the non-core capability packages and `docs/architecture.md`'s "Capability Services" table. As of last refresh: `ctx.llm`, `ctx.bash`, `ctx.sandbox`, `ctx.codeRuntime`, `ctx.fs`, `ctx.skills`, `ctx.web`, `ctx.compact`, `ctx.subagents`, `ctx.workflows`, `ctx.sessionPersistence`, `ctx.sessionQuery`. + +**Do this**: + +1. Read `docs/architecture.md` +2. Extract the two `ctx.*` tables verbatim +3. Cross-check against `packages/`: services live under `packages/core/*` (defaults) or under `packages///` (capabilities). The inner package dir mirrors the npm name without the `@deepseek-ai/dsh-` prefix — e.g. `packages/session-query/session-query/` publishes `@deepseek-ai/dsh-session-query`. Never assume the inner dir carries a `dsh-` prefix. + +### 2. Diff against the current HTML templates + +Read `harness-arch-en.html` and `harness-arch-zh.html` in this skill directory. Pull out the currently-rendered `ctx.*` names. Report the diff: + +``` +Default services: no change +Capability services: + ctx., − ctx., ↻ ctx. +``` + +### 3. Update the templates + +If there are changes, edit both HTML files in place. Each card is one line: + +```html +
ctx.somethingshort description
+``` + +For a **new** service: +- Description is **short** — 2–4 words (EN), 3–6 chars (ZH) +- Ground the description in what the package's README or its `ctx..register()` **actually** does. Do NOT paraphrase from an abstract or invent capabilities the code doesn't have. +- Add the card in **both** languages, in docs order. + +For a **removed** service: delete the card in both files. + +For a **renamed** service: update the `.name` span in both files. + +**Do not touch the layout**. Rows are: +- Top row (`row top`): exactly 5 default-service cards +- Bottom row (`row bottom`): 12 capability-service cards + +If the capability count grows past ~13, the row gets visually tight. Stop and ask the user before shrinking fonts or wrapping to two rows. + +### 4. Render to PNG + +```bash +bash .agents/skills/dsh-arch-diagram/render.sh +``` + +Default output: `/assets/arch-en.png` and `/assets/arch-zh.png` — the paths that `README.md` and `README.zh.md` already reference. + +Pass an alternate directory as `$1` to write elsewhere. `CHROME` and `PORT` env vars override the browser path and http.server port. + +The script: +- Spins up a temporary `python3 -m http.server` on `127.0.0.1` (needed so Google Fonts CDN loads reliably in Chrome headless) +- Runs Chrome headless twice at `--force-device-scale-factor=2 --window-size=1536,580` +- Writes two 3072×1160 PNGs (~600 KB each) +- Tears down the server + +### 5. Verify by eye — mandatory, do not skip + +After rendering, **open each PNG and visually check every item** in this list. Do not report the diagram as done without going through it. + +- [ ] Top-row card count matches the Default Services list you extracted in §1, every name rendered in full (no truncation on the longest, e.g. `ctx.systemPrompt` / `ctx.agentLoop`) +- [ ] Bottom-row card count matches the Capability Services list you extracted in §1, every name in full (especially the longest, e.g. `ctx.sessionPersistence`) +- [ ] Every card has a description underneath, and the description matches what the code does (not made up) +- [ ] Bar reads `Cordis · microkernel (vendored)` (EN) / `Cordis · 微内核 (vendored)` (ZH) +- [ ] Number of vertical connector lines equals (top-row cards + bottom-row cards) from §1. All straight vertical, all parallel, each reaching the horizontal center of its card +- [ ] `cordis.yml` sidebar visible on the right; dashed arrow points left into the bar +- [ ] `deployment leaf` / `部署清单` and `picks which plugins load` / `决定哪些插件加载` are readable and NOT crossed through by any connector line +- [ ] Chinese descriptions render as CJK glyphs, not `□` tofu boxes (means fonts loaded) +- [ ] No large empty gradient area at the bottom of the image — if there is, tune `--window-size` in `render.sh` + +If any check fails: fix the CSS or template, re-run `render.sh`, re-check. Do not report "done" on first render without visually confirming. + +--- + +## Design system (locked — do not modify without explicit user request) + +Colors: +- Background: `linear-gradient(135deg, #ffffff 0%, #e8effc 100%)` +- Brand blue (Cordis bar + connectors): `#4a6ef5` +- Ink text: `#1a1a1a` +- Muted text: `#8a8f9c` +- Card border: `#dde3ef` +- Card fill: `#ffffff` + +Typography (**sans-serif only** — never serif, never italic): +- English title & body: **Inter** (Google Fonts) +- Chinese title & body: **Noto Sans SC** (Google Fonts) with `PingFang SC` local fallback +- Code labels (`ctx.*`, `cordis.yml`, `vendored`): **JetBrains Mono** (Google Fonts) + +Layout: +- `.page` max-width 1560 px, centered +- `.bus-row`, `.row.top`, `.row.bottom` all 96% width, centered +- Top row: `flex: 1` on each card (equal widths) +- Bottom row: `justify-content: space-between` + `flex: 0 0 auto` on each card — cards keep their intrinsic (nowrap) width and adjacent card backgrounds cannot clip a description +- Bus: `#4a6ef5` filled, 60 px tall, 8 px radius +- `cordis.yml` sidebar `position: absolute` at `left: calc(100% + 20px)` of `.bus-row`, width 130 px +- All connectors: CSS `::before` / `::after` pseudo-elements, 2 px wide, 40 px tall, `#4a6ef5`, centered via `left: 50%; transform: translateX(-50%)` — this is what guarantees pixel-perfect vertical parallel lines regardless of card content + +Rendering: +- Chrome headless `--force-device-scale-factor=2` +- `--window-size=1820,580` → output is 3640×1160 (aspect ~3.14:1, wider than square-ish so a 12-card capability row fits without truncation) +- Local http.server on `127.0.0.1` so CDN fonts load cleanly + +--- + +## Files in this skill + +- `SKILL.md` — this file +- `harness-arch.css` — shared design system (colors, fonts, layout, connectors) +- `harness-arch-en.html` — English template +- `harness-arch-zh.html` — Chinese template +- `render.sh` — Chrome headless renderer + +Templates are self-contained. Fonts load from Google Fonts CDN; no local font files. + +--- + +## Rules I keep breaking (and shouldn't) + +1. **Verify the output by looking at it.** Don't report "done" and move on — actually inspect each PNG and check every item in §5. +2. **Ground service descriptions in the code, not the docs' abstract, not the marketing copy.** If unsure what a package does, read its `src/` or the `ctx..register()` block. +3. **Don't touch layout unless asked.** 96% row/bar width, 40 px connector height, and 60 px bar height are all tuned. Card counts grow one at a time; once the bottom row starts to visibly overflow again (adjacent card backgrounds clipping a description, or the `cordis.yml` sidebar falling outside the render viewport), stop and ask before shrinking fonts, widening the viewport further, or wrapping to two rows. +4. **Never introduce a serif font or italic.** Not for titles, not for annotations, not "to make it feel editorial." This diagram is DeepSeek brand: sans-serif, upright, only. diff --git a/.agents/skills/dsh-arch-diagram/harness-arch-en.html b/.agents/skills/dsh-arch-diagram/harness-arch-en.html new file mode 100644 index 0000000000..117f606e97 --- /dev/null +++ b/.agents/skills/dsh-arch-diagram/harness-arch-en.html @@ -0,0 +1,66 @@ + + + + + + DeepSeek Harness · Architecture + + + +
+

ARCHITECTURE

+

System overview

+ +
+ + +
+
ctx.sessionsevent-sourced log
+
ctx.systemPromptprompt assembly
+
ctx.toolstool registry & pipeline
+
ctx.agentsagent handles & events
+
ctx.agentLoopReAct control loop
+
+ +
+
+ Cordis + · + microkernel + (vendored) +
+
+
+ + + + +
+
+
cordis.yml
+
deployment leaf
+
+
picks which plugins load
+
+
+ +
+
ctx.llmLLM provider adapter
+
ctx.bashshell execution
+
ctx.sandboxprocess confinement
+
ctx.codeRuntimeJS worker runtime
+
ctx.fsfilesystem + policy
+
ctx.skillsreusable skills
+
ctx.websearch & fetch
+
ctx.compactcontext compression
+
ctx.subagentsspawn / fork / ACP
+
ctx.workflowsdynamic orchestration
+
ctx.sessionPersistenceJSONL / SQLite
+
ctx.sessionQueryunified log reads
+
+ + +
+
+ + diff --git a/.agents/skills/dsh-arch-diagram/harness-arch-zh.html b/.agents/skills/dsh-arch-diagram/harness-arch-zh.html new file mode 100644 index 0000000000..ca2da1b4f1 --- /dev/null +++ b/.agents/skills/dsh-arch-diagram/harness-arch-zh.html @@ -0,0 +1,66 @@ + + + + + + DeepSeek Harness · 架构 + + + +
+

架 构

+

系统一览

+ +
+ + +
+
ctx.sessions事件溯源日志
+
ctx.systemPrompt系统提示词组装
+
ctx.tools工具注册与执行
+
ctx.agentsAgent 实例与事件
+
ctx.agentLoopReAct 控制循环
+
+ +
+
+ Cordis + · + 微内核 + (vendored) +
+
+
+ + + + +
+
+
cordis.yml
+
部署清单
+
+
决定哪些插件加载
+
+
+ +
+
ctx.llm模型适配层
+
ctx.bash命令行执行
+
ctx.sandbox进程隔离
+
ctx.codeRuntimeJS 运行时
+
ctx.fs文件读写
+
ctx.skills可复用技能
+
ctx.web网页搜索抓取
+
ctx.compact上下文压缩
+
ctx.subagents子智能体
+
ctx.workflows动态编排
+
ctx.sessionPersistence会话持久化
+
ctx.sessionQuery会话日志查询
+
+ + +
+
+ + diff --git a/.agents/skills/dsh-arch-diagram/harness-arch.css b/.agents/skills/dsh-arch-diagram/harness-arch.css new file mode 100644 index 0000000000..97ac526b8e --- /dev/null +++ b/.agents/skills/dsh-arch-diagram/harness-arch.css @@ -0,0 +1,220 @@ +/* DeepSeek brand — bone-white + brand-blue, all sans-serif, no italic, no serif. */ + +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap'); + +:root { + --bg-top: #ffffff; + --bg-bot: #e8effc; + --ink: #1a1a1a; + --muted: #8a8f9c; + --card-bd: #dde3ef; + --card-bg: #ffffff; + --brand: #4a6ef5; + --brand-soft: #dbe4fe; + + --sans: 'Inter', 'Noto Sans SC', 'PingFang SC', -apple-system, BlinkMacSystemFont, system-ui, sans-serif; + --cn: 'Noto Sans SC', 'PingFang SC', 'Inter', -apple-system, sans-serif; + --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace; +} + +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +body { + font-family: var(--sans); + color: var(--ink); + background: linear-gradient(135deg, var(--bg-top) 0%, var(--bg-bot) 100%); + padding: 40px 64px 32px; + -webkit-font-smoothing: antialiased; + font-feature-settings: "kern" 1, "liga" 1, "cv02" 1, "cv11" 1; +} + +.page { + max-width: 1560px; + margin: 0 auto; +} + +/* ── header ─────────────────────────────────────────── */ +.eyebrow { + font-family: var(--sans); + font-size: 12px; + font-weight: 500; + letter-spacing: 0.22em; + color: var(--muted); + text-transform: uppercase; + margin-bottom: 10px; +} +.eyebrow.cn { font-family: var(--cn); letter-spacing: 0.4em; text-transform: none; } + +h1 { + font-family: var(--sans); + font-size: 40px; + font-weight: 600; + letter-spacing: -0.02em; + line-height: 1.15; + color: var(--ink); + margin-bottom: 88px; +} +h1.cn { font-family: var(--cn); letter-spacing: 0.02em; font-weight: 600; } + +/* ── diagram frame ──────────────────────────────────── */ +.diagram { position: relative; } + +.section-label { + font-family: var(--sans); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.22em; + color: var(--muted); + text-transform: uppercase; + text-align: center; + margin-bottom: 20px; +} +.section-label.cn { font-family: var(--cn); letter-spacing: 0.4em; text-transform: none; font-size: 12px; } +.section-label.bottom { margin: 20px 0 0; } + +/* ── card rows ──────────────────────────────────────── */ +.row { + display: flex; + gap: 12px; + justify-content: center; + width: 96%; + margin: 0 auto; + position: relative; +} +.row.top .card { flex: 1; } +.row.bottom { + gap: 0; + justify-content: space-between; +} +/* flex: 0 0 auto so cards keep their intrinsic (nowrap) width and + neighbouring card backgrounds cannot clip a description. */ +.row.bottom .card { flex: 0 0 auto; } + +.card { + background: var(--card-bg); + border: 1px solid var(--card-bd); + border-radius: 6px; + padding: 14px 10px; + text-align: center; + min-width: 0; + position: relative; +} +.card .name { + font-family: var(--mono); + font-size: 13px; + font-weight: 500; + color: var(--ink); + line-height: 1.2; + white-space: nowrap; + display: block; +} +.card .desc { + font-family: var(--sans); + font-size: 11px; + font-weight: 400; + color: var(--muted); + margin-top: 4px; + line-height: 1.3; + min-height: 28px; + white-space: nowrap; +} +.card .desc.cn { font-family: var(--cn); } +.row.bottom .card { padding: 10px 6px; } +.row.bottom .card .name { font-size: 10px; } +.row.bottom .card .desc { font-size: 9px; min-height: 22px; } +.row.bottom .card .desc.cn { font-size: 10px; } + +/* connectors — pure CSS, guaranteed vertical & parallel */ +.row.top .card::after, +.row.bottom .card::before { + content: ''; + position: absolute; + left: 50%; + transform: translateX(-50%); + width: 2px; + background: var(--brand); +} +.row.top .card::after { top: 100%; height: 40px; } +.row.bottom .card::before { bottom: 100%; height: 40px; } + +/* ── bus row (Cordis) ───────────────────────────────── */ +.bus-row { + position: relative; + width: 96%; + margin: 40px auto; +} +.bus { + height: 60px; + background: var(--brand); + color: #ffffff; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + font-family: var(--sans); + font-size: 18px; + font-weight: 500; + letter-spacing: 0.01em; +} +.bus .dot { padding: 0 12px; opacity: 0.75; } +.bus .vendored { + font-family: var(--mono); + font-size: 15px; + font-weight: 400; + opacity: 0.8; + margin-left: 8px; +} +.bus.cn .core { font-family: var(--cn); } + +/* ── cordis.yml side box (positioned outside bus width) ─ */ +.yml-side { + position: absolute; + left: calc(100% + 20px); + top: 50%; + transform: translateY(-50%); + width: 130px; + display: flex; + flex-direction: column; + align-items: flex-start; +} +.yml-arrow { + position: absolute; + left: -30px; + top: 50%; + transform: translateY(-50%); + width: 30px; + height: 12px; +} +.yml-arrow svg { display: block; } +.yml-box { + width: 100%; + background: var(--card-bg); + border: 1px solid var(--card-bd); + border-radius: 6px; + padding: 12px 10px; + text-align: center; +} +.yml-box .file { + font-family: var(--mono); + font-size: 13px; + font-weight: 500; + color: var(--ink); +} +.yml-box .sub { + font-family: var(--sans); + font-size: 10px; + color: var(--muted); + margin-top: 4px; + line-height: 1.3; +} +.yml-box .sub.cn { font-family: var(--cn); letter-spacing: 0.05em; } +.yml-note { + font-family: var(--sans); + font-size: 10px; + color: var(--muted); + margin-top: 10px; + width: 100%; + text-align: center; + line-height: 1.4; +} +.yml-note.cn { font-family: var(--cn); letter-spacing: 0.05em; } diff --git a/.agents/skills/dsh-arch-diagram/render.sh b/.agents/skills/dsh-arch-diagram/render.sh new file mode 100755 index 0000000000..781f79b9ef --- /dev/null +++ b/.agents/skills/dsh-arch-diagram/render.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# render.sh — Chrome headless renderer for the DeepSeek Harness architecture diagram. +# +# Writes arch-en.png and arch-zh.png (3072×1160, ~600 KB each) to the given output +# directory. Default is /assets/, which is where the README image references +# resolve. +# +# Usage: +# bash render.sh # writes to /assets/ +# bash render.sh /some/other/dir # writes there instead +# +# Env overrides: +# CHROME=/path/to/Chrome # non-standard Chrome location +# PORT= # override the local http.server port + +set -e + +SKILL_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SKILL_DIR/../../.." && pwd)" +OUT_DIR="${1:-$REPO_ROOT/assets}" +BIND_PORT="${PORT:-0}" # 0 → kernel picks a free port +SERVER_LOG="$(mktemp -t dsh-arch-diagram-server.XXXXXX.log)" + +# Locate a Chrome / Chromium binary. Honour $CHROME if set; otherwise probe +# common per-platform paths so `bash render.sh` works on macOS + Linux out +# of the box. +if [ -z "$CHROME" ]; then + for candidate in \ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ + "/Applications/Chromium.app/Contents/MacOS/Chromium" \ + "$(command -v google-chrome 2>/dev/null || true)" \ + "$(command -v google-chrome-stable 2>/dev/null || true)" \ + "$(command -v chromium 2>/dev/null || true)" \ + "$(command -v chromium-browser 2>/dev/null || true)"; do + if [ -n "$candidate" ] && [ -x "$candidate" ]; then + CHROME="$candidate"; break + fi + done +fi + +if [ -z "$CHROME" ] || [ ! -x "$CHROME" ]; then + echo "No Chrome / Chromium binary found." >&2 + echo "Tried: macOS default, google-chrome, google-chrome-stable, chromium, chromium-browser." >&2 + echo "Set CHROME=/path/to/binary and rerun." >&2 + exit 1 +fi + +mkdir -p "$OUT_DIR" + +python3 -u -m http.server "$BIND_PORT" --bind 127.0.0.1 --directory "$SKILL_DIR" \ + >"$SERVER_LOG" 2>&1 & +SERVER_PID=$! +cleanup() { kill "$SERVER_PID" 2>/dev/null; rm -f "$SERVER_LOG"; } +trap cleanup EXIT INT TERM + +# Discover the actual bound port from Python's own startup line +# ("Serving HTTP on 127.0.0.1 port ..."). Works whether the kernel +# picked it or PORT was set explicitly; no external `lsof` needed. +PORT="" +for _ in $(seq 1 40); do + PORT=$(awk '/Serving HTTP on/ {print $6; exit}' "$SERVER_LOG" 2>/dev/null || true) + [ -n "$PORT" ] && break + # Bail early if the server died (e.g. explicit PORT already in use). + kill -0 "$SERVER_PID" 2>/dev/null || break + sleep 0.05 +done +if [ -z "$PORT" ]; then + echo "Failed to detect local server port. Server log:" >&2 + cat "$SERVER_LOG" >&2 || true + exit 1 +fi + +# Chrome/Chromium refuses to run as root without --no-sandbox. Rendering +# a local static HTML doc under a headless browser doesn't need Chrome's +# own sandbox, so passing the flag when EUID is 0 makes the script work +# in Codex/CI container environments that default to root. +CHROME_EXTRA_ARGS=() +if [ "$(id -u)" = "0" ]; then + CHROME_EXTRA_ARGS+=(--no-sandbox) +fi + +for lang in en zh; do + out="$OUT_DIR/arch-$lang.png" + "$CHROME" \ + "${CHROME_EXTRA_ARGS[@]}" \ + --headless=new \ + --disable-gpu \ + --hide-scrollbars \ + --force-device-scale-factor=2 \ + --window-size=1820,580 \ + --virtual-time-budget=8000 \ + --screenshot="$out" \ + "http://127.0.0.1:$PORT/harness-arch-$lang.html" \ + 2>/dev/null + size=$(du -h "$out" | awk '{print $1}') + echo "[$lang] wrote $out ($size)" +done diff --git a/README.i18n.yaml b/README.i18n.yaml index 790812344d..0a718b627d 100644 --- a/README.i18n.yaml +++ b/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write -README.md: 53dd3896eb15800125673e7c44f7de02daca9376 -README.zh.md: ab826f62658248249ec18c57b35c0065c0f909d1 +README.md: 3380558e6c956cdc7f1b748b9ea8d3d455f781db +README.zh.md: 9f415af0a6582c455fdb8e8bb5400dd28b42a161 diff --git a/README.md b/README.md index 53dd3896eb..3380558e6c 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,240 @@ -# DeepSeek Harness + + +
+ + +

DeepSeek Harness

+ +**The plugin-first agent SDK. Every capability — including the loop — is a plugin.** + +

+ license + node + pnpm + typescript + ACP + Discord + X +

English | [中文](README.zh.md) -The **DeepSeek Harness SDK** is a plugin-based SDK for building agent harnesses. + +[Docs](https://deepseek.com/harness-sdk/docs)  ·  [Landing page](https://deepseek.com/harness-sdk)  ·  [Community](#community) -## Development +
-This monorepo is built on the [Cordis](https://github.com/cordiverse/cordis) framework (vendored as source under `vendor/`), microkernel-style: everything is a plugin. +
+ +

+ DeepSeek Harness — System overview +

+ +## What is this? + +DeepSeek Harness is a TypeScript SDK for building AI agents on top of the [Cordis](https://github.com/cordiverse/cordis) microkernel. **Every service, including the ReAct loop, is a plugin registered through `ctx.*`.** A batteries-included service registry ships in the box — LLM adapters, sandboxed execution, filesystem with policy, web search, sub-agents, dynamic workflows, session persistence, and more — and a `cordis.yml` at your project root chooses which get loaded. You can replace any of them, add your own, or leave the shipped defaults alone. + +## Getting started + +**New project** (one-command scaffold): ```sh -pnpm install -pnpm run test # vitest -pnpm run demo:repl # REPL agent demo (needs DEEPSEEK_API_KEY) -pnpm run demo:acp # ACP server agent demo (needs DEEPSEEK_API_KEY) +npm create @deepseek-ai/harness # coming soon, not yet on npm ``` -For humans, start with the [development guide](docs/development.md) for local setup, hooks, environment variables, and quality gates, then read the [architecture design](docs/architecture.md) and [documentation graph index](docs/graph-atlas.md) before package work. Local context lives in [packages/](packages/) and [vendor/](vendor/). +**From source** (read the code / run demos / contribute): -For agents, follow [AGENTS.md](AGENTS.md). +```sh +git clone https://github.com/deepseek-harness/deepseek-harness.git +cd deepseek-harness +pnpm install +export DEEPSEEK_API_KEY=sk-... # optional — omit and use pnpm run demo:echo (mock, no key) +pnpm run demo:repl +``` + +Requires **Node `^22.19 || ≥24`** and **pnpm ≥ 11.7** (Node engine and pnpm pinned in `package.json`; `corepack enable` picks up the exact pnpm version). Node 23 is not on the support matrix. + +**Heads up:** `demo:repl` runs real `read` / `write` / `edit` file tools and `bash` in your current working directory — best run from a scratch dir or a git-clean project so you can review the changes. + +## Use it in your editor + +Harness ships an [Agent Client Protocol (ACP)](https://agentclientprotocol.com) server. ACP lets an editor drive an agent from its sidebar; [Zed](https://zed.dev) supports it natively. + +The ACP server command (from your local clone): + +```sh +pnpm run demo:acp +``` + +Zed side — Zed's `settings.json` (Cmd-Shift-P → "zed: open settings") takes an `agent_servers` entry: + +```json +{ + "agent_servers": { + "DeepSeek Harness": { + "command": "pnpm", + "args": ["--dir", "/path/to/deepseek-harness", "run", "demo:acp"], + "env": { "DEEPSEEK_API_KEY": "sk-..." } + } + } +} +``` + +`--dir` points at your local clone. Zed launches the agent as a subprocess; each Zed session maps to its own agent instance, with chat in the sidebar and tool calls (arguments, results, file diffs) rendered inline in the editor. Configuration details in [`examples/acp-agent`](./examples/acp-agent) (including the snapshot-tested surface). + +**VS Code / Cursor** — install an ACP client extension for either editor, such as [ACP Client](https://marketplace.visualstudio.com/items?itemName=formulahendry.acp-client) (`formulahendry.acp-client`) or [ACP Pro](https://marketplace.visualstudio.com/items?itemName=duclvz.acp-pro) (`duclvz.acp-pro`), and point a custom agent at `pnpm run demo:acp`. + +**Other ACP clients** — same launch. Feature-by-feature support matrix in [`packages/ui/acp/acp-feature-support.md`](./packages/ui/acp/acp-feature-support.md). + +## Embed it in your own app + +Harness bootstraps from a `cordis.yml` via [`@deepseek-ai/dsh-app-boot`](./packages/ui/app-boot). For library-style integration into your own Node.js service, the same boot helpers apply: + +```ts +// my-app.ts +import { + boot, + installFailLoud, + loadEnv, + resolveConfigPath, +} from '@deepseek-ai/dsh-app-boot' + +installFailLoud('my-app') +loadEnv('my-app') + +const ctx = await boot('my-app', resolveConfigPath('./cordis.yml', undefined)) +// ctx is the Cordis root Context; every service you mount in cordis.yml +// is reachable via ctx.* (ctx.agents, ctx.sessions, ctx.tools, …). +// The app plugins loaded from cordis.yml keep the process alive on their own +// (stdio agents hold stdin; the ACP agent holds an RPC connection). +// To shut down programmatically, call `await ctx.fiber.dispose()`. +``` + +`boot()` returns once the whole plugin tree has settled. Two separate failure paths: a module-import failure rejects the `boot()` Promise directly, so the caller's `await` throws — handle it with `try/catch`. `installFailLoud` covers a different case — a late plugin-init rejection surfacing *after* `boot()` has already resolved, which would otherwise become an unhandled rejection and die silently. In `cordis.yml`, the entry-point app plugin — `dsh-stdio-agent` for a REPL, `dsh-acp-agent` for an ACP server, or a custom one — sits alongside whichever services should load. Full helper surface: [`packages/ui/app-boot`](./packages/ui/app-boot). + +For end-to-end examples, see [`examples/`](./examples): + +- [`echo-agent`](./examples/echo-agent) — a minimal setup with a mock LLM and an echo tool +- [`coding-agent`](./examples/coding-agent) — a full coding agent wired to the real DeepSeek LLM +- [`acp-agent`](./examples/acp-agent) — ACP server, with a sandbox composition variant + +## Demo + +Harness driving Zed as an ACP agent — chat in the sidebar, tool calls (bash, file edits, diffs) rendered inline in the editor: + +

+ +

+ + + +## Write a plugin + +A Harness function/namespace plugin exports `name`, `inject`, and `apply` — cordis's Loader reads those separately. **`export default` breaks this shape** ([why](./docs/postmortem/0001-acp-default-export-drops-inject.md)): the Loader keeps only the `apply` function and silently drops `inject` / `name`, so the plugin fails to load with `cannot get property … without inject`. Inside `apply(ctx)`, tools / LLM adapters / services register through `ctx.*`. + +The minimal echo tool from [`examples/echo-agent`](./examples/echo-agent): + +```ts +// echo-tool.ts +import type { Context } from 'cordis' +import { defineTool } from '@deepseek-ai/dsh-tools' + +export const name = 'echo-tool' +export const inject = ['tools'] + +export function apply(ctx: Context) { + ctx.tools.register(defineTool({ + name: 'echo', + description: 'Echo the given text back, uppercased.', + parameters: { + text: { type: 'string', required: true }, + }, + async execute(args) { + // args is typed: { text: string } + return [{ type: 'text', text: `ECHO: ${args.text.toUpperCase()}` }] + }, + })) +} +``` + +`parameters` uses the [schemastery](./vendor/schemastery) JSON-Schema-shaped DSL — one field per property, with `required: true` for mandatory ones. A leaf `cordis.yml` is a flat `EntryOptions[]` the Loader iterates; this tool's entry looks like: + +```yaml +- id: echo-tool + name: './echo-tool.ts' # your tool +``` + +Alongside it, a bootable config also needs an LLM adapter and a `stdio-agent` app entry whose `config.model` points at an id that adapter registers. The minimal runnable version — mock LLM + this echo tool + a `stdio-agent` entry wired to `mock-echo` — is [`examples/echo-agent`](./examples/echo-agent), launched via: + +```sh +pnpm run demo:echo +``` + +LLM-adapter and UI-plugin shapes: [`docs/cookbook/extension-cookbook.md`](./docs/cookbook/extension-cookbook.md). + +## Packages + +All packages ship under the `@deepseek-ai/dsh-*` scope. Grouped by family: + +| Family | What lives here | +|---|---| +| **Core** (`packages/core/`) | `dsh-scope` · `dsh-session` · `dsh-tools` · `dsh-agent` · `dsh-agent-loop` · `dsh-system-prompt` | +| **LLM** (`packages/llm/`) | `dsh-llm` (the seam) + `dsh-llm-deepseek` (hand-rolled) and `dsh-llm-pi-ai` (library-backed twin — same DeepSeek endpoint, different internals, kept for design verification) | +| **Bash** (`packages/bash/`) | Shell execution: local + sandboxed backends, model-facing `bash` tool | +| **Filesystem** (`packages/fs/`) | Filesystem service with a policy layer, `read` / `write` / `edit` tools | +| **Web** (`packages/web/`) | Web search (Perplexity, Exa, DeepSeek) + fetch, model-facing tool | +| **Sandbox** (`packages/sandbox/`) | Process-confinement seam (bwrap / Landlock / Seatbelt) — wraps a caller's argv under a per-call policy; execution itself lives in `ctx.bash` | +| **Code runtime** (`packages/code-runtime/`) | JS worker runtime that Code Mode dispatches into | +| **Sub-agents** (`packages/subagent/`) | `spawn`, `fork`, plus in-process / subprocess / ACP-backed backends | +| **Workflows** (`packages/workflow/`) | Dynamic workflow orchestration (worker-thread execution) | +| **Skills** (`packages/skill/`) | Skill-provider registry (`ctx.skills`) + a local-filesystem provider | +| **Session persistence** (`packages/session-persistence/`) | Event-log persistence: JSONL and SQLite backends | +| **Session query** (`packages/session-query/`) | `ctx.sessionQuery` — unified logical-corpus reads over live sessions + persistence | +| **Compact** (`packages/compact/`) | Context compression / summarization | +| **Context** (`packages/context/`) | Opt-in request-context enrichment (e.g. `dsh-time-context` — dynamic time-in-prompt) | +| **Cordis toolset** (`packages/cordis/`) | Model-facing tools that inspect / mount / unmount cordis plugins at runtime | +| **UI apps** (`packages/ui/`) | `dsh-stdio-agent` (REPL) · `dsh-acp-agent` (ACP server) · `dsh-app-boot` · approval + ask-user primitives | +| **Hooks** (`packages/hooks/`) | Hook protocol + Claude Code / OpenAI Codex hook-config bridges | +| **Guards** (`packages/guard/`) | Advisory loop-hygiene plugins (e.g. `repeat-tool-guard` for repeated-call escalation) | +| **Timeouts** (`packages/timeout/`) | `timeout-policy` — a zero-config `tools/execute` wrapper enforcing per-tool `timeoutMs` | +| **Todo** (`packages/todo/`) | The model-facing `todo_write` tool (whole-list task tracker) | +| **Support** (`packages/support/`) | `invariants` — runtime diagnostic plugin mounted unconditionally by the shipped `dsh-agent-spine-demo` bundle; plus test/dev-only helpers (`llm-replay`, `acp-snapshot`, `subagent-mock`) | +| **Example bundles** (`packages/examples/`) | Ready-to-run demo compositions the top-level `demo:*` scripts launch: `dsh-agent-spine-demo` (default spine + capabilities), `dsh-stdio-demo` (REPL), `dsh-acp-demo` (ACP server), `dsh-jsonrpc-demo` | +| **Utils** (`packages/util/`) | Internal utility packages (`brand`, `timeout`) | + +For the full module dependency graph, see [`docs/module-graph.md`](./docs/module-graph.md). + +## Deep dives + +To understand what makes DeepSeek Harness different, start here: + +- [Architecture](./docs/architecture.md) — the service taxonomy and the microkernel structure +- [Agent lifecycle](./docs/agent-lifecycle.md) — how a turn flows through the loop, with sequence diagrams +- [Cordis primer](./docs/cordis-primer.md) — a working introduction to the underlying plugin framework +- [Tool execution pipeline](./docs/tool-execution-pipeline.md) — how a tool call passes through permission gates, hooks, and logging +- [Capability seams](./docs/capability-seams.md) — the extension points each service exposes +- [Code Mode](./docs/rfc/implemented/feature/2026-06-15-code-mode.md) — the model writes one JavaScript program per turn that chains many bash / tool calls, executed in a single runtime pass. **One model round-trip per multi-step operation**, not one per call. +- [Dynamic Workflows](./docs/rfc/implemented/feature/2026-07-05-dynamic-workflows.md) — the model writes a plain-JS orchestrator that fans out sub-agents in parallel, joins their results, and returns to the parent — instead of a chain of sub-agent tool calls. +- [Self-referential Cordis toolset](./docs/rfc/implemented/feature/2026-07-08-self-referential-cordis-toolset.md) — the SDK's own plumbing (`cordis_inspect`, `cordis_mount`, `cordis_unmount`) is exposed as tools, so the model can inspect its own runtime and load new plugins on the fly. + +Docs site: **[deepseek.com/harness-sdk/docs](https://deepseek.com/harness-sdk/docs)**. + +## Community + + + +- **[GitHub Issues](https://github.com/deepseek-harness/deepseek-harness/issues)** — bug reports +- **[GitHub Discussions](https://github.com/deepseek-harness/deepseek-harness/discussions)** — questions, ideas, RFCs + +Real-time chat on Discord. Release announcements on X / Twitter. + +## License + +[BSD 3-Clause](./LICENSE) © DeepSeek diff --git a/README.zh.md b/README.zh.md index ab826f6265..9f415af0a6 100644 --- a/README.zh.md +++ b/README.zh.md @@ -1,20 +1,240 @@ -# DeepSeek Harness + + +
+ + +

DeepSeek Harness

+ +**插件优先的 agent(智能体) SDK。每一项能力 — 包括 loop 本身 — 都是插件。** + +

+ license + node + pnpm + typescript + ACP +

[English](README.md) | 中文 -**DeepSeek Harness SDK** 是用于构建 agent harness(智能体框架)的 SDK,采取基于插件的设计。 + +[文档](https://deepseek.com/harness-sdk/docs)  ·  [Landing page](https://deepseek.com/harness-sdk)  ·  [社群](#community) -## 开发 +
-本 monorepo 基于 [Cordis](https://github.com/cordiverse/cordis) 框架构建(以源码形式收录在 `vendor/` 下),采用微内核风格:所有功能都以插件形式提供。 +
+ +

+ DeepSeek Harness · 系统一览 +

+ +## 这是什么? + +DeepSeek Harness 是一个用 TypeScript 写的 AI agent SDK,构建在 [Cordis](https://github.com/cordiverse/cordis) 微内核之上。**所有服务,包括默认的 ReAct loop,都是通过 `ctx.*` 注册的插件。** 仓库里带了一整套开箱即用的服务 —— LLM 适配、沙盒执行、带策略的文件读写、网页搜索、子 agent、动态工作流、会话持久化等 —— 由项目根目录下的 `cordis.yml` 决定加载哪些。你可以替换任何一项、加装自己的,或者保留默认。 + +## 上手 + +**新起一个项目**(一条命令生成脚手架): ```sh -pnpm install -pnpm run test # vitest -pnpm run demo:repl # REPL agent demo (needs DEEPSEEK_API_KEY) -pnpm run demo:acp # ACP server agent demo (needs DEEPSEEK_API_KEY) +npm create @deepseek-ai/harness # coming soon, not yet on npm ``` -面向开发者:先读[开发指南](docs/development.md),了解本地环境搭建、钩子、环境变量与质量门禁,动手改 package 之前再读[架构设计](docs/architecture.md)和[文档关系图索引](docs/graph-atlas.md)。局部上下文见 [packages/](packages/) 与 [vendor/](vendor/)。 +**克隆仓库**(读代码 / 跑 demo / 贡献代码): -面向 agent:遵循 [AGENTS.md](AGENTS.md)。 +```sh +git clone https://github.com/deepseek-harness/deepseek-harness.git +cd deepseek-harness +pnpm install +export DEEPSEEK_API_KEY=sk-... # optional — omit and use pnpm run demo:echo (mock, no key) +pnpm run demo:repl +``` + +需要 **Node `^22.19 || ≥24`** 和 **pnpm ≥ 11.7**(Node 引擎与 pnpm 版本由 `package.json` 的 `engines` / `packageManager` 字段锁定;`corepack enable` 会自动装对 pnpm 版本)。Node 23 不在支持范围内。 + +**注意:** `demo:repl` 会用真实的 `read` / `write` / `edit` 文件工具和 `bash` 操作**当前工作目录**,最好在空目录或干净的 git 项目里运行,方便随时 review 改动。 + +## 接入编辑器 + +Harness 内置了一个 [Agent Client Protocol (ACP)](https://agentclientprotocol.com) server。ACP 是一个把 agent 挂到编辑器边栏作为后端的协议;[Zed](https://zed.dev) 目前原生支持。 + +ACP server 的启动命令(在 clone 的仓库根目录下): + +```sh +pnpm run demo:acp +``` + +Zed 端 —— 在 Zed 的 `settings.json`(Cmd-Shift-P → "zed: open settings")里加上 `agent_servers` 一节: + +```json +{ + "agent_servers": { + "DeepSeek Harness": { + "command": "pnpm", + "args": ["--dir", "/path/to/deepseek-harness", "run", "demo:acp"], + "env": { "DEEPSEEK_API_KEY": "sk-..." } + } + } +} +``` + +`--dir` 指向本地仓库路径。Zed 把 agent 作为子进程拉起,每个 Zed session 对应一个独立的 agent 实例;编辑器边栏可以直接对话,tool 调用(参数、结果、文件 diff)内联渲染到编辑区。完整配置说明见 [`examples/acp-agent`](./examples/acp-agent)。 + +**VS Code / Cursor** —— 两个编辑器都可以装 ACP 客户端插件,比如 [ACP Client](https://marketplace.visualstudio.com/items?itemName=formulahendry.acp-client)(`formulahendry.acp-client`)或 [ACP Pro](https://marketplace.visualstudio.com/items?itemName=duclvz.acp-pro)(`duclvz.acp-pro`),把 `pnpm run demo:acp` 配成自定义 agent 即可接入。 + +**其他 ACP 客户端** —— 接入方式相同。支持哪些 ACP 特性见 [`packages/ui/acp/acp-feature-support.md`](./packages/ui/acp/acp-feature-support.md)。 + +## 嵌入自己的应用 + +Harness 是通过 [`@deepseek-ai/dsh-app-boot`](./packages/ui/app-boot) 从一份 `cordis.yml` 引导起来的。如果希望在个人 Node.js 服务里以库的形式集成,可以用同样的引导方式: + +```ts +// my-app.ts +import { + boot, + installFailLoud, + loadEnv, + resolveConfigPath, +} from '@deepseek-ai/dsh-app-boot' + +installFailLoud('my-app') +loadEnv('my-app') + +const ctx = await boot('my-app', resolveConfigPath('./cordis.yml', undefined)) +// ctx is the Cordis root Context; every service you mount in cordis.yml +// is reachable via ctx.* (ctx.agents, ctx.sessions, ctx.tools, …). +// The app plugins loaded from cordis.yml keep the process alive on their own +// (stdio agents hold stdin; the ACP agent holds an RPC connection). +// To shut down programmatically, call `await ctx.fiber.dispose()`. +``` + +`boot()` 会在整棵插件树 settle 完之后返回。两条失败路径要分开处理:模块导入失败会直接 reject `boot()` 的 Promise,`await` 处会抛出,调用方用 `try/catch` 接住即可。`installFailLoud` 负责的是另一件事 —— `boot()` 返回之后才浮出来的 late plugin-init rejection,如果不接就会变成无人处理的 unhandled rejection 静默死掉。`cordis.yml` 里的 app 插件入口 —— `dsh-stdio-agent`(REPL)、`dsh-acp-agent`(ACP server)或自定义 —— 搭配想加载的服务。完整的 helper 表见 [`packages/ui/app-boot`](./packages/ui/app-boot)。 + +完整的组合示例见 [`examples/`](./examples): + +- [`echo-agent`](./examples/echo-agent) —— mock LLM + echo tool 的最小示例 +- [`coding-agent`](./examples/coding-agent) —— 接真实 DeepSeek LLM 的完整 coding agent +- [`acp-agent`](./examples/acp-agent) —— ACP server,含一个沙盒 composition variant + +## 演示 + +Harness 作为 ACP agent 挂在 Zed 里 —— 边栏对话,工具调用(bash、文件编辑、diff)内联渲染在编辑区: + +

+ +

+ + + +## 编写插件 + +Harness 的 function/namespace 插件通过分开的 `name` / `inject` / `apply` 命名导出注册,cordis Loader 读的是这些字段。**`export default` 不适用于这种形态** —— Loader 只会拿到 `apply` 函数,`inject` / `name` 被静默丢掉,加载时报 `cannot get property … without inject`(详见 [postmortem 0001](./docs/postmortem/0001-acp-default-export-drops-inject.md))。`apply(ctx)` 内通过 `ctx.*` 注册 tool、挂载 LLM adapter 或暴露 service。 + +下面这个是 [`examples/echo-agent`](./examples/echo-agent) 里的真实 echo tool 插件: + +```ts +// echo-tool.ts +import type { Context } from 'cordis' +import { defineTool } from '@deepseek-ai/dsh-tools' + +export const name = 'echo-tool' +export const inject = ['tools'] + +export function apply(ctx: Context) { + ctx.tools.register(defineTool({ + name: 'echo', + description: 'Echo the given text back, uppercased.', + parameters: { + text: { type: 'string', required: true }, + }, + async execute(args) { + // args is typed: { text: string } + return [{ type: 'text', text: `ECHO: ${args.text.toUpperCase()}` }] + }, + })) +} +``` + +`parameters` 是 [schemastery](./vendor/schemastery) 的 JSON-Schema 风格 DSL —— 每个字段一项定义,`required: true` 标记必填。leaf `cordis.yml` 是 Loader 迭代的一个 flat `EntryOptions[]`,这个工具的条目长这样: + +```yaml +- id: echo-tool + name: './echo-tool.ts' # your tool +``` + +同一份配置里还要有 LLM adapter 和一个 `stdio-agent` app 条目,`config.model` 指向 adapter 里注册的某个 model id。最小可跑组合 —— mock LLM + 这个 echo tool + 接到 `mock-echo` 的 `stdio-agent` —— 见 [`examples/echo-agent`](./examples/echo-agent),运行命令: + +```sh +pnpm run demo:echo +``` + +LLM adapter 与 UI 插件的写法见 [`docs/cookbook/extension-cookbook.md`](./docs/cookbook/extension-cookbook.md)。 + +## Packages + +所有包都在 `@deepseek-ai/dsh-*` scope 下,按目录分组: + +| 分组 | 包含 | +|---|---| +| **Core**(`packages/core/`)| `dsh-scope` · `dsh-session` · `dsh-tools` · `dsh-agent` · `dsh-agent-loop` · `dsh-system-prompt` | +| **LLM**(`packages/llm/`)| `dsh-llm`(seam)+ `dsh-llm-deepseek`(手写实现)与 `dsh-llm-pi-ai`(第三方库实现的孪生 —— 打同一个 DeepSeek endpoint,内部走不同代码路径,用于设计验证)| +| **Bash**(`packages/bash/`)| 命令行执行:本地 + 沙盒后端,模型可调用的 `bash` tool | +| **Filesystem**(`packages/fs/`)| 带策略层的文件服务,`read` / `write` / `edit` tools | +| **Web**(`packages/web/`)| 网页搜索(Perplexity、Exa、DeepSeek)+ fetch,模型可调用的 tool | +| **Sandbox**(`packages/sandbox/`)| 进程隔离接缝(bwrap / Landlock / Seatbelt)—— 按每次调用的策略包一层 argv,真正的执行由 `ctx.bash` 负责 | +| **Code runtime**(`packages/code-runtime/`)| Code Mode 分发进入的 JS worker 运行时 | +| **Sub-agents**(`packages/subagent/`)| `spawn` / `fork`,以及进程内 / 子进程 / ACP 后端 | +| **Workflows**(`packages/workflow/`)| 动态工作流编排(worker 线程执行)| +| **Skills**(`packages/skill/`)| Skill provider 注册中心(`ctx.skills`)+ 本地文件系统 provider | +| **Session persistence**(`packages/session-persistence/`)| 事件日志持久化:JSONL 与 SQLite 后端 | +| **Session query**(`packages/session-query/`)| `ctx.sessionQuery` —— 把 live sessions 和持久化层合成同一份逻辑语料的统一查询 | +| **Compact**(`packages/compact/`)| 上下文压缩 / 摘要 | +| **Context**(`packages/context/`)| 可选的请求上下文增强(如 `dsh-time-context` —— 系统提示词里注入动态时间)| +| **Cordis toolset**(`packages/cordis/`)| 模型可调用的、在运行时查看 / 挂载 / 卸载 cordis 插件的 tools | +| **UI apps**(`packages/ui/`)| `dsh-stdio-agent`(REPL)· `dsh-acp-agent`(ACP server)· `dsh-app-boot` · approval / ask-user 基础件 | +| **Hooks**(`packages/hooks/`)| Hook 协议 + Claude Code / OpenAI Codex 的 hook 配置桥 | +| **Guards**(`packages/guard/`)| 建议性的 loop 健康插件(如 `repeat-tool-guard` —— 检测同一 tool 重复调用并升级 advisory)| +| **Timeouts**(`packages/timeout/`)| `timeout-policy` —— 零配置的 `tools/execute` 包装,按 tool 声明的 `timeoutMs` 强制超时 | +| **Todo**(`packages/todo/`)| 模型可调用的 `todo_write` tool(整表任务追踪)| +| **Support**(`packages/support/`)| `invariants` —— 由默认组合 `dsh-agent-spine-demo` 无条件挂载的运行时诊断插件;此外是仅测试/开发用的辅助包(`llm-replay`、`acp-snapshot`、`subagent-mock`)| +| **Example bundles**(`packages/examples/`)| 顶层 `demo:*` 脚本直接跑的组合示例包:`dsh-agent-spine-demo`(默认 spine + 能力)、`dsh-stdio-demo`(REPL)、`dsh-acp-demo`(ACP server)、`dsh-jsonrpc-demo` | +| **Utils**(`packages/util/`)| 内部工具包(`brand`、`timeout`)| + +完整的模块依赖图见 [`docs/module-graph.md`](./docs/module-graph.md)。 + +## 深入阅读 + +想理解 DeepSeek Harness 为什么与众不同,从这里入手: + +- [架构](./docs/architecture.md) —— 服务分类和微内核结构 +- [agent 生命周期](./docs/agent-lifecycle.md) —— 一次 turn 在 loop 里的流转(含时序图) +- [Cordis 入门](./docs/cordis-primer.md) —— 底层插件框架的实用入门 +- [工具执行流水线](./docs/tool-execution-pipeline.md) —— 一次 tool 调用如何经过权限校验、hooks 和日志 +- [能力接缝](./docs/capability-seams.md) —— 每个服务暴露的替换点 +- [Code Mode](./docs/rfc/implemented/feature/2026-06-15-code-mode.md) —— 模型每个 turn 写一段 JS 程序,在一次运行里串起多次 bash / tool 调用。**多步操作 → 一次模型往返**,不是每次调用一次往返 +- [动态工作流](./docs/rfc/implemented/feature/2026-07-05-dynamic-workflows.md) —— 模型写一段 JS orchestrator,把多个 sub-agent 并行 fan out、合并结果、再回到父 agent —— 而不是链式地调 subagent tool +- [自引用的 Cordis 工具集](./docs/rfc/implemented/feature/2026-07-08-self-referential-cordis-toolset.md) —— SDK 自身的插件管理机制(`cordis_inspect` / `cordis_mount` / `cordis_unmount`)以 tool 的形式暴露给模型,让模型能在运行时查看当前运行时并按需挂载新插件 + +文档站:**[deepseek.com/harness-sdk/docs](https://deepseek.com/harness-sdk/docs)**。 + +## 社群 + + + +- **[GitHub Issues](https://github.com/deepseek-harness/deepseek-harness/issues)** —— Bug 反馈 +- **[GitHub Discussions](https://github.com/deepseek-harness/deepseek-harness/discussions)** —— 功能建议、设计讨论、Q&A + +企业微信讨论群通过腾讯问卷申请入群,专人筛选后邀请: + +腾讯问卷 · 企业微信社群入群申请 + +## License + +[BSD 3-Clause](./LICENSE) © DeepSeek diff --git a/assets/arch-en.png b/assets/arch-en.png new file mode 100644 index 0000000000..4a84c5e590 Binary files /dev/null and b/assets/arch-en.png differ diff --git a/assets/arch-zh.png b/assets/arch-zh.png new file mode 100644 index 0000000000..c273791b9f Binary files /dev/null and b/assets/arch-zh.png differ diff --git a/assets/community-wecom-survey.png b/assets/community-wecom-survey.png new file mode 100644 index 0000000000..d6f6040ba7 Binary files /dev/null and b/assets/community-wecom-survey.png differ diff --git a/assets/demo-acp.mp4 b/assets/demo-acp.mp4 new file mode 100644 index 0000000000..b5a67deaec Binary files /dev/null and b/assets/demo-acp.mp4 differ