dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
web3 extensions for the deepseek harness where everything is a plugin
One-shot get-started (builds latest 02ca906 stack, tests, starts xmtp-prod, spits QR + wallet):
bash quickstart.sh
# or: MUSE_SPARK_API_KEY=<your-key> bash quickstart.shSpits Invite URL: https://popup.convos.org/v2?i=... + ANSI QR (qrencode -t ANSIUTF8) and wallet 0xa85dD3FbD8C2c831Ef156036F14638CcFf03b44e (dynamic wallet_info→ctx.wallet.address). Also available: ./show-convos-qr.sh / ./show-xmtp-qr.sh for QR-only.
Reimplementation of the sovereign web3 agent harness using DeepSeek harness as core, where everything is a plug-in. Replaces https://github.com/Haven-hvn/haven-core and https://github.com/Haven-hvn/haven-adapters
There is deliberately no aggregate bundle: people may want one capability and not another, so each package ships its own dsh.bundle.patch → cordis.patch.yml inserting only its own rows, and installs independently:
dsh plugin --profile <name> add /path/to/dsh-haven/<package>Package · Haven concept · dsh seam it lands on dsh-wallet · WalletIdentity custody ("the key never leaves this boundary") + the CryptoAdapter contract · ctx.wallet service; credentials resolved through ctx.credentials per operation — configuration carries *references*, never keys dsh-wallet-ethereum · EthereumCryptoAdapter → OWS migration plan · provider plugin registering a CryptoAdapter per chain family, backed by @open-wallet-standard/core (sign-only; the standard handles all chain families) dsh-treasury · Treasury machine: balances, expenses, FUNDED/LOW/CRITICAL/DEPLETED survival gradient · storage-domain tables + derived state; a policy plugin short-circuits agent/request and tools/pre-execute, metered off llm/token-meter dsh-channel-xmtp · XmtpChannel direct agent↔user messaging · one dsh agent per conversation (ctx.agents), inbound via agent.followup, replies via sendText; EOA identity signs through ctx.wallet dsh-storage-synapse · SynapseStorageAdapter + StorageBackend pinning · ctx.synapse + synapse_pin / synapse_pin_status agent tools; every node request wallet-signed per operation dsh-wallet-tools · wallet address/balance exposure (replaces hard-coded persona) · wallet_info tool via ctx.tools + ctx.wallet.address() live (no hard-coded 0x...) dsh-persona · Haven persona / system instructions · agent/request composition; generic instruction to call wallet_info when address/balance/funding asked dsh-tool-prowlarr · Prowlarr indexer search bridge (use-case agnostic) · prowlarr_indexers / prowlarr_search read-only tools via ctx.tools; no wallet seam dsh-tool-acquisition · Download/acquisition arm (Haven acquisition/ port, torrent clients outsourced) · acquire_submit / acquire_status tools via ctx.tools; qBittorrent → Transmission failover, no wallet seam
dsh-wallet is the custody root; the other packages build on it:
dsh-wallet ← dsh-wallet-ethereum (registers the evm CryptoAdapter)
↑
├── dsh-channel-xmtp (signs XMTP identity per signature)
├── dsh-storage-synapse (signs node requests per request)
└── dsh-wallet-tools (exposes wallet_info via ctx.tools → ctx.wallet)
dsh-persona (composes agent/request; calls wallet_info, no hard-coded address)
dsh-treasury (independent; needs the storage stack)A typical full install:
dsh plugin --profile <name> add \
/path/to/dsh-haven/dsh-wallet \
/path/to/dsh-haven/dsh-wallet-ethereum \
/path/to/dsh-haven/dsh-treasury \
/path/to/dsh-haven/dsh-channel-xmtp \
/path/to/dsh-haven/dsh-storage-synapse \
@open-wallet-standard/core @xmtp/node-sdkThe two SDKs are optional peers: every package loads, mounts, and tests without them (lazy imports with actionable errors; tests substitute internals.* seams).
dsh-treasury only): the profile must mount storage,storage-json/storage-sqlite, and storage-domain rows (present in dsh-web-app; absent in dsh-base). The treasury patch does NOT insert them — a row id inserted by two layers mounts the plugin twice.
dsh-channel-xmtp only): agents/sessions/llm, present inany agent-running profile.
inject lists stay dormant instead of failing, soinstall order is free.
Web3 plugins are isolated as code, coupled at the seam — a direct consequence of how the DeepSeek harness composes.
export const name,export const inject, export function apply(ctx, config)) with its own dsh.bundle.patch → cordis.patch.yml. There is no aggregate bundle; dsh plugin add installs one capability at a time and inject ordering is free (unmet inject stays dormant). This is why dsh-wallet, dsh-channel-xmtp, dsh-storage-synapse, dsh-treasury, and dsh-wallet-tools each build via prepare (tsdown → lib/) and test without the others (internals.* seams).
ctx.wallet (custody), ctx.tools (model-facing tools), ctx.agents/ctx.sessions (per-conversation agents), ctx.synapse/ctx.treasury (storage). Plugins declare this with inject — e.g. inject = ['wallet','tools'] in dsh-wallet-tools and dsh-storage-synapse — so they mount only when the seam exists, and call it per-operation (ctx.wallet.address(), ctx.wallet.signMessage(), ctx.tools.register(defineTool(...))).
Harness limitations that force this shape:
@deepseek-ai/dsh-tools exposes one scheduler (ctx.tools[TOOL_RUNTIME_SCHEDULER].prepare). If two instances are deduped incorrectly the Symbol mismatches and every tool/call fails with Cannot read properties of undefined (reading 'prepare'). Bundles therefore depend on dsh-tools as a peer (0.2.1-alpha.1, exact — dsh also rejects a bundle whose @deepseek-ai/dsh-* peers do not match the running CLI) and link: installs must dedupe to one copy.keyRef/wallet names; ctx.credentials.resolve runs inside signMessage/address and is dropped. Consumers (XMTP identity in dsh-channel-xmtp, per-request x-synapse-* headers in dsh-storage-synapse, wallet_info in dsh-wallet-tools) see only addresses/signatures. Hard-coding an address in persona (When asked for address, answer with 0x...) breaks rotation and wallet-agnostic installs — the correct seam is a tool that resolves ctx.wallet.address(config.wallet) live.dsh-channel-xmtp creates one ctx.agents session per XMTP conversation (SessionId derived from conversationId), handles conversations.sync() before getConversationById, reconnect/consent sweep, and dedup. The channel owns transport; the agent owns the turn.Result: add dsh-wallet once, then compose any subset. dsh-wallet-tools (wallet_info tool, presentCall: {kind:'read'}) makes the EVM address model-reachable without persona shortcuts; dsh-channel-xmtp makes it XMTP-reachable; dsh-storage-synapse makes it storage-reachable — all through ctx.wallet, none by sharing key material.
Haven's rule — *the private key never leaves its layer; everything else requests signatures* — maps to one dsh pattern used everywhere here:
keyRef,dbEncryptionKeyRef). A pasted raw key fails loud at plugin load because key material cannot syntactically be a CredentialRef.
ctx.credentials.resolve runsper call, the provider signs, every reference is dropped. Rotation reaches the very next operation without restart.
addresses and signatures through ctx.wallet.
pnpm install # workspace of five packages
pnpm vitest # specs live in <package>/tests/**Each package builds self-contained via prepare (tsdown → lib/), so git or path installs work without monorepo context. Money figures are integer µUSD (USD × 1e6) throughout, matching haven-core.