Files
SynthesisAgent.OpenclawPlugin/openclaw.plugin.json
zhi 0324a47d13 feat: HTTP /v1/chat/completions + WS bridge + process manager
Real first cut. OpenClaw routes agent turns via /v1/chat/completions
(OpenAI-compatible SSE) into our bridge. Bridge ensures a long-lived
claude process per session-key, pushes the user message as
notifications/claude/channel into the running Claude Code, awaits a
reply via the WS connection, streams the reply back as SSE deltas.

- core/process-manager: spawn / track / reap claude processes, auto-confirm
  the --dangerously-load-development-channels dev-mode prompt by piping
  "1\n" to stdin shortly after spawn
- web/bridge-server: unified HTTP + WS server, per-session FIFO queue,
  SSE heartbeat (empty content delta — SSE comments don't reset OpenClaw's
  idle watchdog), reply buffering for streaming progress chunks
- index.ts: definePluginEntry for OpenClaw runtime + standalone-mode main
  for laptop smoke testing (just `bun index.ts`)

Same-machine simplifications: no bridge token, no permission_request
reverse channel. Session key = agent_id::chat_id (contractor-agent
convention).
2026-05-14 13:28:00 +00:00

53 lines
1.8 KiB
JSON

{
"id": "synthesis-agent",
"name": "SynthesisAgent",
"description": "Routes OpenClaw agent turns through long-lived interactive Claude Code processes; replaces the claude -p path so usage stays on the subscription quota",
"activation": {
"onStartup": true
},
"commandAliases": [
{ "name": "synthesis" }
],
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"bridgePort": {
"type": "number",
"default": 18900,
"description": "HTTP port for the OpenAI-compatible /v1/chat/completions endpoint that OpenClaw routes agent turns to"
},
"channelWsPort": {
"type": "number",
"default": 18901,
"description": "WebSocket port that each spawned Claude process's ClaudePlugin dials back into"
},
"permissionMode": {
"type": "string",
"default": "bypassPermissions",
"description": "Claude Code permission mode for spawned sessions"
},
"idleKillMs": {
"type": "number",
"default": 3600000,
"description": "Idle time after which a session's claude process is killed; next message resumes it"
},
"maxProcesses": {
"type": "number",
"default": 16,
"description": "Hard cap on concurrent claude processes; new sessions beyond this evict the oldest idle one"
},
"mappingDbPath": {
"type": "string",
"default": "~/.openclaw/synthesis/sessions.json",
"description": "Where openclaw_session ↔ claude_session_uuid mapping is persisted"
},
"channelName": {
"type": "string",
"default": "synthesis",
"description": "Name used in `--channels server:<name>` when spawning claude; must match the MCP server name in ClaudePlugin's .mcp.json"
}
}
}
}