@agentic-patterns/server 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ const app = createServer({
|
|
|
37
37
|
sseExporter: sse,
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
serve({ fetch: app.fetch, port:
|
|
40
|
+
serve({ fetch: app.fetch, port: 3456 });
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
## Routes
|
|
@@ -76,13 +76,39 @@ Consumers subscribe via `EventSource("/admin/events/stream")`.
|
|
|
76
76
|
|
|
77
77
|
`POST /hooks/:eventType` accepts raw Claude Code lifecycle payloads and:
|
|
78
78
|
|
|
79
|
-
1. Validates the event name against the 26 known lifecycle events
|
|
79
|
+
1. Validates the event name against the 26 known lifecycle events
|
|
80
80
|
2. Publishes a `ClaudeCodeHookEvent` to the bus, preserving the full raw payload
|
|
81
81
|
3. Derives matching `agent.tool.start` / `agent.tool.end` events for `PreToolUse` / `PostToolUse` so standard dashboard views light up automatically
|
|
82
82
|
4. If the request carries an `x-ap-runner-correlation-id` header, skips step 3 (runner already emits tool events natively)
|
|
83
83
|
|
|
84
84
|
Pair with the `hooks/emit.mjs` script shipped at the repo root — a zero-dependency Node script that reads Claude Code hook stdin and POSTs here, always exiting 0 so hooks never block the user.
|
|
85
85
|
|
|
86
|
+
### Supported events
|
|
87
|
+
|
|
88
|
+
| Category | Events |
|
|
89
|
+
|---|---|
|
|
90
|
+
| Session | `SessionStart`, `InstructionsLoaded`, `SessionEnd` |
|
|
91
|
+
| Prompt | `UserPromptSubmit` |
|
|
92
|
+
| Tools | `PreToolUse`, `PostToolUse`, `PostToolUseFailure` |
|
|
93
|
+
| Permissions | `PermissionRequest`, `PermissionDenied` |
|
|
94
|
+
| Subagents & tasks | `SubagentStart`, `SubagentStop`, `TaskCreated`, `TaskCompleted`, `TeammateIdle` |
|
|
95
|
+
| Stop | `Stop`, `StopFailure` |
|
|
96
|
+
| Workspace | `ConfigChange`, `CwdChanged`, `FileChanged`, `WorktreeCreate`, `WorktreeRemove` |
|
|
97
|
+
| Compaction | `PreCompact`, `PostCompact` |
|
|
98
|
+
| Elicitation | `Elicitation`, `ElicitationResult` |
|
|
99
|
+
| Notification | `Notification` |
|
|
100
|
+
|
|
101
|
+
### Troubleshooting
|
|
102
|
+
|
|
103
|
+
Events not arriving? Check in this order:
|
|
104
|
+
|
|
105
|
+
1. `curl -X POST http://localhost:3456/hooks/UserPromptSubmit -H "content-type: application/json" -d '{"session_id":"t","hook_event_name":"UserPromptSubmit"}'` returns `{"ok":true}` → server is up
|
|
106
|
+
2. `curl -N http://localhost:3456/admin/events/stream` shows the event during step 1 → bus wiring is fine
|
|
107
|
+
3. Consumer project has `.claude/settings.json` with 26 entries referencing `${CLAUDE_PROJECT_DIR}/hooks/emit.mjs`
|
|
108
|
+
4. `AP_DASHBOARD_URL` in the project's `.env` matches the server's bind address
|
|
109
|
+
|
|
110
|
+
Full guide: [CLAUDE-CODE-PLUGIN-ACTIVATION.md](../../docs/CLAUDE-CODE-PLUGIN-ACTIVATION.md) — activation model, failure modes, emit.mjs contract.
|
|
111
|
+
|
|
86
112
|
## Configuration
|
|
87
113
|
|
|
88
114
|
```typescript
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/app.ts","../src/middleware/cors.ts","../src/middleware/error-handler.ts","../src/routes/admin.ts","../src/routes/agents.ts","../src/routes/conversations.ts","../src/sse.ts","../src/routes/health.ts","../src/routes/hooks.ts"],"sourcesContent":["// @agentic-patterns/server — barrel export\nexport { createServer } from \"./app.js\";\nexport type {\n ServerConfig,\n AgentRegistration,\n AdminServiceProtocol,\n SSEExporterLike,\n ConversationStoreLike,\n CORSConfig,\n} from \"./config.js\";\nexport { agentEventToSSE, type SSEMessage } from \"./sse.js\";\n","/**\n * Hono application factory.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"./config.js\";\nimport { corsMiddleware } from \"./middleware/cors.js\";\nimport { errorHandler } from \"./middleware/error-handler.js\";\nimport { adminRoutes } from \"./routes/admin.js\";\nimport { agentRoutes } from \"./routes/agents.js\";\nimport { type ConversationEntry, conversationRoutes } from \"./routes/conversations.js\";\nimport { healthRoutes } from \"./routes/health.js\";\nimport { hookRoutes } from \"./routes/hooks.js\";\n\n/**\n * Create a configured Hono app with all routes.\n *\n * Each call creates a fresh conversation registry, so multiple\n * servers in the same process do not share conversation state.\n */\nexport function createServer(config: ServerConfig): Hono {\n const app = new Hono();\n const conversations = new Map<string, ConversationEntry>();\n\n // Middleware\n app.use(\"*\", corsMiddleware(config.cors));\n app.onError(errorHandler);\n\n // Routes\n app.route(\"/\", healthRoutes());\n app.route(\"/\", agentRoutes(config.agents));\n app.route(\"/\", conversationRoutes(config.agents, conversations, config.eventBus));\n app.route(\"/\", adminRoutes(config));\n app.route(\"/\", hookRoutes(config.eventBus));\n\n return app;\n}\n","/**\n * CORS middleware for dashboard dev.\n */\n\nimport { cors } from \"hono/cors\";\nimport type { CORSConfig } from \"../config.js\";\n\n/**\n * Build the Hono cors middleware for this server.\n *\n * Defaults are permissive (`origin: \"*\"`) for local development; callers\n * should pin origin/headers/credentials for production via `ServerConfig.cors`.\n */\nexport function corsMiddleware(config?: CORSConfig) {\n return cors({\n origin: config?.origin ?? \"*\",\n allowMethods: config?.allowMethods ?? [\"GET\", \"POST\", \"OPTIONS\"],\n allowHeaders: config?.allowHeaders ?? [\"Content-Type\"],\n ...(config?.maxAge !== undefined ? { maxAge: config.maxAge } : {}),\n ...(config?.credentials !== undefined ? { credentials: config.credentials } : {}),\n ...(config?.exposeHeaders !== undefined ? { exposeHeaders: config.exposeHeaders } : {}),\n });\n}\n","/**\n * Global error handler.\n */\n\nimport type { ErrorHandler } from \"hono\";\n\nexport const errorHandler: ErrorHandler = (err, c) => {\n console.error(\"Server error:\", err);\n return c.json({ error: err.message || \"Internal server error\" }, 500);\n};\n","/**\n * Admin routes — dashboard stats, tool analytics, token usage, live event stream.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"../config.js\";\n\nexport function adminRoutes(config: ServerConfig): Hono {\n const app = new Hono();\n\n app.get(\"/admin/dashboard\", async (c) => {\n const stats = await config.adminService.getDashboardStats();\n return c.json(stats);\n });\n\n app.get(\"/admin/agents\", async (c) => {\n const agents = await config.adminService.getAllAgentStats();\n return c.json(agents);\n });\n\n app.get(\"/admin/tools\", async (c) => {\n const tools = await config.adminService.getToolAnalytics();\n return c.json(tools);\n });\n\n app.get(\"/admin/tokens\", async (c) => {\n const groupBy = (c.req.query(\"group_by\") as \"agent\" | \"model\") ?? \"agent\";\n const usage = await config.adminService.getTokenUsage({ groupBy });\n return c.json(usage);\n });\n\n app.get(\"/admin/events/stream\", (c) => {\n const stream = config.sseExporter.connect();\n\n c.req.raw.signal.addEventListener(\"abort\", () => {\n config.sseExporter.disconnect(stream);\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n });\n\n return app;\n}\n","/**\n * Agent listing routes.\n */\n\nimport { Hono } from \"hono\";\nimport type { AgentRegistration } from \"../config.js\";\n\nexport function agentRoutes(agents: AgentRegistration[]): Hono {\n const app = new Hono();\n\n app.get(\"/agents\", (c) => {\n const summaries = agents.map((a) => ({\n id: a.id,\n name: a.name,\n description: a.description ?? \"\",\n }));\n return c.json(summaries);\n });\n\n return app;\n}\n","/**\n * Conversation routes — create conversations and stream messages via SSE.\n */\n\nimport type { AgentEventBus } from \"@agentic-patterns/runtime\";\nimport { Conversation, createToolboxExecutor } from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { AgentRegistration } from \"../config.js\";\nimport { agentEventToSSE } from \"../sse.js\";\n\n/** Entry in the per-server conversation registry. */\nexport interface ConversationEntry {\n conversation: Conversation;\n agentId: string;\n}\n\nexport function conversationRoutes(\n agents: AgentRegistration[],\n conversations: Map<string, ConversationEntry>,\n eventBus: AgentEventBus,\n): Hono {\n const app = new Hono();\n\n // POST /conversations — create a new conversation\n app.post(\"/conversations\", async (c) => {\n const body = await c.req.json<{ agent_id: string }>();\n const agentId = body.agent_id;\n\n const reg = agents.find((a) => a.id === agentId);\n if (!reg) {\n return c.json({ error: \"Agent not found\" }, 404);\n }\n\n // Wire a ToolExecutor so AgentRunner can actually execute tool calls\n // from the agent's Capability toolboxes (not just format them for the LLM).\n const toolExecutor = createToolboxExecutor(\n reg.agent as unknown as Parameters<typeof createToolboxExecutor>[0],\n );\n const conversation = new Conversation(reg.agent, reg.runner, { toolExecutor });\n conversations.set(conversation.id, { conversation, agentId });\n\n return c.json({ id: conversation.id, agent_id: agentId }, 201);\n });\n\n // POST /conversations/:id/messages — send message, stream SSE response\n app.post(\"/conversations/:id/messages\", async (c) => {\n const convId = c.req.param(\"id\");\n const entry = conversations.get(convId);\n\n if (!entry) {\n return c.json({ error: \"Conversation not found\" }, 404);\n }\n\n const body = await c.req.json<{ content: string }>();\n const content = body.content;\n\n if (!content || typeof content !== \"string\") {\n return c.json({ error: \"content is required\" }, 400);\n }\n\n const { conversation } = entry;\n\n if (!conversation.runner.stream) {\n return c.json({ error: \"Streaming not supported by this runner\" }, 501);\n }\n\n // SSE streaming response. We pass the server's shared eventBus so\n // emitted events reach every attached exporter (collector, SSE\n // broadcast, etc.) in addition to flowing through the generator for\n // this client stream.\n return streamSSE(c, async (stream) => {\n for await (const event of conversation.stream(content, { eventBus })) {\n const msg = agentEventToSSE(event);\n if (msg) {\n await stream.writeSSE(msg);\n }\n }\n\n await stream.writeSSE({ event: \"done\", data: \"{}\" });\n });\n });\n\n return app;\n}\n","/**\n * SSE formatting for Hono streaming.\n *\n * Converts AgentEvents to `{ event, data }` objects compatible with Hono's\n * streamSSE writeSSE() method.\n *\n * Delegates wire-name and payload mapping to the runtime's canonical\n * `toSSEMapping` so the server stays in sync with the 20-event vocabulary\n * defined in the spec. Only internal observability events (iteration.* and\n * llm.*) are filtered here — they remain available over the admin SSE\n * stream (SSEExporter) for operators.\n */\n\nimport type { AgentEvent, AgentEventType } from \"@agentic-patterns/runtime\";\nimport { toSSEMapping } from \"@agentic-patterns/runtime\";\n\n/** SSE message shape for Hono's writeSSE(). */\nexport interface SSEMessage {\n event: string;\n data: string;\n}\n\n/**\n * Internal observability events not surfaced to end clients. They remain\n * available over the admin SSE stream for operators.\n */\nconst INTERNAL_EVENT_TYPES: ReadonlySet<AgentEventType> = new Set<AgentEventType>([\n \"agent.iteration.start\",\n \"agent.iteration.end\",\n \"agent.llm.start\",\n \"agent.llm.end\",\n]);\n\n/**\n * Convert an AgentEvent to an SSE message for Hono streaming.\n *\n * Returns `null` for events that are not part of the client-facing\n * protocol (internal observability events, or events with no SSE mapping).\n */\nexport function agentEventToSSE(event: AgentEvent): SSEMessage | null {\n if (INTERNAL_EVENT_TYPES.has(event.type)) return null;\n const mapping = toSSEMapping(event);\n if (!mapping) return null;\n return { event: mapping.name, data: JSON.stringify(mapping.payload) };\n}\n","/**\n * Health check route.\n */\n\nimport { Hono } from \"hono\";\n\nexport function healthRoutes(): Hono {\n const app = new Hono();\n app.get(\"/health\", (c) => c.json({ status: \"ok\" }));\n return app;\n}\n","/**\n * Claude Code hook bridge — receive hook callbacks from the Claude Code\n * CLI and republish them on the AgentEventBus.\n *\n * The Claude Code CLI is configured (via `.claude/settings.json`) to POST\n * each hook callback as JSON to `/hooks/:eventType`. We validate the\n * event name against the known hook list, normalize the payload into a\n * `ClaudeCodeHookEvent`, publish it to the bus, then publish any derived\n * canonical events (PreToolUse → agent.tool.start, etc.).\n */\n\nimport {\n type AgentEventBus,\n type ClaudeCodeHookEvent,\n isClaudeCodeHookName,\n mapClaudeCodeHookToAgentEvents,\n} from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\n\nfunction newSpanId(): string {\n if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n return (globalThis as unknown as { crypto: { randomUUID(): string } }).crypto.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function hookRoutes(eventBus: AgentEventBus): Hono {\n const app = new Hono();\n\n app.post(\"/hooks/:eventType\", async (c) => {\n const eventType = c.req.param(\"eventType\");\n if (!isClaudeCodeHookName(eventType)) {\n return c.json({ error: `unknown hook event: ${eventType}` }, 400);\n }\n\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const sessionId = typeof body.session_id === \"string\" ? body.session_id : \"unknown\";\n\n // Runner correlation: when a ClaudeCodeRunner spawned this CC session it\n // tags every hook POST with `x-ap-runner-correlation-id`. We preserve the\n // raw hook (PreCompact, PermissionRequest, etc. give value the runner\n // doesn't emit) but SKIP deriving `agent.tool.start`/`agent.tool.end`\n // events to avoid double-counting alongside the runner's own tool events.\n const runnerCorrelationId =\n c.req.header(\"x-ap-runner-correlation-id\") ?? undefined;\n\n const hookEvent: ClaudeCodeHookEvent = {\n type: \"claude_code.hook\",\n traceId: sessionId,\n runId: sessionId,\n spanId: newSpanId(),\n timestamp: new Date(),\n hookName: eventType,\n sessionId,\n transcriptPath:\n typeof body.transcript_path === \"string\" ? body.transcript_path : undefined,\n cwd: typeof body.cwd === \"string\" ? body.cwd : undefined,\n permissionMode:\n typeof body.permission_mode === \"string\" ? body.permission_mode : undefined,\n toolName: typeof body.tool_name === \"string\" ? body.tool_name : undefined,\n toolInput: body.tool_input,\n toolResponse: body.tool_response,\n toolUseId: typeof body.tool_use_id === \"string\" ? body.tool_use_id : undefined,\n payload: body,\n ...(runnerCorrelationId ? { runnerCorrelationId } : {}),\n };\n\n await eventBus.publish(hookEvent);\n\n if (!runnerCorrelationId) {\n const derived = mapClaudeCodeHookToAgentEvents(hookEvent);\n for (const e of derived) {\n await eventBus.publish(e);\n }\n }\n\n return c.json({ ok: true });\n });\n\n return app;\n}\n"],"mappings":"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","names":["import_hono","import_hono","import_runtime","import_hono","import_hono","import_runtime","import_hono"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/app.ts","../src/middleware/cors.ts","../src/middleware/error-handler.ts","../src/routes/admin.ts","../src/routes/agents.ts","../src/routes/conversations.ts","../src/sse.ts","../src/routes/health.ts","../src/routes/hooks.ts"],"sourcesContent":["// @agentic-patterns/server — barrel export\nexport { createServer } from \"./app.js\";\nexport type {\n ServerConfig,\n AgentRegistration,\n AdminServiceProtocol,\n SSEExporterLike,\n ConversationStoreLike,\n CORSConfig,\n} from \"./config.js\";\nexport { agentEventToSSE, type SSEMessage } from \"./sse.js\";\n","/**\n * Hono application factory.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"./config.js\";\nimport { corsMiddleware } from \"./middleware/cors.js\";\nimport { errorHandler } from \"./middleware/error-handler.js\";\nimport { adminRoutes } from \"./routes/admin.js\";\nimport { agentRoutes } from \"./routes/agents.js\";\nimport { type ConversationEntry, conversationRoutes } from \"./routes/conversations.js\";\nimport { healthRoutes } from \"./routes/health.js\";\nimport { hookRoutes } from \"./routes/hooks.js\";\n\n/**\n * Create a configured Hono app with all routes.\n *\n * Each call creates a fresh conversation registry, so multiple\n * servers in the same process do not share conversation state.\n */\nexport function createServer(config: ServerConfig): Hono {\n const app = new Hono();\n const conversations = new Map<string, ConversationEntry>();\n\n // Middleware\n app.use(\"*\", corsMiddleware(config.cors));\n app.onError(errorHandler);\n\n // Routes\n app.route(\"/\", healthRoutes());\n app.route(\"/\", agentRoutes(config.agents));\n app.route(\"/\", conversationRoutes(config.agents, conversations, config.eventBus));\n app.route(\"/\", adminRoutes(config));\n app.route(\"/\", hookRoutes(config.eventBus));\n\n return app;\n}\n","/**\n * CORS middleware for dashboard dev.\n */\n\nimport { cors } from \"hono/cors\";\nimport type { CORSConfig } from \"../config.js\";\n\n/**\n * Build the Hono cors middleware for this server.\n *\n * Defaults are permissive (`origin: \"*\"`) for local development; callers\n * should pin origin/headers/credentials for production via `ServerConfig.cors`.\n */\nexport function corsMiddleware(config?: CORSConfig) {\n return cors({\n origin: config?.origin ?? \"*\",\n allowMethods: config?.allowMethods ?? [\"GET\", \"POST\", \"OPTIONS\"],\n allowHeaders: config?.allowHeaders ?? [\"Content-Type\"],\n ...(config?.maxAge !== undefined ? { maxAge: config.maxAge } : {}),\n ...(config?.credentials !== undefined ? { credentials: config.credentials } : {}),\n ...(config?.exposeHeaders !== undefined ? { exposeHeaders: config.exposeHeaders } : {}),\n });\n}\n","/**\n * Global error handler.\n */\n\nimport type { ErrorHandler } from \"hono\";\n\nexport const errorHandler: ErrorHandler = (err, c) => {\n console.error(\"Server error:\", err);\n return c.json({ error: err.message || \"Internal server error\" }, 500);\n};\n","/**\n * Admin routes — dashboard stats, tool analytics, token usage, live event stream.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"../config.js\";\n\nexport function adminRoutes(config: ServerConfig): Hono {\n const app = new Hono();\n\n app.get(\"/admin/dashboard\", async (c) => {\n const stats = await config.adminService.getDashboardStats();\n return c.json(stats);\n });\n\n app.get(\"/admin/agents\", async (c) => {\n const agents = await config.adminService.getAllAgentStats();\n return c.json(agents);\n });\n\n app.get(\"/admin/tools\", async (c) => {\n const tools = await config.adminService.getToolAnalytics();\n return c.json(tools);\n });\n\n app.get(\"/admin/tokens\", async (c) => {\n const groupBy = (c.req.query(\"group_by\") as \"agent\" | \"model\") ?? \"agent\";\n const usage = await config.adminService.getTokenUsage({ groupBy });\n return c.json(usage);\n });\n\n app.get(\"/admin/events/stream\", (c) => {\n const stream = config.sseExporter.connect();\n\n c.req.raw.signal.addEventListener(\"abort\", () => {\n config.sseExporter.disconnect(stream);\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n });\n\n return app;\n}\n","/**\n * Agent listing routes.\n */\n\nimport { Hono } from \"hono\";\nimport type { AgentRegistration } from \"../config.js\";\n\nexport function agentRoutes(agents: AgentRegistration[]): Hono {\n const app = new Hono();\n\n app.get(\"/agents\", (c) => {\n const summaries = agents.map((a) => ({\n id: a.id,\n name: a.name,\n description: a.description ?? \"\",\n }));\n return c.json(summaries);\n });\n\n return app;\n}\n","/**\n * Conversation routes — create conversations and stream messages via SSE.\n */\n\nimport type { AgentEventBus } from \"@agentic-patterns/runtime\";\nimport { Conversation, createToolboxExecutor } from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { AgentRegistration } from \"../config.js\";\nimport { agentEventToSSE } from \"../sse.js\";\n\n/** Entry in the per-server conversation registry. */\nexport interface ConversationEntry {\n conversation: Conversation;\n agentId: string;\n}\n\nexport function conversationRoutes(\n agents: AgentRegistration[],\n conversations: Map<string, ConversationEntry>,\n eventBus: AgentEventBus,\n): Hono {\n const app = new Hono();\n\n // POST /conversations — create a new conversation\n app.post(\"/conversations\", async (c) => {\n const body = await c.req.json<{ agent_id: string }>();\n const agentId = body.agent_id;\n\n const reg = agents.find((a) => a.id === agentId);\n if (!reg) {\n return c.json({ error: \"Agent not found\" }, 404);\n }\n\n // Wire a ToolExecutor so AgentRunner can actually execute tool calls\n // from the agent's Capability toolboxes (not just format them for the LLM).\n const toolExecutor = createToolboxExecutor(\n reg.agent as unknown as Parameters<typeof createToolboxExecutor>[0],\n );\n const conversation = new Conversation(reg.agent, reg.runner, { toolExecutor });\n conversations.set(conversation.id, { conversation, agentId });\n\n return c.json({ id: conversation.id, agent_id: agentId }, 201);\n });\n\n // POST /conversations/:id/messages — send message, stream SSE response\n app.post(\"/conversations/:id/messages\", async (c) => {\n const convId = c.req.param(\"id\");\n const entry = conversations.get(convId);\n\n if (!entry) {\n return c.json({ error: \"Conversation not found\" }, 404);\n }\n\n const body = await c.req.json<{ content: string }>();\n const content = body.content;\n\n if (!content || typeof content !== \"string\") {\n return c.json({ error: \"content is required\" }, 400);\n }\n\n const { conversation } = entry;\n\n if (!conversation.runner.stream) {\n return c.json({ error: \"Streaming not supported by this runner\" }, 501);\n }\n\n // SSE streaming response. We pass the server's shared eventBus so\n // emitted events reach every attached exporter (collector, SSE\n // broadcast, etc.) in addition to flowing through the generator for\n // this client stream.\n return streamSSE(c, async (stream) => {\n for await (const event of conversation.stream(content, { eventBus })) {\n const msg = agentEventToSSE(event);\n if (msg) {\n await stream.writeSSE(msg);\n }\n }\n\n await stream.writeSSE({ event: \"done\", data: \"{}\" });\n });\n });\n\n return app;\n}\n","/**\n * SSE formatting for Hono streaming.\n *\n * Converts AgentEvents to `{ event, data }` objects compatible with Hono's\n * streamSSE writeSSE() method.\n *\n * Delegates wire-name and payload mapping to the runtime's canonical\n * `toSSEMapping` so the server stays in sync with the 20-event vocabulary\n * defined in the spec. Only internal observability events (iteration.* and\n * llm.*) are filtered here — they remain available over the admin SSE\n * stream (SSEExporter) for operators.\n */\n\nimport type { AgentEvent, AgentEventType } from \"@agentic-patterns/runtime\";\nimport { toSSEMapping } from \"@agentic-patterns/runtime\";\n\n/** SSE message shape for Hono's writeSSE(). */\nexport interface SSEMessage {\n event: string;\n data: string;\n}\n\n/**\n * Internal observability events not surfaced to end clients. They remain\n * available over the admin SSE stream for operators.\n */\nconst INTERNAL_EVENT_TYPES: ReadonlySet<AgentEventType> = new Set<AgentEventType>([\n \"agent.iteration.start\",\n \"agent.iteration.end\",\n \"agent.llm.start\",\n \"agent.llm.end\",\n]);\n\n/**\n * Convert an AgentEvent to an SSE message for Hono streaming.\n *\n * Returns `null` for events that are not part of the client-facing\n * protocol (internal observability events, or events with no SSE mapping).\n */\nexport function agentEventToSSE(event: AgentEvent): SSEMessage | null {\n if (INTERNAL_EVENT_TYPES.has(event.type)) return null;\n const mapping = toSSEMapping(event);\n if (!mapping) return null;\n return { event: mapping.name, data: JSON.stringify(mapping.payload) };\n}\n","/**\n * Health check route.\n */\n\nimport { Hono } from \"hono\";\n\nexport function healthRoutes(): Hono {\n const app = new Hono();\n app.get(\"/health\", (c) => c.json({ status: \"ok\" }));\n return app;\n}\n","/**\n * Claude Code hook bridge — receive hook callbacks from the Claude Code\n * CLI and republish them on the AgentEventBus.\n *\n * The Claude Code CLI is configured (via `.claude/settings.json`) to POST\n * each hook callback as JSON to `/hooks/:eventType`. We validate the\n * event name against the known hook list, normalize the payload into a\n * `ClaudeCodeHookEvent`, publish it to the bus, then publish any derived\n * canonical events (PreToolUse → agent.tool.start, etc.).\n */\n\nimport {\n type AgentEventBus,\n type ClaudeCodeHookEvent,\n isClaudeCodeHookName,\n mapClaudeCodeHookToAgentEvents,\n} from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\n\nfunction newSpanId(): string {\n if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n return (globalThis as unknown as { crypto: { randomUUID(): string } }).crypto.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function hookRoutes(eventBus: AgentEventBus): Hono {\n const app = new Hono();\n\n app.post(\"/hooks/:eventType\", async (c) => {\n const eventType = c.req.param(\"eventType\");\n if (!isClaudeCodeHookName(eventType)) {\n return c.json({ error: `unknown hook event: ${eventType}` }, 400);\n }\n\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const sessionId = typeof body.session_id === \"string\" ? body.session_id : \"unknown\";\n\n // Runner correlation: when a ClaudeCodeRunner spawned this CC session it\n // tags every hook POST with `x-ap-runner-correlation-id`. We preserve the\n // raw hook (PreCompact, PermissionRequest, etc. give value the runner\n // doesn't emit) but SKIP deriving `agent.tool.start`/`agent.tool.end`\n // events to avoid double-counting alongside the runner's own tool events.\n const runnerCorrelationId = c.req.header(\"x-ap-runner-correlation-id\") ?? undefined;\n\n const hookEvent: ClaudeCodeHookEvent = {\n type: \"claude_code.hook\",\n traceId: sessionId,\n runId: sessionId,\n spanId: newSpanId(),\n timestamp: new Date(),\n hookName: eventType,\n sessionId,\n transcriptPath: typeof body.transcript_path === \"string\" ? body.transcript_path : undefined,\n cwd: typeof body.cwd === \"string\" ? body.cwd : undefined,\n permissionMode: typeof body.permission_mode === \"string\" ? body.permission_mode : undefined,\n toolName: typeof body.tool_name === \"string\" ? body.tool_name : undefined,\n toolInput: body.tool_input,\n toolResponse: body.tool_response,\n toolUseId: typeof body.tool_use_id === \"string\" ? body.tool_use_id : undefined,\n payload: body,\n ...(runnerCorrelationId ? { runnerCorrelationId } : {}),\n };\n\n await eventBus.publish(hookEvent);\n\n if (!runnerCorrelationId) {\n const derived = mapClaudeCodeHookToAgentEvents(hookEvent);\n for (const e of derived) {\n await eventBus.publish(e);\n }\n }\n\n return c.json({ ok: true });\n });\n\n return app;\n}\n"],"mappings":"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","names":["import_hono","import_hono","import_runtime","import_hono","import_hono","import_runtime","import_hono"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/app.ts","../src/middleware/cors.ts","../src/middleware/error-handler.ts","../src/routes/admin.ts","../src/routes/agents.ts","../src/routes/conversations.ts","../src/sse.ts","../src/routes/health.ts","../src/routes/hooks.ts"],"sourcesContent":["/**\n * Hono application factory.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"./config.js\";\nimport { corsMiddleware } from \"./middleware/cors.js\";\nimport { errorHandler } from \"./middleware/error-handler.js\";\nimport { adminRoutes } from \"./routes/admin.js\";\nimport { agentRoutes } from \"./routes/agents.js\";\nimport { type ConversationEntry, conversationRoutes } from \"./routes/conversations.js\";\nimport { healthRoutes } from \"./routes/health.js\";\nimport { hookRoutes } from \"./routes/hooks.js\";\n\n/**\n * Create a configured Hono app with all routes.\n *\n * Each call creates a fresh conversation registry, so multiple\n * servers in the same process do not share conversation state.\n */\nexport function createServer(config: ServerConfig): Hono {\n const app = new Hono();\n const conversations = new Map<string, ConversationEntry>();\n\n // Middleware\n app.use(\"*\", corsMiddleware(config.cors));\n app.onError(errorHandler);\n\n // Routes\n app.route(\"/\", healthRoutes());\n app.route(\"/\", agentRoutes(config.agents));\n app.route(\"/\", conversationRoutes(config.agents, conversations, config.eventBus));\n app.route(\"/\", adminRoutes(config));\n app.route(\"/\", hookRoutes(config.eventBus));\n\n return app;\n}\n","/**\n * CORS middleware for dashboard dev.\n */\n\nimport { cors } from \"hono/cors\";\nimport type { CORSConfig } from \"../config.js\";\n\n/**\n * Build the Hono cors middleware for this server.\n *\n * Defaults are permissive (`origin: \"*\"`) for local development; callers\n * should pin origin/headers/credentials for production via `ServerConfig.cors`.\n */\nexport function corsMiddleware(config?: CORSConfig) {\n return cors({\n origin: config?.origin ?? \"*\",\n allowMethods: config?.allowMethods ?? [\"GET\", \"POST\", \"OPTIONS\"],\n allowHeaders: config?.allowHeaders ?? [\"Content-Type\"],\n ...(config?.maxAge !== undefined ? { maxAge: config.maxAge } : {}),\n ...(config?.credentials !== undefined ? { credentials: config.credentials } : {}),\n ...(config?.exposeHeaders !== undefined ? { exposeHeaders: config.exposeHeaders } : {}),\n });\n}\n","/**\n * Global error handler.\n */\n\nimport type { ErrorHandler } from \"hono\";\n\nexport const errorHandler: ErrorHandler = (err, c) => {\n console.error(\"Server error:\", err);\n return c.json({ error: err.message || \"Internal server error\" }, 500);\n};\n","/**\n * Admin routes — dashboard stats, tool analytics, token usage, live event stream.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"../config.js\";\n\nexport function adminRoutes(config: ServerConfig): Hono {\n const app = new Hono();\n\n app.get(\"/admin/dashboard\", async (c) => {\n const stats = await config.adminService.getDashboardStats();\n return c.json(stats);\n });\n\n app.get(\"/admin/agents\", async (c) => {\n const agents = await config.adminService.getAllAgentStats();\n return c.json(agents);\n });\n\n app.get(\"/admin/tools\", async (c) => {\n const tools = await config.adminService.getToolAnalytics();\n return c.json(tools);\n });\n\n app.get(\"/admin/tokens\", async (c) => {\n const groupBy = (c.req.query(\"group_by\") as \"agent\" | \"model\") ?? \"agent\";\n const usage = await config.adminService.getTokenUsage({ groupBy });\n return c.json(usage);\n });\n\n app.get(\"/admin/events/stream\", (c) => {\n const stream = config.sseExporter.connect();\n\n c.req.raw.signal.addEventListener(\"abort\", () => {\n config.sseExporter.disconnect(stream);\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n });\n\n return app;\n}\n","/**\n * Agent listing routes.\n */\n\nimport { Hono } from \"hono\";\nimport type { AgentRegistration } from \"../config.js\";\n\nexport function agentRoutes(agents: AgentRegistration[]): Hono {\n const app = new Hono();\n\n app.get(\"/agents\", (c) => {\n const summaries = agents.map((a) => ({\n id: a.id,\n name: a.name,\n description: a.description ?? \"\",\n }));\n return c.json(summaries);\n });\n\n return app;\n}\n","/**\n * Conversation routes — create conversations and stream messages via SSE.\n */\n\nimport type { AgentEventBus } from \"@agentic-patterns/runtime\";\nimport { Conversation, createToolboxExecutor } from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { AgentRegistration } from \"../config.js\";\nimport { agentEventToSSE } from \"../sse.js\";\n\n/** Entry in the per-server conversation registry. */\nexport interface ConversationEntry {\n conversation: Conversation;\n agentId: string;\n}\n\nexport function conversationRoutes(\n agents: AgentRegistration[],\n conversations: Map<string, ConversationEntry>,\n eventBus: AgentEventBus,\n): Hono {\n const app = new Hono();\n\n // POST /conversations — create a new conversation\n app.post(\"/conversations\", async (c) => {\n const body = await c.req.json<{ agent_id: string }>();\n const agentId = body.agent_id;\n\n const reg = agents.find((a) => a.id === agentId);\n if (!reg) {\n return c.json({ error: \"Agent not found\" }, 404);\n }\n\n // Wire a ToolExecutor so AgentRunner can actually execute tool calls\n // from the agent's Capability toolboxes (not just format them for the LLM).\n const toolExecutor = createToolboxExecutor(\n reg.agent as unknown as Parameters<typeof createToolboxExecutor>[0],\n );\n const conversation = new Conversation(reg.agent, reg.runner, { toolExecutor });\n conversations.set(conversation.id, { conversation, agentId });\n\n return c.json({ id: conversation.id, agent_id: agentId }, 201);\n });\n\n // POST /conversations/:id/messages — send message, stream SSE response\n app.post(\"/conversations/:id/messages\", async (c) => {\n const convId = c.req.param(\"id\");\n const entry = conversations.get(convId);\n\n if (!entry) {\n return c.json({ error: \"Conversation not found\" }, 404);\n }\n\n const body = await c.req.json<{ content: string }>();\n const content = body.content;\n\n if (!content || typeof content !== \"string\") {\n return c.json({ error: \"content is required\" }, 400);\n }\n\n const { conversation } = entry;\n\n if (!conversation.runner.stream) {\n return c.json({ error: \"Streaming not supported by this runner\" }, 501);\n }\n\n // SSE streaming response. We pass the server's shared eventBus so\n // emitted events reach every attached exporter (collector, SSE\n // broadcast, etc.) in addition to flowing through the generator for\n // this client stream.\n return streamSSE(c, async (stream) => {\n for await (const event of conversation.stream(content, { eventBus })) {\n const msg = agentEventToSSE(event);\n if (msg) {\n await stream.writeSSE(msg);\n }\n }\n\n await stream.writeSSE({ event: \"done\", data: \"{}\" });\n });\n });\n\n return app;\n}\n","/**\n * SSE formatting for Hono streaming.\n *\n * Converts AgentEvents to `{ event, data }` objects compatible with Hono's\n * streamSSE writeSSE() method.\n *\n * Delegates wire-name and payload mapping to the runtime's canonical\n * `toSSEMapping` so the server stays in sync with the 20-event vocabulary\n * defined in the spec. Only internal observability events (iteration.* and\n * llm.*) are filtered here — they remain available over the admin SSE\n * stream (SSEExporter) for operators.\n */\n\nimport type { AgentEvent, AgentEventType } from \"@agentic-patterns/runtime\";\nimport { toSSEMapping } from \"@agentic-patterns/runtime\";\n\n/** SSE message shape for Hono's writeSSE(). */\nexport interface SSEMessage {\n event: string;\n data: string;\n}\n\n/**\n * Internal observability events not surfaced to end clients. They remain\n * available over the admin SSE stream for operators.\n */\nconst INTERNAL_EVENT_TYPES: ReadonlySet<AgentEventType> = new Set<AgentEventType>([\n \"agent.iteration.start\",\n \"agent.iteration.end\",\n \"agent.llm.start\",\n \"agent.llm.end\",\n]);\n\n/**\n * Convert an AgentEvent to an SSE message for Hono streaming.\n *\n * Returns `null` for events that are not part of the client-facing\n * protocol (internal observability events, or events with no SSE mapping).\n */\nexport function agentEventToSSE(event: AgentEvent): SSEMessage | null {\n if (INTERNAL_EVENT_TYPES.has(event.type)) return null;\n const mapping = toSSEMapping(event);\n if (!mapping) return null;\n return { event: mapping.name, data: JSON.stringify(mapping.payload) };\n}\n","/**\n * Health check route.\n */\n\nimport { Hono } from \"hono\";\n\nexport function healthRoutes(): Hono {\n const app = new Hono();\n app.get(\"/health\", (c) => c.json({ status: \"ok\" }));\n return app;\n}\n","/**\n * Claude Code hook bridge — receive hook callbacks from the Claude Code\n * CLI and republish them on the AgentEventBus.\n *\n * The Claude Code CLI is configured (via `.claude/settings.json`) to POST\n * each hook callback as JSON to `/hooks/:eventType`. We validate the\n * event name against the known hook list, normalize the payload into a\n * `ClaudeCodeHookEvent`, publish it to the bus, then publish any derived\n * canonical events (PreToolUse → agent.tool.start, etc.).\n */\n\nimport {\n type AgentEventBus,\n type ClaudeCodeHookEvent,\n isClaudeCodeHookName,\n mapClaudeCodeHookToAgentEvents,\n} from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\n\nfunction newSpanId(): string {\n if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n return (globalThis as unknown as { crypto: { randomUUID(): string } }).crypto.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function hookRoutes(eventBus: AgentEventBus): Hono {\n const app = new Hono();\n\n app.post(\"/hooks/:eventType\", async (c) => {\n const eventType = c.req.param(\"eventType\");\n if (!isClaudeCodeHookName(eventType)) {\n return c.json({ error: `unknown hook event: ${eventType}` }, 400);\n }\n\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const sessionId = typeof body.session_id === \"string\" ? body.session_id : \"unknown\";\n\n // Runner correlation: when a ClaudeCodeRunner spawned this CC session it\n // tags every hook POST with `x-ap-runner-correlation-id`. We preserve the\n // raw hook (PreCompact, PermissionRequest, etc. give value the runner\n // doesn't emit) but SKIP deriving `agent.tool.start`/`agent.tool.end`\n // events to avoid double-counting alongside the runner's own tool events.\n const runnerCorrelationId =\n c.req.header(\"x-ap-runner-correlation-id\") ?? undefined;\n\n const hookEvent: ClaudeCodeHookEvent = {\n type: \"claude_code.hook\",\n traceId: sessionId,\n runId: sessionId,\n spanId: newSpanId(),\n timestamp: new Date(),\n hookName: eventType,\n sessionId,\n transcriptPath:\n typeof body.transcript_path === \"string\" ? body.transcript_path : undefined,\n cwd: typeof body.cwd === \"string\" ? body.cwd : undefined,\n permissionMode:\n typeof body.permission_mode === \"string\" ? body.permission_mode : undefined,\n toolName: typeof body.tool_name === \"string\" ? body.tool_name : undefined,\n toolInput: body.tool_input,\n toolResponse: body.tool_response,\n toolUseId: typeof body.tool_use_id === \"string\" ? body.tool_use_id : undefined,\n payload: body,\n ...(runnerCorrelationId ? { runnerCorrelationId } : {}),\n };\n\n await eventBus.publish(hookEvent);\n\n if (!runnerCorrelationId) {\n const derived = mapClaudeCodeHookToAgentEvents(hookEvent);\n for (const e of derived) {\n await eventBus.publish(e);\n }\n }\n\n return c.json({ ok: true });\n });\n\n return app;\n}\n"],"mappings":"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","names":["Hono","Hono","Hono","Hono","Hono","Hono","Hono"]}
|
|
1
|
+
{"version":3,"sources":["../src/app.ts","../src/middleware/cors.ts","../src/middleware/error-handler.ts","../src/routes/admin.ts","../src/routes/agents.ts","../src/routes/conversations.ts","../src/sse.ts","../src/routes/health.ts","../src/routes/hooks.ts"],"sourcesContent":["/**\n * Hono application factory.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"./config.js\";\nimport { corsMiddleware } from \"./middleware/cors.js\";\nimport { errorHandler } from \"./middleware/error-handler.js\";\nimport { adminRoutes } from \"./routes/admin.js\";\nimport { agentRoutes } from \"./routes/agents.js\";\nimport { type ConversationEntry, conversationRoutes } from \"./routes/conversations.js\";\nimport { healthRoutes } from \"./routes/health.js\";\nimport { hookRoutes } from \"./routes/hooks.js\";\n\n/**\n * Create a configured Hono app with all routes.\n *\n * Each call creates a fresh conversation registry, so multiple\n * servers in the same process do not share conversation state.\n */\nexport function createServer(config: ServerConfig): Hono {\n const app = new Hono();\n const conversations = new Map<string, ConversationEntry>();\n\n // Middleware\n app.use(\"*\", corsMiddleware(config.cors));\n app.onError(errorHandler);\n\n // Routes\n app.route(\"/\", healthRoutes());\n app.route(\"/\", agentRoutes(config.agents));\n app.route(\"/\", conversationRoutes(config.agents, conversations, config.eventBus));\n app.route(\"/\", adminRoutes(config));\n app.route(\"/\", hookRoutes(config.eventBus));\n\n return app;\n}\n","/**\n * CORS middleware for dashboard dev.\n */\n\nimport { cors } from \"hono/cors\";\nimport type { CORSConfig } from \"../config.js\";\n\n/**\n * Build the Hono cors middleware for this server.\n *\n * Defaults are permissive (`origin: \"*\"`) for local development; callers\n * should pin origin/headers/credentials for production via `ServerConfig.cors`.\n */\nexport function corsMiddleware(config?: CORSConfig) {\n return cors({\n origin: config?.origin ?? \"*\",\n allowMethods: config?.allowMethods ?? [\"GET\", \"POST\", \"OPTIONS\"],\n allowHeaders: config?.allowHeaders ?? [\"Content-Type\"],\n ...(config?.maxAge !== undefined ? { maxAge: config.maxAge } : {}),\n ...(config?.credentials !== undefined ? { credentials: config.credentials } : {}),\n ...(config?.exposeHeaders !== undefined ? { exposeHeaders: config.exposeHeaders } : {}),\n });\n}\n","/**\n * Global error handler.\n */\n\nimport type { ErrorHandler } from \"hono\";\n\nexport const errorHandler: ErrorHandler = (err, c) => {\n console.error(\"Server error:\", err);\n return c.json({ error: err.message || \"Internal server error\" }, 500);\n};\n","/**\n * Admin routes — dashboard stats, tool analytics, token usage, live event stream.\n */\n\nimport { Hono } from \"hono\";\nimport type { ServerConfig } from \"../config.js\";\n\nexport function adminRoutes(config: ServerConfig): Hono {\n const app = new Hono();\n\n app.get(\"/admin/dashboard\", async (c) => {\n const stats = await config.adminService.getDashboardStats();\n return c.json(stats);\n });\n\n app.get(\"/admin/agents\", async (c) => {\n const agents = await config.adminService.getAllAgentStats();\n return c.json(agents);\n });\n\n app.get(\"/admin/tools\", async (c) => {\n const tools = await config.adminService.getToolAnalytics();\n return c.json(tools);\n });\n\n app.get(\"/admin/tokens\", async (c) => {\n const groupBy = (c.req.query(\"group_by\") as \"agent\" | \"model\") ?? \"agent\";\n const usage = await config.adminService.getTokenUsage({ groupBy });\n return c.json(usage);\n });\n\n app.get(\"/admin/events/stream\", (c) => {\n const stream = config.sseExporter.connect();\n\n c.req.raw.signal.addEventListener(\"abort\", () => {\n config.sseExporter.disconnect(stream);\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n });\n\n return app;\n}\n","/**\n * Agent listing routes.\n */\n\nimport { Hono } from \"hono\";\nimport type { AgentRegistration } from \"../config.js\";\n\nexport function agentRoutes(agents: AgentRegistration[]): Hono {\n const app = new Hono();\n\n app.get(\"/agents\", (c) => {\n const summaries = agents.map((a) => ({\n id: a.id,\n name: a.name,\n description: a.description ?? \"\",\n }));\n return c.json(summaries);\n });\n\n return app;\n}\n","/**\n * Conversation routes — create conversations and stream messages via SSE.\n */\n\nimport type { AgentEventBus } from \"@agentic-patterns/runtime\";\nimport { Conversation, createToolboxExecutor } from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { AgentRegistration } from \"../config.js\";\nimport { agentEventToSSE } from \"../sse.js\";\n\n/** Entry in the per-server conversation registry. */\nexport interface ConversationEntry {\n conversation: Conversation;\n agentId: string;\n}\n\nexport function conversationRoutes(\n agents: AgentRegistration[],\n conversations: Map<string, ConversationEntry>,\n eventBus: AgentEventBus,\n): Hono {\n const app = new Hono();\n\n // POST /conversations — create a new conversation\n app.post(\"/conversations\", async (c) => {\n const body = await c.req.json<{ agent_id: string }>();\n const agentId = body.agent_id;\n\n const reg = agents.find((a) => a.id === agentId);\n if (!reg) {\n return c.json({ error: \"Agent not found\" }, 404);\n }\n\n // Wire a ToolExecutor so AgentRunner can actually execute tool calls\n // from the agent's Capability toolboxes (not just format them for the LLM).\n const toolExecutor = createToolboxExecutor(\n reg.agent as unknown as Parameters<typeof createToolboxExecutor>[0],\n );\n const conversation = new Conversation(reg.agent, reg.runner, { toolExecutor });\n conversations.set(conversation.id, { conversation, agentId });\n\n return c.json({ id: conversation.id, agent_id: agentId }, 201);\n });\n\n // POST /conversations/:id/messages — send message, stream SSE response\n app.post(\"/conversations/:id/messages\", async (c) => {\n const convId = c.req.param(\"id\");\n const entry = conversations.get(convId);\n\n if (!entry) {\n return c.json({ error: \"Conversation not found\" }, 404);\n }\n\n const body = await c.req.json<{ content: string }>();\n const content = body.content;\n\n if (!content || typeof content !== \"string\") {\n return c.json({ error: \"content is required\" }, 400);\n }\n\n const { conversation } = entry;\n\n if (!conversation.runner.stream) {\n return c.json({ error: \"Streaming not supported by this runner\" }, 501);\n }\n\n // SSE streaming response. We pass the server's shared eventBus so\n // emitted events reach every attached exporter (collector, SSE\n // broadcast, etc.) in addition to flowing through the generator for\n // this client stream.\n return streamSSE(c, async (stream) => {\n for await (const event of conversation.stream(content, { eventBus })) {\n const msg = agentEventToSSE(event);\n if (msg) {\n await stream.writeSSE(msg);\n }\n }\n\n await stream.writeSSE({ event: \"done\", data: \"{}\" });\n });\n });\n\n return app;\n}\n","/**\n * SSE formatting for Hono streaming.\n *\n * Converts AgentEvents to `{ event, data }` objects compatible with Hono's\n * streamSSE writeSSE() method.\n *\n * Delegates wire-name and payload mapping to the runtime's canonical\n * `toSSEMapping` so the server stays in sync with the 20-event vocabulary\n * defined in the spec. Only internal observability events (iteration.* and\n * llm.*) are filtered here — they remain available over the admin SSE\n * stream (SSEExporter) for operators.\n */\n\nimport type { AgentEvent, AgentEventType } from \"@agentic-patterns/runtime\";\nimport { toSSEMapping } from \"@agentic-patterns/runtime\";\n\n/** SSE message shape for Hono's writeSSE(). */\nexport interface SSEMessage {\n event: string;\n data: string;\n}\n\n/**\n * Internal observability events not surfaced to end clients. They remain\n * available over the admin SSE stream for operators.\n */\nconst INTERNAL_EVENT_TYPES: ReadonlySet<AgentEventType> = new Set<AgentEventType>([\n \"agent.iteration.start\",\n \"agent.iteration.end\",\n \"agent.llm.start\",\n \"agent.llm.end\",\n]);\n\n/**\n * Convert an AgentEvent to an SSE message for Hono streaming.\n *\n * Returns `null` for events that are not part of the client-facing\n * protocol (internal observability events, or events with no SSE mapping).\n */\nexport function agentEventToSSE(event: AgentEvent): SSEMessage | null {\n if (INTERNAL_EVENT_TYPES.has(event.type)) return null;\n const mapping = toSSEMapping(event);\n if (!mapping) return null;\n return { event: mapping.name, data: JSON.stringify(mapping.payload) };\n}\n","/**\n * Health check route.\n */\n\nimport { Hono } from \"hono\";\n\nexport function healthRoutes(): Hono {\n const app = new Hono();\n app.get(\"/health\", (c) => c.json({ status: \"ok\" }));\n return app;\n}\n","/**\n * Claude Code hook bridge — receive hook callbacks from the Claude Code\n * CLI and republish them on the AgentEventBus.\n *\n * The Claude Code CLI is configured (via `.claude/settings.json`) to POST\n * each hook callback as JSON to `/hooks/:eventType`. We validate the\n * event name against the known hook list, normalize the payload into a\n * `ClaudeCodeHookEvent`, publish it to the bus, then publish any derived\n * canonical events (PreToolUse → agent.tool.start, etc.).\n */\n\nimport {\n type AgentEventBus,\n type ClaudeCodeHookEvent,\n isClaudeCodeHookName,\n mapClaudeCodeHookToAgentEvents,\n} from \"@agentic-patterns/runtime\";\nimport { Hono } from \"hono\";\n\nfunction newSpanId(): string {\n if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n return (globalThis as unknown as { crypto: { randomUUID(): string } }).crypto.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function hookRoutes(eventBus: AgentEventBus): Hono {\n const app = new Hono();\n\n app.post(\"/hooks/:eventType\", async (c) => {\n const eventType = c.req.param(\"eventType\");\n if (!isClaudeCodeHookName(eventType)) {\n return c.json({ error: `unknown hook event: ${eventType}` }, 400);\n }\n\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n const sessionId = typeof body.session_id === \"string\" ? body.session_id : \"unknown\";\n\n // Runner correlation: when a ClaudeCodeRunner spawned this CC session it\n // tags every hook POST with `x-ap-runner-correlation-id`. We preserve the\n // raw hook (PreCompact, PermissionRequest, etc. give value the runner\n // doesn't emit) but SKIP deriving `agent.tool.start`/`agent.tool.end`\n // events to avoid double-counting alongside the runner's own tool events.\n const runnerCorrelationId = c.req.header(\"x-ap-runner-correlation-id\") ?? undefined;\n\n const hookEvent: ClaudeCodeHookEvent = {\n type: \"claude_code.hook\",\n traceId: sessionId,\n runId: sessionId,\n spanId: newSpanId(),\n timestamp: new Date(),\n hookName: eventType,\n sessionId,\n transcriptPath: typeof body.transcript_path === \"string\" ? body.transcript_path : undefined,\n cwd: typeof body.cwd === \"string\" ? body.cwd : undefined,\n permissionMode: typeof body.permission_mode === \"string\" ? body.permission_mode : undefined,\n toolName: typeof body.tool_name === \"string\" ? body.tool_name : undefined,\n toolInput: body.tool_input,\n toolResponse: body.tool_response,\n toolUseId: typeof body.tool_use_id === \"string\" ? body.tool_use_id : undefined,\n payload: body,\n ...(runnerCorrelationId ? { runnerCorrelationId } : {}),\n };\n\n await eventBus.publish(hookEvent);\n\n if (!runnerCorrelationId) {\n const derived = mapClaudeCodeHookToAgentEvents(hookEvent);\n for (const e of derived) {\n await eventBus.publish(e);\n }\n }\n\n return c.json({ ok: true });\n });\n\n return app;\n}\n"],"mappings":"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","names":["Hono","Hono","Hono","Hono","Hono","Hono","Hono"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentic-patterns/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Hono HTTP server for agentic-patterns agents — routes, SSE streaming, admin API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"dev": "tsx --watch examples/live-demo.ts"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@agentic-patterns/core": "0.1.
|
|
56
|
-
"@agentic-patterns/runtime": "0.1.
|
|
55
|
+
"@agentic-patterns/core": "0.1.4",
|
|
56
|
+
"@agentic-patterns/runtime": "0.1.4",
|
|
57
57
|
"hono": "^4.0.0",
|
|
58
58
|
"zod": "^3.23.0"
|
|
59
59
|
},
|