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).
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "synthesis-agent",
|
||||
"name": "SynthesisAgent",
|
||||
"description": "Manages long-lived interactive Claude Code processes per OpenClaw session; bridges OpenClaw events <-> SynthesisAgent.ClaudePlugin",
|
||||
"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
|
||||
},
|
||||
@@ -14,22 +14,17 @@
|
||||
"properties": {
|
||||
"bridgePort": {
|
||||
"type": "number",
|
||||
"default": 18801,
|
||||
"description": "TCP port the bridge WebSocket server binds on (127.0.0.1)"
|
||||
"default": 18900,
|
||||
"description": "HTTP port for the OpenAI-compatible /v1/chat/completions endpoint that OpenClaw routes agent turns to"
|
||||
},
|
||||
"bridgeToken": {
|
||||
"type": "string",
|
||||
"default": "synthesis-local",
|
||||
"description": "Shared secret each ClaudePlugin instance must present in its hello frame"
|
||||
},
|
||||
"claudePluginRef": {
|
||||
"type": "string",
|
||||
"default": "plugin:synthesis-claude@local",
|
||||
"description": "The --channels argument passed to claude on spawn"
|
||||
"channelWsPort": {
|
||||
"type": "number",
|
||||
"default": 18901,
|
||||
"description": "WebSocket port that each spawned Claude process's ClaudePlugin dials back into"
|
||||
},
|
||||
"permissionMode": {
|
||||
"type": "string",
|
||||
"default": "acceptEdits",
|
||||
"default": "bypassPermissions",
|
||||
"description": "Claude Code permission mode for spawned sessions"
|
||||
},
|
||||
"idleKillMs": {
|
||||
@@ -45,7 +40,12 @@
|
||||
"mappingDbPath": {
|
||||
"type": "string",
|
||||
"default": "~/.openclaw/synthesis/sessions.json",
|
||||
"description": "Where openclaw_session <-> claude_session UUID mapping is persisted"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user