feat: add OpenCode provider via webhook adapter - #327
Conversation
Implements HookProvider for OpenCode (opencode.ai), a server-based AI agent runtime. Unlike Claude Code (CLI-based), OpenCode runs as a persistent server with REST API + SSE event stream. Provider details: - normalizeHookEvent: translates bridge webhook payloads (session.status, message.updated, tool.start/end, session.start/end) to AgentEvent format - formatToolStatus: covers OpenCode + escal-ai custom tools (github-*, plane-*) - No file fallback (OpenCode uses DB, not JSONL transcripts) - install/uninstall are no-ops (server is always connected) - areHooksInstalled returns true Closes pixel-agents-hq#67
- compositeProvider.ts wraps multiple HookProviders, dispatching normalizeHookEvent to each in registration order. - cli.ts creates compositeProvider(claudeProvider, opencodeProvider) so the standalone server handles both webhook formats.
sessionStart necesita cwd para que Pixel Agents cree un pending external session. watchAllSessions=true permite que sesiones OpenCode (sin directorio tracked de Claude) sean aceptadas.
…cha SessionStart)
- webview-ui/public/assets/characters/: reemplazados char_0 (Aiko), char_1 (Nairo), char_2 (Kobai) con sprites recoloreados - core/src/provider.ts: AgentEvent.sessionStart incluye palette? - core/src/messages.ts: AgentCreated incluye palette? - server/src/types.ts: AgentState incluye palette? - server/src/sessionRouter.ts: PendingExternalSession incluye palette - hookEventHandler.ts: extrae palette de sessionStart, la pasa a pending y a onExternalSessionDetected - httpServer.ts: incluye palette en agentCreated WebSocket msg - fileWatcher.ts: hooks-only agent setea palette en AgentState - agentRuntime.ts: pasa palette a adoptExternalSessionFromHook - opencode.webhook.ts: normalizeHookEvent extrae agent_name + palette del payload y los usa en sessionStart - useExtensionMessages.ts: webview usa palette from agentCreated si esta presente
|
Tried this branch end-to-end on Linux with the standalone CLI ( 1. The hook route drops every OpenCode event, with a 200
if (event.session_id && event.hook_event_name) {
options.onHookEvent?.(providerId, event);
}The webhook payload this PR documents (and that So every OpenCode POST is accepted with Confirmed by isolating the pieces: One-line fix, if it fits your intent: if (event.session_id && (event.hook_event_name || event.event_type)) {Or have the provider declare which discriminator field it uses, since this is exactly the kind of thing a second hooks-only provider will hit again. 2. Opening the UI silently turns
|
Description
Adds a new
HookProviderimplementation for OpenCode (opencode.ai), enabling Pixel Agents to visualize OpenCode sessions alongside Claude Code.OpenCode is a server-based AI agent runtime (not a CLI like Claude Code). It exposes an SSE endpoint (
/global/event) and a REST API. This PR adds:Changes
server/src/providers/hook/opencode/— New provider directory:opencode.ts— HookProvider implementationopencode.webhook.ts—normalizeHookEvent+formatToolStatusopencode-constants.ts— Tool classification setsserver/src/compositeProvider.ts— New utility to wrap multiple HookProviders, dispatchingnormalizeHookEventto each in registration order. Used by the standalone CLI to support both Claude Code and OpenCode.server/src/cli.ts— Updated to create acompositeProvider(claudeProvider, opencodeProvider)so the standalone server handles both webhook formats.Event mapping (bridge → webhook):
session.status: busy→sessionStartsession.status: idle→turnEndmessage.updated(assistant) →toolStarttool.start→toolStartwith tool nametool.end→toolEndUnit tests — 23 tests covering all event types and tool status formatting
How to test
npx pixel-agents --port 3100 --host 0.0.0.0Related issues
Closes #67
Test plan
E2E coverage
Tested manually via standalone CLI (e2e tests pending; will follow up in a separate PR).