Skip to content

feat(agent): add dsh agent — bridge cc-connect to a running DeepSeek Harness (dsh) web server - #1676

Open
whiteguo233 wants to merge 2 commits into
chenhg5:mainfrom
whiteguo233:feat/dsh-agent
Open

feat(agent): add dsh agent — bridge cc-connect to a running DeepSeek Harness (dsh) web server#1676
whiteguo233 wants to merge 2 commits into
chenhg5:mainfrom
whiteguo233:feat/dsh-agent

Conversation

@whiteguo233

Copy link
Copy Markdown

Summary

Adds a new agent adapter agent/dsh that bridges cc-connect to a running DeepSeek Harness (dsh) web server on the same machine, so any cc-connect platform (Feishu, Telegram, WeChat, …) can drive dsh sessions — including the plugin-style Go module published at dsh-external/dsh-cc-connect.

What it does

  • Sessions: POST /api/session.create with the project work_dir as cwd; same session id + cwd is idempotent server-side, so cc-connect restarts resume the same dsh conversation automatically.
  • Streaming: consumes the aggregated WebSocket event stream (GET /api/events.mux); text/reasoning deltas are coalesced into sentence-sized chunks (dsh streams token-by-token) so IM delivery isn't word-by-word.
  • Permissions: approval/requestedEventPermissionRequest (Feishu Allow/Deny buttons) → POST /api/respond; question/requested → AskUserQuestion cards with answers mapped back to option labels.
  • Commands: /stop via session.cancel (AgentSessionCanceller), per-turn timeout_mins watchdog, /model via session.models/selectModel, /list + cross-project session-id validation, cc-connect doctor reachability check.
  • cc-connect CLI integration: CC_PROJECT/CC_SESSION_KEY/CC_DATA_DIR injected into the first prompt of fresh sessions so in-session cron/timer/relay CLI calls work; ProjectMemoryFile() returns <work_dir>/AGENTS.md (dsh natively loads it), so relay/cron instructions land in the model context.
  • Frame-loss protection: the mux stream aggregates every server session; the socket reader filters to the target session and gives critical frames (turn/end, approval/question requests, stream errors) blocking priority — without this a busy Web GUI flood could drop turn/end and leave the engine stuck after a permission answer.

Changes

  • agent/dsh/ — new adapter (client.go RPC/WebSocket wire, session.go AgentSession + event mapping, dsh.go Agent + optional interfaces, aggregator.go delta coalescing) with 16 unit tests (mock dsh server over a real WebSocket) plus a smoke-tagged integration test against a live server
  • cmd/cc-connect/plugin_agent_dsh.go//go:build !no_dsh registration
  • Makefiledsh added to ALL_AGENTS
  • config.example.toml — dsh project example (bilingual)
  • CHANGELOG.md — Unreleased entry
  • web/src/pages/Projects/ProjectList.tsx — add dsh (+ other registered-but-missing agents) to the new-project wizard's hardcoded AGENT_OPTIONS (the detail page already lists agents from the API)
  • web/pnpm-workspace.yaml — fix malformed esbuild allowlist (onlyBuiltDependencies: esbuild scalar → allowBuilds: { esbuild: true }); without it vite build fails on pnpm 10.13+

Verification

  • go vet ./agent/dsh/, CGO_ENABLED=0 GOOS=linux go build ./... (CI platform), go test -race ./agent/dsh/ — all green
  • web build (tsc && vite build) — green
  • End-to-end smoke test against a real dsh web server (session create → prompt → streamed reply) — passed
  • Deployed in production on macOS for several days: streaming, rich cards, permission round-trips, /stop, resume all working

Notes

  • Requires a running dsh web server on the same machine (default http://127.0.0.1:3080); config field base_url overrides.
  • macOS go build ./... currently fails on origin/main itself (daemon/check_linger_other.go has //go:build !linux while daemon/launchd.go has //go:build darwin, redeclaring CheckLinger). Unrelated to this PR; the linux build (CI) is green. Happy to fix it separately if desired.

white added 2 commits August 14, 2026 00:55
…h) web server

Implements the core.Agent / core.AgentSession interfaces over the dsh
typed RPC API (POST /api/session.<method>) and the aggregated WebSocket
event stream (GET /api/events.mux):

- Sessions are created per-project (work_dir as cwd) and resume
  automatically; the same session id + cwd is idempotent on the server.
- Streaming output: text/reasoning deltas are coalesced into sentence-
  sized EventText/EventThinking chunks (dsh streams token-by-token) so
  platform delivery is not word-by-word.
- Permission round-trips: approval/requested -> EventPermissionRequest ->
  POST /api/respond; AskUserQuestion cards map back to option labels.
- /stop via session.cancel (AgentSessionCanceller), per-turn timeout_mins
  watchdog, /model via session.selectModel, /list + cross-project session
  id validation, cc-connect doctor reachability check.
- CC_PROJECT / CC_SESSION_KEY / CC_DATA_DIR are injected into the first
  prompt of fresh sessions so the in-session cc-connect CLI (cron/timer/
  relay) works; ProjectMemoryFile returns <work_dir>/AGENTS.md which dsh
  natively loads.
- Frame-loss protection: the mux stream aggregates every server session,
  so the socket reader filters to the target session and gives critical
  frames (turn/end, approval/question requests, stream errors) blocking
  priority — a flood from other sessions previously dropped turn/end and
  left the engine stuck after a permission answer.
- session.list updatedAt parsed as float64 (dsh reports fractional
  millisecond timestamps).

16 unit tests (mock dsh server over real WebSocket) + build-tagged smoke
test against a live server. Requires a running dsh web server
(default http://127.0.0.1:3080).
…wlist

- AGENT_OPTIONS in the project wizard was hardcoded and stale: add dsh
  (DSH / DeepSeek Harness) plus the other registered-but-missing agents
  (reasonix, kimi, iflow, pi, tmux) so the wizard matches the backend
  registry. The project detail page already lists agents from the API.
- web/pnpm-workspace.yaml used a malformed 'onlyBuiltDependencies: esbuild'
  scalar; pnpm 10.13+ requires the 'allowBuilds' map. Without the esbuild
  postinstall the vite build fails ('esbuild binary not found').
@whiteguo233
whiteguo233 requested a review from chenhg5 as a code owner August 13, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant