WebSocket protocol
The widget and the Node service communicate over a single WebSocket bound to 127.0.0.1. Every message is { type, payload }.
Server → client
{ type: 'hello', payload: { agentId, model, version } }
{ type: 'event', payload: InvokeEvent } // see agents/types.ts
{ type: 'cdp-status', payload: { state, reason?, matchingTabUrl?, browser?, launching? } }
{ type: 'specs-list', payload: { specs: SpecSummary[] } }
{ type: 'seeds-list', payload: { seeds: { name, note, signature, code, source }[] } }
{ type: 'modes', payload: { current: string|null, available: ModeEntry[] } }
{ type: '<plugin-namespaced>', payload: <plugin-specific> } // plugin-broadcast events (e.g. security:flow:*)
{ type: 'spec-saved', payload: { name, path } }
{ type: 'spec-exists', payload: { slug, existingPath } }
{ type: 'case-csv-saved', payload: { name, path } }
{ type: 'case-csv-exists', payload: { slug, existingPath } }
{ type: 'agents', payload: { current: string, available: AgentAvailability[] } }
{ type: 'error', payload: { message } }
Client → server
{ type: 'command', payload: { text, sessionId?, reRecord?: { slug } } } // when reRecord.slug is set, the service collects tool_use events server-side and on a clean session_end overwrites __vibe_tests__/<slug>.spec.ts (v0.11 ⟳ Re-record)
{ type: 'cancel' }
{ type: 'check-cdp', payload: { pageUrl } } // "is this widget in the debug Chrome?"
{ type: 'launch-chrome', payload: { pageUrl } } // start debug Chrome, navigate to pageUrl
{ type: 'focus-debug', payload: { pageUrl } } // bringToFront the matching tab in debug Chrome
{ type: 'save-spec', payload: { name, description, steps, assertions?, overwrite? } }
{ type: 'save-case-csv', payload: { name, description, steps, assertions?, jiraProjectKey?, labels?, overwrite? } }
{ type: 'list-specs' } // ask for every spec under __vibe_tests__/, with parsed JSDoc headers
{ type: 'list-seeds' } // built-in + .hover/rules/ translation seeds (read-only)
{ type: 'list-agents' }
{ type: 'switch-agent', payload: { agentId } }
{ type: 'set-mode', payload: { modeId: string|null } } // null = exit moded operation
{ type: 'list-modes' }
For the authoritative list see packages/core/src/service.ts and the InvokeEvent union in packages/core/src/agents/types.ts.