deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
English | 中文
DeepSeek Harness Python is a plugin-first agent harness with two cooperating Cordis runtimes. PyCordis owns backend plugins and the Python Agent Spine. The original TypeScript Cordis remains in the browser and owns page plugins. A versioned Browser Bridge connects them through explicit JSON RPC and Events.
The goal is a stable harness where new product behavior is normally delivered as a plugin, without changing the Agent Loop or either lifecycle kernel.
One logical plugin has one root identity and may contain a backend contribution, a client contribution, or both:
plugin.toml
backend.py
frontend/
package.json
src/
dist/client.js
protocol/api.schema.json
plugin.toml is authoritative. Nested Python or frontend package files are build inputs and cannot redefine the Plugin ID or version.
| Plugin form | Runtime | Typical use |
|---|---|---|
| Backend only | PyCordis | Tools, LLM providers, storage, workflows, policy |
| Client only | Cordis TS | Panels, commands, page state, browser integrations |
| Full stack | Both | UI backed by Python services through RPC and Events |
The two runtimes do not share objects or lifecycle state. The Dynamic Plugin Manager computes one content Revision from the manifest and declared artifacts, starts the backend Fiber, publishes the exact client bundle, and projects the desired graph to connected pages. Each page then mounts one Cordis TS child Fiber for the same Plugin ID and Revision.
flowchart LR
M["plugin.toml"] --> PM["Dynamic Plugin Manager"]
PM --> PY["PyCordis backend Fiber"]
PM --> AR["Revisioned client artifacts"]
AR --> BB["HTTP / WebSocket Browser Bridge"]
BB --> TS["Cordis TS page Fiber"]
PY <--> |"Revision-qualified RPC / Events"| BB
Enable, update, rollback, and disable are live operations. An update disposes the old backend registrations and asks pages to unload the old client Fiber before activating the replacement. Stale Revision calls lose authority. Disable removes publication, backend Effects, page Fiber contributions, and outstanding page-owned calls.
Backend plugins receive their exact Manager-owned identity through the isolated PLUGIN_RUNTIME_IDENTITY Service. Browser modules that export createPlugin(api) receive a revision-bound PluginChannel from reconciliation. Plugins never calculate or accept their own runtime Revision as user configuration.
Browser readiness is derived separately from publication. The Host defaults to requiring every connected page to activate a required client contribution; deployments may select any_connected globally or per Plugin ID. A required client plugin stays WAITING until a page connects, can recover from FAILED without republishing, and reports page-qualified diagnostics through the Manager snapshot.
The supported Python author API is harness.sdk. Backend-only plugins use define_backend_plugin; plugins that need the Browser Bridge use define_bridge_backend_plugin and identity-free RPC/Event descriptors:
from harness.sdk import define_bridge_backend_plugin, rpc_method
DESCRIBE = rpc_method("describe")
async def setup(ctx):
await ctx.channel.register_rpc(DESCRIBE, lambda arguments: arguments)
plugin = define_bridge_backend_plugin(setup)
Client plugins use the matching TypeScript SDK. defineClientPlugin binds every call, Event, listener, and custom Effect to the reconciled Plugin ID, Revision, and Cordis TS Fiber:
import { defineClientPlugin, rpcMethod } from '@deepseek-harness/browser-bridge-client'
const describe = rpcMethod<{ value: string }, { value: string }>('describe')
export const createPlugin = defineClientPlugin(async (ctx) => {
const result = await ctx.call(describe, { value: 'ready' })
document.body.dataset.plugin = result.value
return () => { delete document.body.dataset.plugin }
})
Production factories never accept Plugin ID or Revision. Test-only harnesses under harness.sdk.testing and @deepseek-harness/browser-bridge-client/testing inject fixture identity while exercising the same public lifecycle paths.
Create a complete backend-only, client-only, or full-stack project with the scaffolder:
uv --directory python run deepseek-harness-plugin create \
--kind full-stack \
--plugin-id com.example.echo \
--destination plugins/echo
uv --directory python run deepseek-harness-plugin validate plugins/echo
python -m harness.scaffold is equivalent. Generation is deterministic, refuses every existing destination, and installs no dependencies. Client templates pin the TypeScript SDK package; until that package is published, repository development links the workspace package as shown by the template acceptance tests.
frontend/
python/
harness/
tests/
pyproject.toml
uv.lock
docs/specs/
docs/source-notes/
The distribution name is deepseek-harness-python; the only supported import root is harness inside the python/ workspace. There is no src/ tree or deepseek_harness compatibility package.
all_connected and any_connected quorum, connection-generation fencing, structured diagnostics, recovery, and disable drainage.See implementation progress, the productization roadmap, and the foundation completion specification for acceptance evidence and intentional exclusions.
Build the browser runtime, then point the Host at one or more catalog directories whose immediate children contain plugin.toml:
pnpm --dir frontend install
pnpm --dir frontend run build:browser
uv --directory python run deepseek-harness-python \
--port 0 \
--plugins ./plugins \
--client-quorum all_connected \
--client-quorum-override com.example.preview=any_connected \
--browser-runtime ../frontend/dist/browser.js
The command prints the effective URL. --plugins is repeatable, and uv --directory python run python -m harness accepts the same arguments. Omit --browser-runtime for a backend-only Host without the bootstrap routes.
To activate the built-in DeepSeek-compatible route, provide the credential through the environment and configure an exact provider/model pair:
export DEEPSEEK_API_KEY='...'
uv --directory python run deepseek-harness-python \
--llm-provider deepseek \
--llm-model deepseek-chat \
--port 8765
uv --directory python run deepseek-harness-python invoke \
--url http://127.0.0.1:8765 \
'Reply with one short sentence.'
The provider consumes SSE internally so raw chunks remain in the Session log, while the invocation API returns only the terminal Assistant message. Turns for the process-lifetime Session run in FIFO order. The API key is read only when provider activation is requested; the invoke command never reads or sends it directly.
For a product-style local run, persist the Session Log and inspect its deterministic projection after restart:
uv --directory python run deepseek-harness-python \
--session-id default \
--session-db .data/sessions.sqlite \
--llm-provider deepseek \
--llm-model deepseek-chat \
--port 8765
curl http://127.0.0.1:8765/api/v1/sessions/default
SQLite persistence is optional. It stores the append-only event envelopes before they enter the in-memory snapshot; corrupt or incompatible state fails startup instead of being silently discarded.
The browser page uses the same Chat Completions contract as DeepSeek-compatible clients:
curl http://127.0.0.1:8765/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"Hello"}],"stream":false}'
The /v1/chat/completions alias is also available. The page renders the active Session projection and keeps the API key on the Host process.
Enable the loopback Plugin Control API when you need live lifecycle operations. The API is disabled by default and refuses non-loopback listeners:
uv --directory python run deepseek-harness-python --control --plugins ./plugins --port 8765
uv --directory python run deepseek-harness-python plugin --url http://127.0.0.1:8765 list
uv --directory python run deepseek-harness-python plugin --url http://127.0.0.1:8765 enable com.example.echo
uv --directory python run deepseek-harness-python plugin --url http://127.0.0.1:8765 update com.example.echo
Catalog watching is opt-in and uses the same serialized lifecycle coordinator as HTTP operations. A watcher can install new roots, hot-update valid revisions, and apply explicit create/delete policies:
uv --directory python run deepseek-harness-python \
--control \
--plugins ./plugins \
--watch-plugins ./plugins \
--watch-debounce 0.5 \
--watch-create install_disabled \
--watch-delete disable
The control API is intended for trusted local development. It has no authentication, package download, dependency installation, signatures, or untrusted-code isolation. Use uv --directory python run deepseek-harness-plugin sdk export PATH to copy the bundled Browser SDK tarball; client scaffolds vendor that exact digest with a relative file: dependency and a frozen lockfile.
uv --directory python sync
uv --directory python run playwright install chromium
uv --directory python run python -m unittest discover -s tests -v
uv --directory python run ruff check harness tests
uv --directory python run pyright
pnpm --dir frontend install
pnpm --dir frontend run typecheck
pnpm --dir frontend run test
pnpm --dir frontend run build
The current in-process Python Backend Host is for trusted local plugins. Authentication, package distribution, persistent inventory and Sessions, dependency installation, signatures, and process isolation for untrusted plugins remain product or deployment work. The current Agent Session is memory-only and does not claim restart recovery. New product phases start with a normative specification under docs/specs/ and update implementation progress with executable evidence.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。