@axlsdk/studio 0.15.0 → 0.16.1
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 +6 -5
- package/dist/{chunk-IPDMFFTQ.js → chunk-RE6VPUXA.js} +274 -203
- package/dist/chunk-RE6VPUXA.js.map +1 -0
- package/dist/cli.cjs +281 -210
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/assets/index-BzQe3w-R.js +313 -0
- package/dist/client/assets/index-C2nTRFWX.css +1 -0
- package/dist/client/index.html +20 -2
- package/dist/{connection-manager-BMPahDuY.d.cts → connection-manager-DAuqk9lM.d.cts} +24 -1
- package/dist/{connection-manager-BMPahDuY.d.ts → connection-manager-DAuqk9lM.d.ts} +24 -1
- package/dist/middleware.cjs +283 -211
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.cts +32 -9
- package/dist/middleware.d.ts +32 -9
- package/dist/middleware.js +3 -2
- package/dist/middleware.js.map +1 -1
- package/dist/server/index.cjs +281 -210
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +12 -6
- package/dist/server/index.d.ts +12 -6
- package/dist/server/index.js +1 -1
- package/package.json +7 -7
- package/dist/chunk-IPDMFFTQ.js.map +0 -1
- package/dist/client/assets/index-CLKKOaE2.css +0 -1
- package/dist/client/assets/index-rvds50cZ.js +0 -278
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/index.ts","../src/server/redact.ts","../src/server/middleware/error-handler.ts","../src/server/ws/connection-manager.ts","../src/server/ws/protocol.ts","../src/server/ws/handler.ts","../src/server/aggregates/aggregate-snapshots.ts","../src/server/aggregates/trace-aggregator.ts","../src/server/aggregates/execution-aggregator.ts","../src/server/aggregates/eval-aggregator.ts","../src/server/aggregates/reducers.ts","../src/server/routes/health.ts","../src/server/routes/workflows.ts","../src/server/routes/executions.ts","../src/server/routes/sessions.ts","../src/server/routes/agents.ts","../src/server/routes/tools.ts","../src/server/routes/memory.ts","../src/server/routes/decisions.ts","../src/server/routes/costs.ts","../src/server/routes/evals.ts","../src/server/routes/playground.ts","../src/server/routes/eval-trends.ts","../src/server/routes/workflow-stats.ts","../src/server/routes/trace-stats.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport type { AxlRuntime, AxlEvent } from '@axlsdk/axl';\nimport { redactStreamEvent } from './redact.js';\nimport type { StudioEnv } from './types.js';\nimport { errorHandler } from './middleware/error-handler.js';\nimport { ConnectionManager } from './ws/connection-manager.js';\nimport type { BufferCaps } from './ws/connection-manager.js';\nimport { createWsHandlers } from './ws/handler.js';\nimport { TraceAggregator } from './aggregates/trace-aggregator.js';\nimport { ExecutionAggregator } from './aggregates/execution-aggregator.js';\nimport { EvalAggregator } from './aggregates/eval-aggregator.js';\nimport {\n reduceCost,\n emptyCostData,\n reduceWorkflowStats,\n emptyWorkflowStatsData,\n enrichWorkflowStats,\n reduceTraceStats,\n emptyTraceStatsData,\n reduceEvalTrends,\n emptyEvalTrendData,\n} from './aggregates/reducers.js';\nimport type { WindowId } from './aggregates/aggregate-snapshots.js';\nimport { createHealthRoutes } from './routes/health.js';\nimport { createWorkflowRoutes } from './routes/workflows.js';\nimport executionRoutes from './routes/executions.js';\nimport { createSessionRoutes } from './routes/sessions.js';\nimport agentRoutes from './routes/agents.js';\nimport toolRoutes from './routes/tools.js';\nimport memoryRoutes from './routes/memory.js';\nimport decisionRoutes from './routes/decisions.js';\nimport { createCostRoutes } from './routes/costs.js';\nimport { createEvalRoutes } from './routes/evals.js';\nimport { createPlaygroundRoutes } from './routes/playground.js';\nimport { createEvalTrendsRoutes } from './routes/eval-trends.js';\nimport { createWorkflowStatsRoutes } from './routes/workflow-stats.js';\nimport { createTraceStatsRoutes } from './routes/trace-stats.js';\n\nexport type { StudioEnv } from './types.js';\nexport { ConnectionManager } from './ws/connection-manager.js';\nexport type { BroadcastTarget, BufferCaps } from './ws/connection-manager.js';\nexport { TraceAggregator } from './aggregates/trace-aggregator.js';\nexport { ExecutionAggregator } from './aggregates/execution-aggregator.js';\nexport { EvalAggregator } from './aggregates/eval-aggregator.js';\nexport type { WindowId, AggregateBroadcast } from './aggregates/aggregate-snapshots.js';\n\nexport type CreateServerOptions = {\n runtime: AxlRuntime;\n /** Root path for serving pre-built SPA static assets. */\n staticRoot?: string;\n /** Base URL path for client-side routing and API calls. Injected into index.html at serve time. */\n basePath?: string;\n /** When true, disable all mutating API endpoints. */\n readOnly?: boolean;\n /** Apply CORS headers. Default: true (standalone CLI). Set false for embedded middleware. */\n cors?: boolean;\n /** Lazy eval file loader. Called before eval routes access the runtime's registered evals. */\n evalLoader?: () => Promise<void>;\n /**\n * Override the default WS replay-buffer resource caps. All fields are\n * optional; omitted fields keep their documented defaults\n * (1000 events / 4 MiB per buffer, 256 concurrent buffers).\n */\n bufferCaps?: BufferCaps;\n};\n\nexport function createServer(options: CreateServerOptions) {\n const { runtime, staticRoot, basePath = '', readOnly = false } = options;\n const app = new Hono<StudioEnv>();\n const connMgr = new ConnectionManager(options.bufferCaps);\n const windows: WindowId[] = ['24h', '7d', '30d', 'all'];\n\n const costAggregator = new TraceAggregator({\n runtime,\n connMgr,\n channel: 'costs',\n reducer: reduceCost,\n emptyState: emptyCostData,\n windows,\n });\n\n const workflowStatsAggregator = new ExecutionAggregator({\n runtime,\n connMgr,\n channel: 'workflow-stats',\n reducer: reduceWorkflowStats,\n emptyState: emptyWorkflowStatsData,\n windows,\n broadcastTransform: enrichWorkflowStats,\n });\n\n const traceStatsAggregator = new TraceAggregator({\n runtime,\n connMgr,\n channel: 'trace-stats',\n reducer: reduceTraceStats,\n emptyState: emptyTraceStatsData,\n windows,\n });\n\n const evalTrendsAggregator = new EvalAggregator({\n runtime,\n connMgr,\n channel: 'eval-trends',\n reducer: reduceEvalTrends,\n emptyState: emptyEvalTrendData,\n windows,\n });\n\n // ── Middleware ──────────────────────────────────────────────────────\n if (options.cors !== false) {\n app.use('*', cors());\n }\n app.use('*', errorHandler);\n app.use('*', async (c, next) => {\n c.set('runtime', runtime);\n await next();\n });\n\n // ── Read-only mode ──────────────────────────────────────────────────\n if (readOnly) {\n // Patterns must be precise: POST /api/evals/compare is pure computation\n // and must remain allowed, but POST /api/evals/:name/run mutates history.\n const blocked: RegExp[] = [\n /^POST \\/api\\/workflows(\\/|$)/,\n /^POST \\/api\\/executions(\\/|$)/,\n /^POST \\/api\\/sessions(\\/|$)/,\n /^DELETE \\/api\\/sessions(\\/|$)/,\n /^PUT \\/api\\/memory(\\/|$)/,\n /^DELETE \\/api\\/memory(\\/|$)/,\n /^POST \\/api\\/decisions(\\/|$)/,\n /^POST \\/api\\/tools(\\/|$)/,\n /^POST \\/api\\/evals\\/import$/,\n /^POST \\/api\\/evals\\/[^/]+\\/run$/,\n /^POST \\/api\\/evals\\/[^/]+\\/rescore$/,\n /^POST \\/api\\/evals\\/runs\\/[^/]+\\/cancel$/,\n /^DELETE \\/api\\/evals\\/history\\/[^/]+$/,\n /^POST \\/api\\/playground(\\/|$)/,\n ];\n app.use('/api/*', async (c, next) => {\n // c.req.path returns the full path including any parent route prefix\n // (e.g., /studio/api/workflows when mounted via app.route('/studio', ...)).\n // Extract just the /api/... portion for matching.\n const apiIdx = c.req.path.indexOf('/api/');\n const apiPath = apiIdx >= 0 ? c.req.path.slice(apiIdx) : c.req.path;\n const key = `${c.req.method} ${apiPath}`;\n if (blocked.some((re) => re.test(key))) {\n return c.json(\n {\n ok: false,\n error: { code: 'READ_ONLY', message: 'Studio is mounted in read-only mode' },\n },\n 405,\n );\n }\n await next();\n });\n }\n\n // ── API Routes ─────────────────────────────────────────────────────\n const api = new Hono<StudioEnv>();\n api.route('/', createHealthRoutes(readOnly));\n api.route('/', createWorkflowRoutes(connMgr));\n api.route('/', executionRoutes);\n api.route('/', createSessionRoutes(connMgr));\n api.route('/', agentRoutes);\n api.route('/', toolRoutes);\n api.route('/', memoryRoutes);\n api.route('/', decisionRoutes);\n api.route('/', createCostRoutes(costAggregator));\n api.route('/', createEvalTrendsRoutes(evalTrendsAggregator));\n api.route('/', createWorkflowStatsRoutes(workflowStatsAggregator));\n api.route('/', createTraceStatsRoutes(traceStatsAggregator));\n const { app: evalApp, closeActiveRuns } = createEvalRoutes(connMgr, options.evalLoader);\n api.route('/', evalApp);\n api.route('/', createPlaygroundRoutes(connMgr));\n\n app.route('/api', api);\n\n // ── Trace event bridging ───────────────────────────────────────────\n // Aggregators subscribe to runtime events directly via their start() method.\n // This listener handles trace channel broadcasting and decision events only.\n // `isRedactEnabled()` is read per-event so a runtime that flips the flag\n // at runtime (not the common path, but possible) reflects immediately.\n const traceListener = (event: unknown) => {\n // Wrap the whole body in try/catch so a throw in `redactStreamEvent`\n // (malformed event shape) or `broadcastWithWildcard` (serialization\n // error) doesn't propagate back through `EventEmitter.emit('trace')`\n // and starve downstream listeners. Fail-loud to console.error so ops\n // sees it in logs but the runtime keeps going.\n try {\n const traceEvent = event as AxlEvent;\n\n // Broadcast to trace channels — apply the same scrubbing as the\n // playground/workflow execution paths so the trace firehose doesn't\n // leak content the per-route broadcasts are scrubbing.\n const redacted = redactStreamEvent(traceEvent, runtime.isRedactEnabled());\n if (traceEvent.executionId) {\n connMgr.broadcastWithWildcard(`trace:${traceEvent.executionId}`, redacted);\n }\n\n // Broadcast pending decisions. `await_human` is now a first-class\n // AxlEvent type (was a `log` variant before 0.16). Send the redacted\n // shape — `prompt` is user-visible LLM content that respects redact.\n if (traceEvent.type === 'await_human') {\n connMgr.broadcast('decisions', redacted);\n }\n } catch (err) {\n console.error(\n '[axl-studio] trace listener threw; event dropped:',\n err instanceof Error ? err.message : String(err),\n );\n }\n };\n runtime.on('trace', traceListener);\n\n // ── Start aggregators (rebuild from history + subscribe to live events) ──\n const aggregatorStartPromise = Promise.all([\n costAggregator.start(),\n workflowStatsAggregator.start(),\n traceStatsAggregator.start(),\n evalTrendsAggregator.start(),\n ]).catch((err) => console.error('[axl-studio] aggregator start failed:', err));\n\n // ── Static SPA serving (production) ────────────────────────────────\n if (staticRoot) {\n // Read index.html once at startup. When basePath is set, inject the <base>\n // tag and runtime config so asset paths and client-side routing work\n // regardless of whether the mount URL has a trailing slash.\n const indexPath = resolve(staticRoot, 'index.html');\n let spaHtml: string | undefined;\n\n if (!existsSync(indexPath)) {\n console.warn(`[axl-studio] index.html not found at ${indexPath}`);\n } else {\n const rawHtml = readFileSync(indexPath, 'utf-8');\n\n if (basePath) {\n // Escape '<' to prevent </script> in basePath from breaking out of\n // the script tag. JSON.stringify alone is insufficient because the\n // HTML parser processes </script> before JavaScript runs.\n const safeBasePath = JSON.stringify(basePath).replace(/</g, '\\\\u003c');\n const injected = rawHtml.replace(\n '<head>',\n `<head>\\n<base href=\"${basePath}/\">\\n` +\n `<script>window.__AXL_STUDIO_BASE__=${safeBasePath}</script>`,\n );\n\n if (injected === rawHtml) {\n console.warn(\n '[axl-studio] Could not inject basePath into index.html — ' +\n '<head> tag not found. The SPA may not route correctly.',\n );\n }\n spaHtml = injected;\n } else {\n spaHtml = rawHtml;\n }\n }\n\n // Serve static assets (JS, CSS, images). index.html is excluded so the\n // SPA fallback below always serves the version with basePath injection.\n // Without this guard, serveStatic would serve the raw index.html for root\n // requests (/ or /index.html), missing <base> and __AXL_STUDIO_BASE__.\n const staticHandler = serveStatic({\n root: staticRoot,\n rewriteRequestPath: basePath\n ? (path) => (path.startsWith(basePath) ? path.slice(basePath.length) || '/' : path)\n : undefined,\n });\n\n app.use('/*', async (c, next) => {\n const reqPath = c.req.path;\n const resolved =\n basePath && reqPath.startsWith(basePath) ? reqPath.slice(basePath.length) || '/' : reqPath;\n // Skip index.html (handled by SPA fallback) and /ws (handled by WebSocket upgrader)\n if (resolved === '/' || resolved === '/index.html' || resolved === '/ws') {\n return next();\n }\n return staticHandler(c, next);\n });\n\n // SPA fallback: serve the (possibly injected) index.html for all\n // non-API, non-static-asset routes so React Router handles routing.\n // Skip /ws so the WebSocket upgrader (registered after createServer) can handle it.\n if (spaHtml) {\n app.get('*', async (c, next) => {\n const resolved =\n basePath && c.req.path.startsWith(basePath)\n ? c.req.path.slice(basePath.length) || '/'\n : c.req.path;\n if (resolved === '/ws') return next();\n return c.html(spaHtml!);\n });\n }\n }\n\n return {\n app,\n connMgr,\n costAggregator,\n workflowStatsAggregator,\n traceStatsAggregator,\n evalTrendsAggregator,\n aggregatorStartPromise,\n /** Create WS handlers. Call before registering static/SPA routes are reached. */\n createWsHandlers: () => createWsHandlers(connMgr),\n traceListener,\n /** Abort all active streaming eval runs. */\n closeActiveRuns,\n /** Close all aggregators (clear intervals and unsubscribe listeners). */\n closeAggregators: () => {\n costAggregator.close();\n workflowStatsAggregator.close();\n traceStatsAggregator.close();\n evalTrendsAggregator.close();\n },\n };\n}\n","/**\n * Server-side redaction for observability responses.\n *\n * `config.trace.redact` was originally scoped to trace events emitted via\n * `emitTrace()` — it scrubs user/LLM content in prompts, responses, memory\n * values, tool args, etc. But data returned through Studio's REST surface\n * (execution results, memory values, session history) bypassed trace\n * emission entirely and leaked raw content even when trace redaction was\n * on. That inconsistency made \"compliance mode\" misleading: a user would\n * see `[redacted]` in the Trace Explorer timeline and then see raw user\n * data in the sibling Result pane, Memory Browser, or Session Manager.\n *\n * The right user mental model for this config is \"what can the observability\n * layer see?\". We keep the config name `trace.redact` but broaden its scope\n * at the REST read boundary to also scrub:\n *\n * - `ExecutionInfo.result` / `.error` (/api/executions, /api/executions/:id)\n * - Memory values (/api/memory/:scope, /api/memory/:scope/:key)\n * - Session message content + tool call arguments (/api/sessions/:id)\n *\n * Structural metadata (workflow names, agent names, tool names, keys, IDs,\n * timestamps, cost/token metrics) is preserved so the Trace Explorer,\n * Memory Browser, and Session Manager still render useful context when\n * compliance mode is on.\n *\n * Programmatic callers of `runtime.execute()` and direct StateStore access\n * still receive raw values — redaction is an *observability boundary* filter,\n * not a data-at-rest transform. If a user needs scrubbed state-at-rest they\n * configure their own StateStore to store scrubbed values.\n */\nimport type {\n ExecutionInfo,\n ChatMessage,\n PendingDecision,\n AxlEvent,\n EvalHistoryEntry,\n} from '@axlsdk/axl';\nimport { redactEvent } from '@axlsdk/axl';\nimport type { EvalResult, EvalItem, ScorerDetail } from '@axlsdk/eval';\n\n// Stream events on the wire are `AxlEvent` — the translation layer was\n// deleted in PR 1 commit 4. The legacy `StreamEvent` shapes are gone;\n// consumers narrow on the AxlEvent union.\n\nconst REDACTED = '[redacted]';\n\n/**\n * Error `name` values whose `message` is purely structural (codes, counts,\n * identifiers) and safe to surface verbatim under redact mode. Every other\n * error — `ValidationError`, `GuardrailError`, `VerifyError`, arbitrary\n * provider errors, `Error` from user code — is treated as potentially\n * echoing user/LLM content and has its message scrubbed.\n *\n * Kept in sync with the allow-list in\n * `server/middleware/error-handler.ts`; both sites must match so a route\n * that surfaces errors inline has identical redaction semantics to one\n * that throws through the global handler.\n */\nconst SAFE_ERROR_NAMES = new Set([\n 'QuorumNotMet',\n 'NoConsensus',\n 'TimeoutError',\n 'MaxTurnsError',\n 'BudgetExceededError',\n 'ToolDenied',\n]);\n\n/**\n * Scrub an error's `.message` for inclusion in a REST error envelope or WS\n * error event. Under redact mode, only messages from the structural\n * allow-list above pass through; everything else becomes `[redacted]`. The\n * `code`/`name` stay untouched so clients can still branch programmatically.\n *\n * Call sites that catch an error and build a `{ code, message }` envelope\n * locally (instead of re-throwing through `errorHandler`) should use this\n * helper so their redaction behavior stays consistent with the global path.\n */\nexport function redactErrorMessage(err: unknown, redact: boolean): string {\n const raw = err instanceof Error ? err.message : String(err);\n if (!redact) return raw;\n const name = err instanceof Error ? err.name : '';\n return SAFE_ERROR_NAMES.has(name) ? raw : REDACTED;\n}\n\n/**\n * Generic \"scrub any value to the redacted sentinel\" helper. Used by\n * routes that return a single opaque payload (workflow execute result,\n * tool test result, playground done data) where the value could be\n * anything — string, object, array, null, number — and we just want a\n * consistent scrubbed marker regardless of shape.\n */\nexport function redactValue(value: unknown, redact: boolean): unknown {\n if (!redact) return value;\n return REDACTED;\n}\n\n/**\n * Return a shallow-cloned ExecutionInfo with user-content fields scrubbed\n * when `redact` is true. Never mutates the input. When `redact` is false,\n * returns the input unchanged (reference equality preserved).\n *\n * Event scrubbing: every event in `events[]` is piped through\n * `redactStreamEvent` to catch per-variant payloads that emit-time\n * redaction may have missed (e.g., `partial_object.data.object`,\n * `verify.data.lastError`, `pipeline.reason`, terminal `done`/`error`,\n * `tool_call_start.data.args`, `tool_denied.data.*`). Defense in depth —\n * core `emitEvent` scrubs most variants at emission, but the REST\n * serialization boundary is the last line before PII leaves the\n * observability envelope.\n */\nexport function redactExecutionInfo(info: ExecutionInfo, redact: boolean): ExecutionInfo {\n if (!redact) return info;\n return {\n ...info,\n ...(info.result !== undefined ? { result: REDACTED } : {}),\n ...(info.error !== undefined ? { error: REDACTED } : {}),\n events: info.events.map((e) => redactStreamEvent(e, true)),\n };\n}\n\n/** List variant: maps each entry through the single-item redactor. */\nexport function redactExecutionList(infos: ExecutionInfo[], redact: boolean): ExecutionInfo[] {\n if (!redact) return infos;\n return infos.map((info) => redactExecutionInfo(info, redact));\n}\n\n/**\n * Scrub a memory value read through Studio's REST API. Memory values\n * don't flow through `emitTrace` (the memory_remember / memory_recall log\n * events deliberately exclude values — operation-only audit trail), so\n * this isn't closing a trace-to-REST inconsistency. It's broadening the\n * observability-boundary scope to cover memory browser reads.\n *\n * Keys are deliberately preserved so the Memory Browser stays navigable —\n * users with redact on can still see which keys exist and which ones\n * their code is writing to. Keys are programmer-chosen identifiers; if a\n * specific deployment has PII in keys it's a code-level problem and\n * should be fixed at the `ctx.remember()` call site.\n */\nexport function redactMemoryValue(value: unknown, redact: boolean): unknown {\n if (!redact) return value;\n return REDACTED;\n}\n\n/**\n * Memory list variant. Scrubs values on every `{ key, value }` entry;\n * preserves keys for navigation.\n */\nexport function redactMemoryList(\n entries: Array<{ key: string; value: unknown }>,\n redact: boolean,\n): Array<{ key: string; value: unknown }> {\n if (!redact) return entries;\n return entries.map((entry) => ({ key: entry.key, value: REDACTED }));\n}\n\n/**\n * Scrub a single ChatMessage for session history responses. Removes:\n * - `content` — user/LLM text\n * - `tool_calls[*].function.arguments` — tool inputs (JSON string)\n * - `providerMetadata` — opaque provider bag that\n * may contain encoded reasoning / thinking signatures / cache keys\n *\n * Preserves:\n * - `role` — system/user/assistant/tool\n * - `name` — tool/function name on\n * role='tool' messages (non-PII identifier)\n * - `tool_call_id` — join key for tool responses\n * - `tool_calls[*].id` — call ID\n * - `tool_calls[*].type` — always 'function'\n * - `tool_calls[*].function.name` — tool name (non-PII)\n *\n * The preserved fields are exactly the structural metadata you need to\n * understand the shape of a conversation (who said what, which tools\n * were called) without seeing any user/LLM content.\n */\nfunction redactChatMessage(msg: ChatMessage): ChatMessage {\n // We deliberately hand-build the output with an explicit allow-list\n // instead of spreading `msg`, so any new field added to `ChatMessage`\n // in the future (e.g. `refusal`, `reasoning_content`) is silently\n // dropped rather than passing through unscrubbed. The `satisfies`\n // assertion catches the case where a new REQUIRED field is added to\n // `ChatMessage` — typecheck will fail and force a code review on\n // whether the new field should be scrubbed or preserved.\n const scrubbed = {\n role: msg.role,\n content: REDACTED,\n ...(msg.name !== undefined ? { name: msg.name } : {}),\n ...(msg.tool_call_id !== undefined ? { tool_call_id: msg.tool_call_id } : {}),\n ...(msg.tool_calls !== undefined\n ? {\n tool_calls: msg.tool_calls.map((tc) => ({\n id: tc.id,\n type: tc.type,\n function: {\n name: tc.function.name,\n arguments: REDACTED,\n },\n })),\n }\n : {}),\n // providerMetadata deliberately omitted — opaque content.\n } satisfies ChatMessage;\n return scrubbed;\n}\n\n/**\n * Scrub a session history response. Maps every message through\n * `redactChatMessage`. HandoffRecord entries (on the same response) have\n * no content fields — just source/target/mode/timestamp/duration — so\n * they don't need scrubbing.\n */\nexport function redactSessionHistory(history: ChatMessage[], redact: boolean): ChatMessage[] {\n if (!redact) return history;\n return history.map(redactChatMessage);\n}\n\n// ── Stream events (WS broadcast) ─────────────────────────────────────\n\n/**\n * Scrub an `AxlEvent` before broadcasting it to Studio WS subscribers or\n * serializing it through a REST response.\n *\n * Per-variant scrub logic lives in core's `REDACTION_RULES` table\n * (`packages/axl/src/redaction.ts`). Both this WS-boundary scrubber and\n * core's emit-time scrubber consult the same rules, so adding a new\n * `AxlEvent` variant updates both layers in one place — no drift.\n *\n * The defense-in-depth value of this layer remains: when a runtime emits\n * events with `redact: false` (rare but possible — e.g. a multi-tenant\n * setup where the per-request decision is made later) and they land in\n * `ExecutionInfo.events` for a REST read with `redact: true`, this\n * second pass catches the missed scrub. Structural metadata\n * (`executionId`/`step`/`timestamp`/`askId`/`agent`/etc.) and numeric\n * observability fields (`cost`/`tokens`/`duration`) are preserved by\n * every rule.\n *\n * Programmatic callers of `runtime.execute()` and direct StateStore\n * reads still receive raw events — redaction is an observability-boundary\n * filter, not a data-at-rest transform.\n */\nexport function redactStreamEvent(event: AxlEvent, redact: boolean): AxlEvent {\n if (!redact) return event;\n return redactEvent(event);\n}\n\n// ── Eval results ─────────────────────────────────────────────────────\n\n/**\n * Scrub a single `EvalItem`. Per-item user/LLM content lives in:\n * input — the dataset item that drove the workflow\n * output — the workflow's return value\n * error — failure message (may echo user input)\n * annotations — user-supplied per-item labels/ground truth\n * scorerErrors — scorer-thrown error strings that can echo content\n * scoreDetails[*].metadata — especially LLM-scorer reasoning,\n * which mirrors agent_call response content\n *\n * Preserved fields (structural / metrics):\n * scores (numeric), duration, cost, scorerCost\n * scoreDetails[*].{score, duration, cost} (but not metadata)\n * metadata (execution metadata: models, tokens, agentCalls, workflows)\n * traces (trace events — already redacted at emission time)\n */\nfunction redactEvalItem(item: EvalItem): EvalItem {\n const scrubbed: EvalItem = {\n ...item,\n input: REDACTED,\n output: REDACTED,\n ...(item.annotations !== undefined ? { annotations: REDACTED } : {}),\n ...(item.error !== undefined ? { error: REDACTED } : {}),\n ...(item.scorerErrors !== undefined\n ? { scorerErrors: item.scorerErrors.map(() => REDACTED) }\n : {}),\n };\n if (item.scoreDetails) {\n const detailsOut: Record<string, ScorerDetail> = {};\n for (const [name, detail] of Object.entries(item.scoreDetails)) {\n detailsOut[name] = {\n score: detail.score,\n ...(detail.duration !== undefined ? { duration: detail.duration } : {}),\n ...(detail.cost !== undefined ? { cost: detail.cost } : {}),\n // metadata deliberately omitted — may contain LLM scorer reasoning\n };\n }\n scrubbed.scoreDetails = detailsOut;\n }\n return scrubbed;\n}\n\n/**\n * Scrub an `EvalResult` for an observability-boundary read. Items are\n * mapped through `redactEvalItem`; result-level metadata (`dataset`, `id`,\n * `timestamp`, `totalCost`, `duration`, `summary`, `metadata`) is\n * preserved so the Eval Runner UI can still render summary stats,\n * timing, score distributions, and cost aggregates under compliance mode.\n */\nexport function redactEvalResult(result: EvalResult, redact: boolean): EvalResult {\n if (!redact) return result;\n return {\n ...result,\n items: result.items.map(redactEvalItem),\n };\n}\n\n/**\n * Scrub an `EvalHistoryEntry`. Entry-level metadata (id, eval name,\n * timestamp) is preserved; the nested `data` (an `EvalResult`) is\n * scrubbed recursively.\n */\nexport function redactEvalHistoryEntry(entry: EvalHistoryEntry, redact: boolean): EvalHistoryEntry {\n if (!redact) return entry;\n return {\n ...entry,\n data: redactEvalResult(entry.data as EvalResult, redact),\n };\n}\n\n/** List variant for eval history. */\nexport function redactEvalHistoryList(\n entries: EvalHistoryEntry[],\n redact: boolean,\n): EvalHistoryEntry[] {\n if (!redact) return entries;\n return entries.map((e) => redactEvalHistoryEntry(e, redact));\n}\n\n// ── Pending decisions (human-in-the-loop) ───────────────────────────\n\n/**\n * Scrub a `PendingDecision`. The `prompt` field is the human-visible\n * approval question that typically echoes user or agent content (e.g.\n * \"Approve sending this email to `user@acme.com`?\"). Metadata is also\n * scrubbed because it's a free-form bag that may contain arbitrary\n * user data. Structural fields (executionId, channel, createdAt) stay\n * visible so the Decisions panel can still render the approval queue.\n */\nexport function redactPendingDecision(decision: PendingDecision, redact: boolean): PendingDecision {\n if (!redact) return decision;\n return {\n ...decision,\n prompt: REDACTED,\n ...(decision.metadata !== undefined ? { metadata: { redacted: true } } : {}),\n };\n}\n\n/** List variant for pending decisions. */\nexport function redactPendingDecisionList(\n decisions: PendingDecision[],\n redact: boolean,\n): PendingDecision[] {\n if (!redact) return decisions;\n return decisions.map((d) => redactPendingDecision(d, redact));\n}\n","import type { Context, Next } from 'hono';\nimport type { StudioEnv, ApiError } from '../types.js';\nimport { redactErrorMessage } from '../redact.js';\n\nexport async function errorHandler(c: Context<StudioEnv>, next: Next) {\n try {\n await next();\n } catch (err) {\n const rawMessage = err instanceof Error ? err.message : String(err);\n const code = (err as { code?: string }).code ?? 'INTERNAL_ERROR';\n\n // Determine HTTP status from error properties. Status classification\n // uses the raw message (not the redacted one) — redaction only affects\n // what the client sees, not how we categorize the error.\n let status = 500;\n if ('status' in (err as object)) {\n const errStatus = (err as { status: unknown }).status;\n if (typeof errStatus === 'number' && errStatus >= 400 && errStatus < 600) {\n status = errStatus;\n }\n } else if (\n code === 'NOT_FOUND' ||\n rawMessage.includes('not found') ||\n rawMessage.includes('not registered')\n ) {\n status = 404;\n } else if (\n code === 'VALIDATION_ERROR' ||\n rawMessage.includes('Expected') ||\n rawMessage.includes('invalid')\n ) {\n status = 400;\n }\n\n // Under `trace.redact`, error messages can echo user input\n // (ValidationError includes the failing reason, provider errors often\n // quote the request body, GuardrailError includes the trigger reason).\n // `redactErrorMessage` lets structural errors (Budget/Timeout/MaxTurns/\n // Quorum/NoConsensus/ToolDenied) pass through and scrubs the rest.\n const runtime = c.get('runtime');\n const redactOn = runtime?.isRedactEnabled?.() ?? false;\n\n const body: ApiError = {\n ok: false,\n error: { code, message: redactErrorMessage(err, redactOn) },\n };\n\n return c.json(body, status as 400 | 404 | 500);\n }\n}\n","/**\n * Minimal interface for a connection that can receive broadcast messages.\n * Satisfied by WSContext (Hono), ws.WebSocket (Node.js), and the middleware's\n * adapted socket. Internal to ConnectionManager — not part of the public API.\n */\nexport interface BroadcastTarget {\n send(data: string): void;\n close?(): void;\n}\n\n/**\n * Short-lived event buffer for execution streams.\n * Solves the race where a fast provider (e.g., MockProvider) completes\n * before the client's WS subscription is established. Events are buffered\n * per-channel and replayed to late subscribers.\n */\ninterface BufferedEvent {\n /** Pre-serialized JSON message (ready to `ws.send`). */\n msg: string;\n /** Original event data for filter evaluation on replay. */\n data: unknown;\n}\n\ninterface ChannelBuffer {\n events: BufferedEvent[];\n complete: boolean; // True after done/error event\n timer?: ReturnType<typeof setTimeout>;\n /** Sum of `msg.length` over buffered events. Byte-accurate; used to\n * enforce the per-buffer memory cap below. Maintained incrementally\n * so we don't have to re-scan on every push. */\n bytes: number;\n}\n\nconst BUFFER_TTL_MS = 30_000; // Clean up buffers 30s after stream completes\n\n/** Default cap on per-channel buffered events (raised from 500 in\n * spec/16 §5.2 to absorb nested-ask volume — ~10 nested asks × ~20\n * structural events each, with headroom). Override via the\n * `bufferCaps.maxEventsPerBuffer` constructor option on\n * `ConnectionManager`. */\nconst DEFAULT_MAX_BUFFER_EVENTS = 1000;\n\n/** Default per-buffer byte budget. 1000 events × 64KB max each would\n * peak at ~64MB per stream; the real-world distribution is bimodal\n * (hundreds of small structural events + a few verbose `agent_call_end`\n * snapshots), so 4MB per buffer is generous. When exceeded, new non-\n * terminal events are dropped (terminal `done`/`error` always\n * buffered). Review B-4. Override via\n * `bufferCaps.maxBytesPerBuffer`. */\nconst DEFAULT_MAX_BUFFER_BYTES = 4 * 1024 * 1024;\n\n/** Default cap on the number of concurrently-live replay buffers. Each\n * buffer is an open execution/eval stream; without a cap, a server\n * that sees sustained churn (say, 10k short-lived executions / minute)\n * holds 10k × maxBytesPerBuffer = 40GB of event-log memory across the\n * TTL window. When we hit the cap, the oldest complete buffer is\n * evicted immediately; if all live buffers are still incomplete, the\n * oldest one is dropped anyway (its late subscribers will miss the\n * replay, which is degraded UX but NOT a crash). Review SEC-H5.\n * Override via `bufferCaps.maxActiveBuffers`. */\nconst DEFAULT_MAX_ACTIVE_BUFFERS = 256;\n\n/**\n * Operator-tunable replay-buffer resource limits. Exposed via\n * `createStudioMiddleware({ bufferCaps })` and `createServer({ bufferCaps })`\n * so production deployments can tighten or relax memory pressure\n * without forking the package.\n *\n * All three fields are optional; omitted fields fall back to their\n * documented defaults, so passing `{}` is a no-op.\n */\nexport interface BufferCaps {\n /** Per-channel buffered event count cap. Default: 1000. */\n maxEventsPerBuffer?: number;\n /** Per-channel buffered byte budget. Default: 4 MiB. */\n maxBytesPerBuffer?: number;\n /** Global concurrently-live buffer cap. Default: 256. */\n maxActiveBuffers?: number;\n}\n\n/**\n * Stream-only event types excluded from the replay buffer entirely.\n * Late subscribers to an in-flight stream don't need per-token chatter\n * or per-delta progressive-render snapshots — they reconstruct the same\n * info from the final `agent_call_end` (token aggregates) and `done`\n * (final result). Both types are stream-only ergonomics, not\n * correctness-critical for replay. Spec/16 §5.2.\n */\nconst UNBUFFERED_EVENT_TYPES = new Set(['token', 'partial_object']);\n\n/** WS frame size soft cap. Used for both the inbound message reject in\n * `protocol.ts` and the outbound broadcast truncation below — keeping them\n * in one place so they never drift. Events that serialize larger than this\n * on the outbound path are replaced with a truncated placeholder so\n * consumers still receive a signal instead of having the browser's WS\n * client silently drop or close the connection. */\nexport const MAX_WS_FRAME_BYTES = 65536;\n\n/** Channels eligible for replay buffering (execution streams). */\nfunction isBufferedChannel(channel: string): boolean {\n return channel.startsWith('execution:') || channel.startsWith('eval:');\n}\n\n/**\n * Guard against outbound frames that exceed the WS size budget. Verbose-mode\n * `agent_call` events with a full `messages[]` snapshot can balloon past 64KB\n * on long conversations; browsers/ws libraries behave inconsistently when this\n * happens (silent drop, connection close, errors). Instead of hoping the\n * underlying stack handles it, we serialize once, check size, and fall back to\n * a truncated placeholder event if the payload is too large.\n *\n * The replacement preserves `channel`, `data.type`, `data.step`, `data.agent`,\n * and `data.tool` so the UI still sees the event shape — it just sees an\n * explicit truncation marker instead of silently losing data.\n */\nfunction truncateIfOversized(msg: string, channel: string, data: unknown): string {\n // WS frame budgets are measured in bytes. `string.length` counts UTF-16\n // code units; a payload with emoji / CJK / other multi-byte UTF-8 chars\n // can pass `msg.length <= 65536` yet serialize to >128KB when the\n // browser encodes the frame. Measure bytes directly to avoid\n // reintroducing the silent-drop / disconnect behavior this function\n // exists to prevent.\n const msgBytes = Buffer.byteLength(msg, 'utf8');\n if (msgBytes <= MAX_WS_FRAME_BYTES) return msg;\n const event = (data ?? {}) as {\n type?: string;\n step?: number;\n agent?: string;\n tool?: string;\n executionId?: string;\n };\n const truncated = {\n type: 'event',\n channel,\n data: {\n ...event,\n data: {\n __truncated: true,\n originalBytes: msgBytes,\n maxBytes: MAX_WS_FRAME_BYTES,\n hint: 'Event exceeded WS frame budget (likely a verbose agent_call with a large messages[] snapshot). Fetch via REST if you need the full payload.',\n },\n },\n };\n return JSON.stringify(truncated);\n}\n\n/**\n * Per-event, per-connection filter used by multi-tenant integrators to scope\n * the trace firehose. Return `true` to deliver the event to this connection,\n * `false` to skip it.\n *\n * `event` is the parsed payload (the same shape that was passed to `broadcast`);\n * `metadata` is whatever the middleware attached via `setMetadata(ws, ...)`\n * after a successful `verifyUpgrade` — typically `{ userId, tenantId }` or\n * similar, sourced from the upgrade request's auth token.\n */\nexport type BroadcastFilter = (event: unknown, metadata: unknown) => boolean;\n\n/**\n * Manages WebSocket connections and channel subscriptions.\n * Supports channel multiplexing: clients subscribe/unsubscribe to channels\n * and receive events only for channels they're subscribed to.\n *\n * Execution channels (`execution:*`) are replay-buffered: events are stored\n * so that late subscribers receive the full event history. Buffers are cleaned\n * up shortly after the stream completes.\n *\n * Multi-tenant deployments can attach per-connection metadata via\n * `setMetadata(ws, data)` and register a `BroadcastFilter` to scope the\n * trace firehose to the authenticated user/tenant.\n */\nexport class ConnectionManager {\n /** channel -> set of WS connections */\n private channels = new Map<string, Set<BroadcastTarget>>();\n /** ws -> subscribed channels + optional integrator-supplied metadata */\n private connections = new Map<BroadcastTarget, { channels: Set<string>; metadata?: unknown }>();\n /** channel -> replay buffer for execution streams */\n private buffers = new Map<string, ChannelBuffer>();\n private maxConnections = 100;\n private filter?: BroadcastFilter;\n /** Resolved replay-buffer caps. Per-instance so embedders can dial them\n * without monkey-patching module-level constants. */\n private readonly maxEventsPerBuffer: number;\n private readonly maxBytesPerBuffer: number;\n private readonly maxActiveBuffers: number;\n\n constructor(bufferCaps?: BufferCaps) {\n // Reject pathological values up-front. `0` would silently drop every\n // non-terminal event (operators following the JSDoc to \"tighten memory\n // pressure\" might pass 0 thinking it disables buffering); negatives\n // make eviction always fire. Fail-loud beats degraded replay UX.\n const validatePositiveInt = (key: keyof BufferCaps, value: number | undefined): void => {\n if (value === undefined) return;\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {\n throw new RangeError(`bufferCaps.${key} must be a positive integer (>= 1); got ${value}`);\n }\n };\n validatePositiveInt('maxEventsPerBuffer', bufferCaps?.maxEventsPerBuffer);\n validatePositiveInt('maxBytesPerBuffer', bufferCaps?.maxBytesPerBuffer);\n validatePositiveInt('maxActiveBuffers', bufferCaps?.maxActiveBuffers);\n this.maxEventsPerBuffer = bufferCaps?.maxEventsPerBuffer ?? DEFAULT_MAX_BUFFER_EVENTS;\n this.maxBytesPerBuffer = bufferCaps?.maxBytesPerBuffer ?? DEFAULT_MAX_BUFFER_BYTES;\n this.maxActiveBuffers = bufferCaps?.maxActiveBuffers ?? DEFAULT_MAX_ACTIVE_BUFFERS;\n }\n\n /**\n * Register a broadcast filter. Called once at middleware construction.\n * The filter runs on every outbound event and can drop or deliver based\n * on the destination connection's metadata.\n */\n setFilter(filter: BroadcastFilter | undefined): void {\n this.filter = filter;\n }\n\n /** Attach integrator-supplied metadata to an already-added connection. */\n setMetadata(ws: BroadcastTarget, metadata: unknown): void {\n const entry = this.connections.get(ws);\n if (entry) entry.metadata = metadata;\n }\n\n /** Register a new WS connection. */\n add(ws: BroadcastTarget): void {\n if (this.connections.size >= this.maxConnections) {\n ws.close?.();\n return;\n }\n this.connections.set(ws, { channels: new Set() });\n }\n\n /** Remove a WS connection and all its subscriptions. */\n remove(ws: BroadcastTarget): void {\n const entry = this.connections.get(ws);\n if (entry) {\n for (const ch of entry.channels) {\n this.channels.get(ch)?.delete(ws);\n if (this.channels.get(ch)?.size === 0) {\n this.channels.delete(ch);\n }\n }\n }\n this.connections.delete(ws);\n }\n\n /** Subscribe a connection to a channel. Replays buffered events for execution channels. */\n subscribe(ws: BroadcastTarget, channel: string): void {\n if (!this.connections.has(ws)) return;\n let subs = this.channels.get(channel);\n if (!subs) {\n subs = new Set();\n this.channels.set(channel, subs);\n }\n subs.add(ws);\n this.connections.get(ws)!.channels.add(channel);\n\n // Replay buffered events for late subscribers. Filter is re-applied on\n // replay so a tenant-B subscriber joining an execution channel doesn't\n // get tenant-A events that were buffered before it connected.\n const buffer = this.buffers.get(channel);\n if (buffer) {\n const metadata = this.connections.get(ws)?.metadata;\n for (const event of buffer.events) {\n if (this.filter) {\n try {\n if (!this.filter(event.data, metadata)) continue;\n } catch {\n continue;\n }\n }\n try {\n ws.send(event.msg);\n } catch {\n this.remove(ws);\n return;\n }\n }\n }\n }\n\n /** Unsubscribe a connection from a channel. */\n unsubscribe(ws: BroadcastTarget, channel: string): void {\n this.channels.get(channel)?.delete(ws);\n if (this.channels.get(channel)?.size === 0) {\n this.channels.delete(channel);\n }\n this.connections.get(ws)?.channels.delete(channel);\n }\n\n /** Broadcast data to all subscribers of a channel. Buffers events for execution channels. */\n broadcast(channel: string, data: unknown): void {\n const msg = truncateIfOversized(\n JSON.stringify({ type: 'event', channel, data }),\n channel,\n data,\n );\n\n // Buffer events for execution channels so late subscribers can replay\n if (isBufferedChannel(channel)) {\n let buffer = this.buffers.get(channel);\n if (!buffer) {\n // Enforce the global-buffer cap before allocating. Evict the\n // oldest-inserted buffer (Map preserves insertion order, so\n // `.keys().next().value` is the eldest). Prefer evicting a\n // completed buffer if any exist — its late-subscriber window\n // is already effectively closed. Falls back to evicting the\n // eldest live buffer under sustained pressure.\n if (this.buffers.size >= this.maxActiveBuffers) {\n let victim: string | undefined;\n for (const [ch, buf] of this.buffers) {\n if (buf.complete) {\n victim = ch;\n break;\n }\n }\n if (victim === undefined) {\n victim = this.buffers.keys().next().value as string | undefined;\n }\n if (victim !== undefined) {\n const old = this.buffers.get(victim);\n if (old?.timer) clearTimeout(old.timer);\n this.buffers.delete(victim);\n }\n }\n buffer = { events: [], complete: false, bytes: 0 };\n this.buffers.set(channel, buffer);\n }\n // Always buffer terminal events; skip non-terminal if at capacity\n // on EITHER the event-count OR byte budget; never buffer\n // high-volume types (token, partial_object) per spec/16 §5.2 —\n // late subscribers reconstruct the same info from structural\n // events.\n const event = data as { type?: string };\n const isTerminal = event.type === 'done' || event.type === 'error';\n const isUnbuffered = event.type !== undefined && UNBUFFERED_EVENT_TYPES.has(event.type);\n if (!isUnbuffered) {\n const msgBytes = Buffer.byteLength(msg, 'utf8');\n const atCountCap = buffer.events.length >= this.maxEventsPerBuffer;\n const atByteCap = buffer.bytes + msgBytes > this.maxBytesPerBuffer;\n if (isTerminal || (!atCountCap && !atByteCap)) {\n buffer.events.push({ msg, data });\n buffer.bytes += msgBytes;\n }\n }\n\n // Schedule buffer cleanup after terminal events\n if (isTerminal) {\n buffer.complete = true;\n if (buffer.timer) clearTimeout(buffer.timer);\n buffer.timer = setTimeout(() => {\n this.buffers.delete(channel);\n }, BUFFER_TTL_MS);\n }\n }\n\n // Send to current subscribers\n const subs = this.channels.get(channel);\n if (!subs || subs.size === 0) return;\n\n for (const ws of [...subs]) {\n // Multi-tenant filter: drop events that don't match this connection's\n // metadata (e.g., wrong tenant). Filter errors are treated as `drop`\n // so a buggy predicate can't accidentally leak events cross-tenant.\n if (this.filter) {\n const metadata = this.connections.get(ws)?.metadata;\n try {\n if (!this.filter(data, metadata)) continue;\n } catch {\n continue;\n }\n }\n try {\n ws.send(msg);\n } catch {\n this.remove(ws);\n }\n }\n }\n\n /** Broadcast to channel and all wildcard subscribers (e.g., trace:* matches trace:abc). */\n broadcastWithWildcard(channel: string, data: unknown): void {\n this.broadcast(channel, data);\n\n // Check for wildcard subscribers: \"prefix:*\" matches \"prefix:anything\"\n // Send with the actual channel name so wildcard subscribers know the source.\n const colonIdx = channel.indexOf(':');\n if (colonIdx > 0) {\n const wildcardChannel = channel.substring(0, colonIdx) + ':*';\n const subs = this.channels.get(wildcardChannel);\n if (!subs || subs.size === 0) return;\n\n const msg = truncateIfOversized(\n JSON.stringify({ type: 'event', channel, data }),\n channel,\n data,\n );\n for (const ws of [...subs]) {\n if (this.filter) {\n const metadata = this.connections.get(ws)?.metadata;\n try {\n if (!this.filter(data, metadata)) continue;\n } catch {\n continue;\n }\n }\n try {\n ws.send(msg);\n } catch {\n this.remove(ws);\n }\n }\n }\n }\n\n /** Close all connections, clear all state and buffers. Used during shutdown. */\n closeAll(): void {\n for (const ws of this.connections.keys()) {\n ws.close?.();\n }\n for (const buffer of this.buffers.values()) {\n if (buffer.timer) clearTimeout(buffer.timer);\n }\n this.connections.clear();\n this.channels.clear();\n this.buffers.clear();\n }\n\n /** Get the number of active connections. */\n get connectionCount(): number {\n return this.connections.size;\n }\n\n /** Check if any connections are subscribed to a channel. */\n hasSubscribers(channel: string): boolean {\n return (this.channels.get(channel)?.size ?? 0) > 0;\n }\n}\n","import type { BroadcastTarget } from './connection-manager.js';\nimport { MAX_WS_FRAME_BYTES, type ConnectionManager } from './connection-manager.js';\n\n/** Channel prefixes that accept suffixes (e.g., execution:abc, trace:*). */\nconst VALID_CHANNEL_PREFIXES = ['execution:', 'trace:', 'eval:'];\n/** Channels that must match exactly (no suffix allowed). */\nconst VALID_EXACT_CHANNELS = ['costs', 'decisions', 'eval-trends', 'workflow-stats', 'trace-stats'];\nconst MAX_CHANNEL_LENGTH = 256;\n\n/**\n * Handle a single WebSocket message according to the Studio protocol.\n * Returns a JSON string to send back to the client, or null for no response.\n *\n * Used by both the Hono WS handler (ws/handler.ts) and the Node.js\n * middleware (middleware.ts) to keep the protocol in one place.\n */\nexport function handleWsMessage(\n raw: string,\n socket: BroadcastTarget,\n connMgr: ConnectionManager,\n): string | null {\n // Reject oversized messages. Shared cap with the outbound broadcast path\n // in connection-manager.ts — see `MAX_WS_FRAME_BYTES` for rationale.\n // Measure bytes (not UTF-16 code units) so multi-byte payloads (emoji /\n // CJK / other non-ASCII) can't pass `raw.length` while serializing past\n // 64KB on the wire — keeping symmetry with the outbound `Buffer.byteLength`\n // check in `connection-manager.ts:truncateIfOversized`.\n if (Buffer.byteLength(raw, 'utf8') > MAX_WS_FRAME_BYTES) {\n return JSON.stringify({ type: 'error', message: 'Message too large' });\n }\n\n let msg: { type: string; channel?: string };\n try {\n msg = JSON.parse(raw);\n } catch {\n return JSON.stringify({ type: 'error', message: 'Invalid JSON' });\n }\n\n switch (msg.type) {\n case 'subscribe': {\n const error = validateChannel(msg.channel);\n if (error) return JSON.stringify({ type: 'error', message: error });\n connMgr.subscribe(socket, msg.channel!);\n return JSON.stringify({ type: 'subscribed', channel: msg.channel });\n }\n case 'unsubscribe': {\n const error = validateChannel(msg.channel);\n if (error) return JSON.stringify({ type: 'error', message: error });\n connMgr.unsubscribe(socket, msg.channel!);\n return JSON.stringify({ type: 'unsubscribed', channel: msg.channel });\n }\n case 'ping':\n return JSON.stringify({ type: 'pong' });\n default:\n return JSON.stringify({ type: 'error', message: 'Unknown message type' });\n }\n}\n\nfunction validateChannel(channel: unknown): string | null {\n if (typeof channel !== 'string' || !channel) {\n return 'Missing or invalid channel';\n }\n if (channel.length > MAX_CHANNEL_LENGTH) {\n return `Channel name exceeds ${MAX_CHANNEL_LENGTH} characters`;\n }\n if (\n !VALID_EXACT_CHANNELS.includes(channel as (typeof VALID_EXACT_CHANNELS)[number]) &&\n !VALID_CHANNEL_PREFIXES.some((p) => channel.startsWith(p))\n ) {\n return `Invalid channel: ${channel}`;\n }\n return null;\n}\n","import type { WSContext } from 'hono/ws';\nimport type { ConnectionManager } from './connection-manager.js';\nimport { handleWsMessage } from './protocol.js';\n\n/** Create WS event handlers for a Hono WebSocket connection. */\nexport function createWsHandlers(connMgr: ConnectionManager) {\n return {\n onOpen(_event: Event, ws: WSContext) {\n connMgr.add(ws);\n },\n\n onMessage(event: MessageEvent, ws: WSContext) {\n const reply = handleWsMessage(String(event.data), ws, connMgr);\n if (reply) ws.send(reply);\n },\n\n onClose(_event: CloseEvent, ws: WSContext) {\n connMgr.remove(ws);\n },\n\n onError(_event: Event, ws: WSContext) {\n connMgr.remove(ws);\n },\n };\n}\n","import type { ConnectionManager } from '../ws/connection-manager.js';\n\nexport type WindowId = '24h' | '7d' | '30d' | 'all';\n\nexport type AggregateBroadcast<State> = {\n snapshots: Record<WindowId, State>;\n updatedAt: number;\n};\n\nconst WINDOW_MS: Record<WindowId, number> = {\n '24h': 24 * 60 * 60 * 1000,\n '7d': 7 * 24 * 60 * 60 * 1000,\n '30d': 30 * 24 * 60 * 60 * 1000,\n all: Number.POSITIVE_INFINITY,\n};\n\nexport function withinWindow(ts: number, window: WindowId, now: number): boolean {\n return ts >= now - WINDOW_MS[window];\n}\n\n/** Hardcoded rebuild interval — no env var or config surface in v1. */\nexport const REBUILD_INTERVAL_MS = 5 * 60_000;\n\nconst ALL_WINDOWS = new Set<string>(Object.keys(WINDOW_MS));\n\n/** Parse a `?window=` query param into a validated WindowId, defaulting to `7d`. */\nexport function parseWindowParam(raw?: string | null, fallback: WindowId = '7d'): WindowId {\n return raw && ALL_WINDOWS.has(raw) ? (raw as WindowId) : fallback;\n}\n\n/**\n * Holds per-window snapshots of an aggregate state and handles\n * window-filter logic and WebSocket broadcast.\n */\nexport class AggregateSnapshots<State> {\n private snapshots: Map<WindowId, State>;\n\n constructor(\n private windows: WindowId[],\n private emptyState: () => State,\n private connMgr: ConnectionManager,\n private channel: string,\n /** Optional transform applied to each window's state before WS broadcast.\n * Useful when the broadcast payload differs from the internal state\n * (e.g., stripping internal arrays and adding computed fields). */\n private broadcastTransform?: (state: State) => unknown,\n ) {\n this.snapshots = new Map(windows.map((w) => [w, emptyState()]));\n }\n\n /** Replace all snapshots atomically — used after a full rebuild. */\n replace(fresh: Map<WindowId, State>): void {\n this.snapshots = fresh;\n this.broadcast();\n }\n\n /** Apply a reducer update to every window where `ts` falls inside the window. */\n fold(ts: number, update: (prev: State) => State): void {\n const now = Date.now();\n let changed = false;\n for (const window of this.windows) {\n if (withinWindow(ts, window, now)) {\n const prev = this.snapshots.get(window)!;\n this.snapshots.set(window, update(prev));\n changed = true;\n }\n }\n if (changed) this.broadcast();\n }\n\n get(window: WindowId): State {\n return this.snapshots.get(window) ?? this.emptyState();\n }\n\n getAll(): Record<WindowId, State> {\n return Object.fromEntries(this.snapshots) as Record<WindowId, State>;\n }\n\n private broadcast(): void {\n const snapshots = this.broadcastTransform\n ? (Object.fromEntries(\n this.windows.map((w) => [w, this.broadcastTransform!(this.snapshots.get(w)!)]),\n ) as Record<WindowId, unknown>)\n : this.getAll();\n this.connMgr.broadcast(this.channel, {\n snapshots,\n updatedAt: Date.now(),\n });\n }\n}\n","import type { AxlRuntime, AxlEvent, ExecutionInfo } from '@axlsdk/axl';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport { AggregateSnapshots, REBUILD_INTERVAL_MS, withinWindow } from './aggregate-snapshots.js';\nimport type { WindowId } from './aggregate-snapshots.js';\n\nexport type TraceReducer<State> = (acc: State, event: AxlEvent) => State;\n\nexport type TraceAggregatorOptions<State> = {\n runtime: AxlRuntime;\n connMgr: ConnectionManager;\n channel: string;\n reducer: TraceReducer<State>;\n emptyState: () => State;\n windows: WindowId[];\n /** Max executions to replay on rebuild. Default 2000. */\n executionCap?: number;\n /** Optional transform applied to each window's state before WS broadcast. */\n broadcastTransform?: (state: State) => unknown;\n};\n\n/**\n * Consumes AxlEvents from execution history and the live trace stream.\n * Maintains per-window aggregate snapshots via a pure reducer.\n */\nexport class TraceAggregator<State> {\n private snaps: AggregateSnapshots<State>;\n private interval?: ReturnType<typeof setInterval>;\n private listener?: (event: AxlEvent) => void;\n private options: TraceAggregatorOptions<State>;\n\n constructor(options: TraceAggregatorOptions<State>) {\n this.options = options;\n this.snaps = new AggregateSnapshots(\n options.windows,\n options.emptyState,\n options.connMgr,\n options.channel,\n options.broadcastTransform,\n );\n }\n\n async start(): Promise<void> {\n await this.rebuild();\n this.listener = (event: AxlEvent) => {\n this.snaps.fold(event.timestamp, (prev) => this.options.reducer(prev, event));\n };\n this.options.runtime.on('trace', this.listener);\n this.interval = setInterval(\n () => this.rebuild().catch((err) => console.error('[axl-studio] rebuild failed:', err)),\n REBUILD_INTERVAL_MS,\n );\n }\n\n async rebuild(): Promise<void> {\n const executions: ExecutionInfo[] = await this.options.runtime.getExecutions();\n const cap = this.options.executionCap ?? 2000;\n const capped = executions.slice(0, cap);\n const now = Date.now();\n const fresh = new Map<WindowId, State>(\n this.options.windows.map((w) => [w, this.options.emptyState()]),\n );\n for (const exec of capped) {\n for (const event of exec.events) {\n for (const window of this.options.windows) {\n if (withinWindow(event.timestamp, window, now)) {\n fresh.set(window, this.options.reducer(fresh.get(window)!, event));\n }\n }\n }\n }\n this.snaps.replace(fresh);\n }\n\n getSnapshot(window: WindowId): State {\n return this.snaps.get(window);\n }\n\n getAllSnapshots(): Record<WindowId, State> {\n return this.snaps.getAll();\n }\n\n close(): void {\n if (this.listener) this.options.runtime.off('trace', this.listener);\n if (this.interval) clearInterval(this.interval);\n }\n}\n","import type { AxlRuntime, AxlEvent, ExecutionInfo } from '@axlsdk/axl';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport { AggregateSnapshots, REBUILD_INTERVAL_MS, withinWindow } from './aggregate-snapshots.js';\nimport type { WindowId } from './aggregate-snapshots.js';\n\nexport type ExecutionReducer<State> = (acc: State, execution: ExecutionInfo) => State;\n\nexport type ExecutionAggregatorOptions<State> = {\n runtime: AxlRuntime;\n connMgr: ConnectionManager;\n channel: string;\n reducer: ExecutionReducer<State>;\n emptyState: () => State;\n windows: WindowId[];\n /** Max executions to replay on rebuild. Default 2000. */\n executionCap?: number;\n /** Optional transform applied to each window's state before WS broadcast. */\n broadcastTransform?: (state: State) => unknown;\n};\n\n/**\n * Consumes ExecutionInfo at the execution granularity (not individual trace events).\n * Live updates arrive via workflow_end trace events — the aggregator fetches the\n * finalized ExecutionInfo and folds it.\n */\nexport class ExecutionAggregator<State> {\n private snaps: AggregateSnapshots<State>;\n private interval?: ReturnType<typeof setInterval>;\n private listener?: (event: AxlEvent) => void;\n private options: ExecutionAggregatorOptions<State>;\n /** Generation counter to prevent stale async fold after rebuild. */\n private generation = 0;\n\n constructor(options: ExecutionAggregatorOptions<State>) {\n this.options = options;\n this.snaps = new AggregateSnapshots(\n options.windows,\n options.emptyState,\n options.connMgr,\n options.channel,\n options.broadcastTransform,\n );\n }\n\n async start(): Promise<void> {\n await this.rebuild();\n this.listener = (event: AxlEvent) => {\n if (event.type !== 'workflow_end') return;\n // Capture generation before the async gap\n const gen = this.generation;\n this.options.runtime\n .getExecution(event.executionId)\n .then((exec) => {\n // Skip if a rebuild happened between event and resolution\n if (this.generation !== gen) return;\n if (exec) {\n this.snaps.fold(exec.startedAt, (prev) => this.options.reducer(prev, exec));\n }\n })\n .catch((err) => console.error('[axl-studio] execution fold failed:', err));\n };\n this.options.runtime.on('trace', this.listener);\n this.interval = setInterval(\n () => this.rebuild().catch((err) => console.error('[axl-studio] rebuild failed:', err)),\n REBUILD_INTERVAL_MS,\n );\n }\n\n async rebuild(): Promise<void> {\n this.generation++;\n const executions: ExecutionInfo[] = await this.options.runtime.getExecutions();\n const cap = this.options.executionCap ?? 2000;\n const capped = executions.slice(0, cap);\n const now = Date.now();\n const fresh = new Map<WindowId, State>(\n this.options.windows.map((w) => [w, this.options.emptyState()]),\n );\n for (const exec of capped) {\n for (const window of this.options.windows) {\n if (withinWindow(exec.startedAt, window, now)) {\n fresh.set(window, this.options.reducer(fresh.get(window)!, exec));\n }\n }\n }\n this.snaps.replace(fresh);\n }\n\n getSnapshot(window: WindowId): State {\n return this.snaps.get(window);\n }\n\n getAllSnapshots(): Record<WindowId, State> {\n return this.snaps.getAll();\n }\n\n close(): void {\n if (this.listener) this.options.runtime.off('trace', this.listener);\n if (this.interval) clearInterval(this.interval);\n }\n}\n","import type { AxlRuntime, EvalHistoryEntry } from '@axlsdk/axl';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport { AggregateSnapshots, REBUILD_INTERVAL_MS, withinWindow } from './aggregate-snapshots.js';\nimport type { WindowId } from './aggregate-snapshots.js';\n\nexport type EvalReducer<State> = (acc: State, entry: EvalHistoryEntry) => State;\n\nexport type EvalAggregatorOptions<State> = {\n runtime: AxlRuntime;\n connMgr: ConnectionManager;\n channel: string;\n reducer: EvalReducer<State>;\n emptyState: () => State;\n windows: WindowId[];\n /** Max eval entries to replay on rebuild. Default 500. */\n entryCap?: number;\n /** Optional transform applied to each window's state before WS broadcast. */\n broadcastTransform?: (state: State) => unknown;\n};\n\n/**\n * Consumes EvalHistoryEntry. Rebuilds from runtime.getEvalHistory().\n * Live updates arrive via runtime.on('eval_result', entry).\n */\nexport class EvalAggregator<State> {\n private snaps: AggregateSnapshots<State>;\n private interval?: ReturnType<typeof setInterval>;\n private listener?: (entry: EvalHistoryEntry) => void;\n private options: EvalAggregatorOptions<State>;\n\n constructor(options: EvalAggregatorOptions<State>) {\n this.options = options;\n this.snaps = new AggregateSnapshots(\n options.windows,\n options.emptyState,\n options.connMgr,\n options.channel,\n options.broadcastTransform,\n );\n }\n\n async start(): Promise<void> {\n await this.rebuild();\n this.listener = (entry: EvalHistoryEntry) => {\n this.snaps.fold(entry.timestamp, (prev) => this.options.reducer(prev, entry));\n };\n this.options.runtime.on('eval_result', this.listener);\n this.interval = setInterval(\n () => this.rebuild().catch((err) => console.error('[axl-studio] rebuild failed:', err)),\n REBUILD_INTERVAL_MS,\n );\n }\n\n async rebuild(): Promise<void> {\n const history: EvalHistoryEntry[] = await this.options.runtime.getEvalHistory();\n const cap = this.options.entryCap ?? 500;\n const capped = history.slice(0, cap);\n const now = Date.now();\n const fresh = new Map<WindowId, State>(\n this.options.windows.map((w) => [w, this.options.emptyState()]),\n );\n for (const entry of capped) {\n for (const window of this.options.windows) {\n if (withinWindow(entry.timestamp, window, now)) {\n fresh.set(window, this.options.reducer(fresh.get(window)!, entry));\n }\n }\n }\n this.snaps.replace(fresh);\n }\n\n getSnapshot(window: WindowId): State {\n return this.snaps.get(window);\n }\n\n getAllSnapshots(): Record<WindowId, State> {\n return this.snaps.getAll();\n }\n\n close(): void {\n if (this.listener) this.options.runtime.off('eval_result', this.listener);\n if (this.interval) clearInterval(this.interval);\n }\n}\n","/**\n * Pure reducer functions for each aggregate panel.\n * Each reducer is a pure (state, source) => state function — no I/O, no mutation.\n */\nimport type { AxlEvent, ExecutionInfo, EvalHistoryEntry } from '@axlsdk/axl';\nimport { eventCostContribution } from '@axlsdk/axl';\nimport type { CostData } from '../types.js';\n\n// ── Shared helpers ────────────────────────────────────────────────────\n\n/** Clamp a possibly-NaN/Infinity number to 0. */\nconst finite = (v: number | undefined): number => (Number.isFinite(v) ? v! : 0);\n\n// ── Cost reducer (AxlEvent → CostData) ──────────────────────────────\n\nfunction emptyRetry(): CostData['retry'] {\n return {\n primary: 0,\n primaryCalls: 0,\n schema: 0,\n schemaCalls: 0,\n validate: 0,\n validateCalls: 0,\n guardrail: 0,\n guardrailCalls: 0,\n retryCalls: 0,\n };\n}\n\nexport function emptyCostData(): CostData {\n return {\n totalCost: 0,\n totalTokens: { input: 0, output: 0, reasoning: 0 },\n byAgent: {},\n byModel: {},\n byWorkflow: {},\n retry: emptyRetry(),\n byEmbedder: {},\n };\n}\n\n/**\n * Pure reducer for CostData with full parity to CostAggregator.onTrace.\n * Handles retry decomposition, embedder cost bucketing, workflow_start\n * detection (both production log-form and test runtime shapes), and\n * NaN/Infinity guards on all numeric accumulations.\n */\nexport function reduceCost(acc: CostData, event: AxlEvent): CostData {\n const isWorkflowStart = event.type === 'workflow_start';\n\n // workflow_start events increment per-workflow executions and return early.\n // They carry no meaningful cost — any cost/token fields are incidental.\n if (isWorkflowStart && event.workflow) {\n const byWorkflow = { ...acc.byWorkflow };\n const prev = byWorkflow[event.workflow] ?? { cost: 0, executions: 0 };\n byWorkflow[event.workflow] = { ...prev, executions: prev.executions + 1 };\n return { ...acc, byWorkflow };\n }\n\n // Early return for events with no cost data.\n if (event.cost == null && !event.tokens) return acc;\n\n // Rollup guard: `eventCostContribution` encapsulates the spec §10\n // \"skip ask_end, finite-check, leaf-only\" invariant. The rest of\n // this reducer buckets the charge across per-agent / per-model /\n // per-workflow views; calling the helper once here keeps the\n // semantics in one place. If the contribution is 0 (ask_end or\n // NaN), short-circuit so we don't increment call counts either.\n const cost = eventCostContribution(event);\n if (event.type === 'ask_end') return acc;\n const tokens = event.tokens ?? {};\n\n // Only count tokens from agent_call_end events — embedder tokens are\n // bucketed separately into byEmbedder.tokens.\n const totalTokens =\n event.type === 'agent_call_end'\n ? {\n input: acc.totalTokens.input + finite(tokens.input),\n output: acc.totalTokens.output + finite(tokens.output),\n reasoning: acc.totalTokens.reasoning + finite(tokens.reasoning),\n }\n : acc.totalTokens;\n\n const byAgent = { ...acc.byAgent };\n if (event.agent) {\n const prev = byAgent[event.agent] ?? { cost: 0, calls: 0 };\n byAgent[event.agent] = { cost: prev.cost + cost, calls: prev.calls + 1 };\n }\n\n const byModel = { ...acc.byModel };\n if (event.model) {\n const prev = byModel[event.model] ?? { cost: 0, calls: 0, tokens: { input: 0, output: 0 } };\n byModel[event.model] = {\n cost: prev.cost + cost,\n calls: prev.calls + 1,\n tokens: {\n input: prev.tokens.input + finite(tokens.input),\n output: prev.tokens.output + finite(tokens.output),\n },\n };\n }\n\n const byWorkflow = { ...acc.byWorkflow };\n if (event.workflow) {\n const prev = byWorkflow[event.workflow] ?? { cost: 0, executions: 0 };\n byWorkflow[event.workflow] = {\n cost: prev.cost + cost,\n executions: prev.executions + (isWorkflowStart ? 1 : 0),\n };\n }\n\n // Retry-cost decomposition: split agent_call_end cost by retryReason.\n let retry = acc.retry;\n if (event.type === 'agent_call_end') {\n const d = (event.data ?? {}) as { retryReason?: 'schema' | 'validate' | 'guardrail' };\n const reason = d.retryReason;\n retry = { ...acc.retry };\n if (reason === 'schema') {\n retry.schema += cost;\n retry.schemaCalls += 1;\n retry.retryCalls += 1;\n } else if (reason === 'validate') {\n retry.validate += cost;\n retry.validateCalls += 1;\n retry.retryCalls += 1;\n } else if (reason === 'guardrail') {\n retry.guardrail += cost;\n retry.guardrailCalls += 1;\n retry.retryCalls += 1;\n } else {\n retry.primary += cost;\n retry.primaryCalls += 1;\n }\n }\n\n // Embedder cost: `memory_remember` / `memory_recall` variants carry\n // `usage.{tokens,model}` and a top-level `cost` (mirrored by the\n // emitter). Bucket by embedder model so the Cost Dashboard's\n // \"Memory (Embedder)\" section can break down spend.\n let byEmbedder = acc.byEmbedder;\n if (event.type === 'memory_remember' || event.type === 'memory_recall') {\n const usage = event.data.usage;\n byEmbedder = { ...acc.byEmbedder };\n const modelKey = usage?.model ?? 'unknown';\n const embedTokens = typeof usage?.tokens === 'number' ? finite(usage.tokens) : 0;\n const prev = byEmbedder[modelKey] ?? { cost: 0, calls: 0, tokens: 0 };\n byEmbedder[modelKey] = {\n cost: prev.cost + cost,\n calls: prev.calls + 1,\n tokens: prev.tokens + embedTokens,\n };\n }\n\n return {\n totalCost: acc.totalCost + cost,\n totalTokens,\n byAgent,\n byModel,\n byWorkflow,\n retry,\n byEmbedder,\n };\n}\n\n// ── Eval trends reducer (EvalHistoryEntry → EvalTrendData) ────────────\n\nexport type EvalTrendRun = {\n timestamp: number;\n id: string;\n scores: Record<string, number>;\n cost: number;\n /** Primary model for this run (first entry of `metadata.models`). Undefined\n * when the run has no recorded models (e.g., legacy data or test harnesses). */\n model?: string;\n /** Total run duration in ms (from `EvalResult.duration`). */\n duration?: number;\n};\n\nexport type EvalTrendEntry = {\n runs: EvalTrendRun[];\n latestScores: Record<string, number>;\n scoreMean: Record<string, number>;\n scoreStd: Record<string, number>;\n costTotal: number;\n runCount: number;\n};\n\nexport type EvalTrendData = {\n byEval: Record<string, EvalTrendEntry>;\n totalRuns: number;\n totalCost: number;\n};\n\nexport function emptyEvalTrendData(): EvalTrendData {\n return { byEval: {}, totalRuns: 0, totalCost: 0 };\n}\n\n/** Extract per-scorer aggregate score from an EvalHistoryEntry's data blob.\n * The EvalResult shape is `{ summary: { scorers: Record<string, { mean, min,\n * max, p50, p95 }> }, ... }`. We take `mean` as the representative score for\n * each scorer in this run — what gets plotted on the trend line. */\nfunction extractScores(data: unknown): Record<string, number> {\n if (!data || typeof data !== 'object') return {};\n const result = data as Record<string, unknown>;\n const summary = result.summary as Record<string, unknown> | undefined;\n const scorers = summary?.scorers as Record<string, { mean?: number } | number> | undefined;\n if (!scorers) return {};\n const out: Record<string, number> = {};\n for (const [name, entry] of Object.entries(scorers)) {\n if (typeof entry === 'number' && Number.isFinite(entry)) {\n out[name] = entry;\n } else if (entry && typeof entry === 'object' && Number.isFinite(entry.mean)) {\n out[name] = entry.mean as number;\n }\n }\n return out;\n}\n\n/** Extract total cost from an EvalHistoryEntry's data blob.\n * `EvalResult.totalCost` is at the top level (not under summary). */\nfunction extractCost(data: unknown): number {\n if (!data || typeof data !== 'object') return 0;\n const result = data as Record<string, unknown>;\n if (Number.isFinite(result.totalCost)) return result.totalCost as number;\n // Back-compat: some early tests/fixtures put it under summary.totalCost\n const summary = result.summary as Record<string, unknown> | undefined;\n return Number.isFinite(summary?.totalCost) ? (summary!.totalCost as number) : 0;\n}\n\n/** Extract the primary model for this run.\n * Prefers the most-called model from `metadata.modelCounts`, falling back to\n * `metadata.models[0]`. Returns undefined if no model is recorded — UI groups\n * those runs under \"unknown\". For a mixed-model run (e.g., classify-then-answer),\n * the most-called model is the honest \"primary\" choice. */\nfunction extractModel(data: unknown): string | undefined {\n if (!data || typeof data !== 'object') return undefined;\n const result = data as Record<string, unknown>;\n const metadata = result.metadata as { models?: unknown; modelCounts?: unknown } | undefined;\n const counts = metadata?.modelCounts;\n if (counts && typeof counts === 'object' && !Array.isArray(counts)) {\n const entries = Object.entries(counts as Record<string, unknown>).filter(\n ([, v]) => typeof v === 'number',\n ) as Array<[string, number]>;\n if (entries.length > 0) {\n // Secondary alphabetical sort breaks ties deterministically so two\n // runs with the same modelCounts (e.g., { a: 3, b: 3 } vs { b: 3, a: 3 })\n // always resolve to the same \"primary model\" regardless of insertion order.\n entries.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));\n return entries[0][0];\n }\n }\n const models = metadata?.models;\n if (Array.isArray(models) && typeof models[0] === 'string') return models[0];\n return undefined;\n}\n\n/** Extract run duration in ms from `EvalResult.duration`. */\nfunction extractDuration(data: unknown): number | undefined {\n if (!data || typeof data !== 'object') return undefined;\n const result = data as Record<string, unknown>;\n return Number.isFinite(result.duration) ? (result.duration as number) : undefined;\n}\n\n/** Compute mean and std for score arrays. */\nfunction computeScoreStats(runs: EvalTrendRun[]): {\n mean: Record<string, number>;\n std: Record<string, number>;\n} {\n const scorerNames = new Set<string>();\n for (const run of runs) {\n for (const name of Object.keys(run.scores)) scorerNames.add(name);\n }\n\n const mean: Record<string, number> = {};\n const std: Record<string, number> = {};\n for (const name of scorerNames) {\n const values = runs.map((r) => r.scores[name]).filter((v) => v != null);\n if (values.length === 0) continue;\n const m = values.reduce((a, b) => a + b, 0) / values.length;\n mean[name] = m;\n const variance = values.reduce((sum, v) => sum + (v - m) ** 2, 0) / values.length;\n std[name] = Math.sqrt(variance);\n }\n return { mean, std };\n}\n\nexport function reduceEvalTrends(acc: EvalTrendData, entry: EvalHistoryEntry): EvalTrendData {\n const scores = extractScores(entry.data);\n const cost = extractCost(entry.data);\n const model = extractModel(entry.data);\n const duration = extractDuration(entry.data);\n const run: EvalTrendRun = {\n timestamp: entry.timestamp,\n id: entry.id,\n scores,\n cost,\n ...(model !== undefined ? { model } : {}),\n ...(duration !== undefined ? { duration } : {}),\n };\n\n const byEval = { ...acc.byEval };\n const prev = byEval[entry.eval];\n // Cap runs array to limit WS broadcast payload size. Client only shows\n // the 10 most recent; keep 50 for future chart use.\n const MAX_EVAL_RUNS = 50;\n const allRuns = prev ? [...prev.runs, run] : [run];\n const runs = allRuns.length > MAX_EVAL_RUNS ? allRuns.slice(-MAX_EVAL_RUNS) : allRuns;\n const { mean, std } = computeScoreStats(runs);\n\n // latestScores is the most recent run's scores by timestamp.\n // During rebuild, entries arrive newest-first, so only overwrite if\n // there's no existing entry or this run is newer.\n const latestScores =\n prev && prev.runs.length > 0 && prev.runs[prev.runs.length - 1].timestamp > run.timestamp\n ? prev.latestScores\n : scores;\n\n byEval[entry.eval] = {\n runs,\n latestScores,\n scoreMean: mean,\n scoreStd: std,\n costTotal: (prev?.costTotal ?? 0) + cost,\n runCount: (prev?.runCount ?? 0) + 1,\n };\n\n return {\n byEval,\n totalRuns: acc.totalRuns + 1,\n totalCost: acc.totalCost + cost,\n };\n}\n\n// ── Workflow stats reducer (ExecutionInfo → WorkflowStatsData) ────────\n\n/** Max recent durations to keep per workflow for percentile computation. */\nconst MAX_DURATIONS = 200;\n\nexport type WorkflowStatsData = {\n byWorkflow: Record<\n string,\n {\n total: number;\n completed: number;\n failed: number;\n /** Bounded sorted array of recent durations for p50/p95. Max MAX_DURATIONS entries. */\n durations: number[];\n durationSum: number;\n avgDuration: number;\n }\n >;\n totalExecutions: number;\n failureRate: number;\n};\n\nexport function emptyWorkflowStatsData(): WorkflowStatsData {\n return { byWorkflow: {}, totalExecutions: 0, failureRate: 0 };\n}\n\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0;\n const idx = (p / 100) * (sorted.length - 1);\n const lower = Math.floor(idx);\n const upper = Math.ceil(idx);\n if (lower === upper) return sorted[lower];\n return sorted[lower] + (sorted[upper] - sorted[lower]) * (idx - lower);\n}\n\nexport function reduceWorkflowStats(\n acc: WorkflowStatsData,\n execution: ExecutionInfo,\n): WorkflowStatsData {\n const byWorkflow = { ...acc.byWorkflow };\n const prev = byWorkflow[execution.workflow] ?? {\n total: 0,\n completed: 0,\n failed: 0,\n durations: [],\n durationSum: 0,\n avgDuration: 0,\n };\n\n // Maintain a bounded sorted array for percentile computation.\n // Insert in sorted position, evict the smallest (front) if over cap.\n // This biases toward recent larger values — acceptable for dashboard use.\n const dur = finite(execution.duration);\n const durations = [...prev.durations];\n const insertIdx = durations.findIndex((d) => d > dur);\n if (insertIdx === -1) durations.push(dur);\n else durations.splice(insertIdx, 0, dur);\n if (durations.length > MAX_DURATIONS) durations.shift();\n\n const total = prev.total + 1;\n const completed = prev.completed + (execution.status === 'completed' ? 1 : 0);\n const failed = prev.failed + (execution.status === 'failed' ? 1 : 0);\n const durationSum = prev.durationSum + dur;\n const avgDuration = durationSum / total;\n\n byWorkflow[execution.workflow] = {\n total,\n completed,\n failed,\n durations,\n durationSum,\n avgDuration,\n };\n\n const totalExecutions = acc.totalExecutions + 1;\n const totalFailed = Object.values(byWorkflow).reduce((sum, w) => sum + w.failed, 0);\n const failureRate = totalExecutions > 0 ? totalFailed / totalExecutions : 0;\n\n return { byWorkflow, totalExecutions, failureRate };\n}\n\n/** Get p50/p95 from a WorkflowStatsData entry. Durations are pre-sorted. */\nexport function getWorkflowPercentiles(entry: WorkflowStatsData['byWorkflow'][string]): {\n durationP50: number;\n durationP95: number;\n} {\n // Durations are maintained in sorted order by the reducer\n return {\n durationP50: percentile(entry.durations, 50),\n durationP95: percentile(entry.durations, 95),\n };\n}\n\n/** Enrich raw WorkflowStatsData with computed percentiles for API/WS consumers.\n * Strips the internal `durations` and `durationSum` fields to keep payloads lean. */\nexport function enrichWorkflowStats(data: WorkflowStatsData) {\n const byWorkflow: Record<\n string,\n {\n total: number;\n completed: number;\n failed: number;\n durationP50: number;\n durationP95: number;\n avgDuration: number;\n }\n > = {};\n for (const [name, entry] of Object.entries(data.byWorkflow)) {\n const { durationP50, durationP95 } = getWorkflowPercentiles(entry);\n byWorkflow[name] = {\n total: entry.total,\n completed: entry.completed,\n failed: entry.failed,\n durationP50,\n durationP95,\n avgDuration: entry.avgDuration,\n };\n }\n return {\n byWorkflow,\n totalExecutions: data.totalExecutions,\n failureRate: data.failureRate,\n };\n}\n\n// ── Trace stats reducer (AxlEvent → TraceStatsData) ────────────────\n\nexport type TraceStatsData = {\n eventTypeCounts: Record<string, number>;\n byTool: Record<string, { calls: number; denied: number; approved: number }>;\n retryByAgent: Record<string, { schema: number; validate: number; guardrail: number }>;\n totalEvents: number;\n};\n\nexport function emptyTraceStatsData(): TraceStatsData {\n return {\n eventTypeCounts: {},\n byTool: {},\n retryByAgent: {},\n totalEvents: 0,\n };\n}\n\nexport function reduceTraceStats(acc: TraceStatsData, event: AxlEvent): TraceStatsData {\n const eventTypeCounts = { ...acc.eventTypeCounts };\n eventTypeCounts[event.type] = (eventTypeCounts[event.type] ?? 0) + 1;\n\n const byTool = { ...acc.byTool };\n if (\n event.type === 'tool_call_end' ||\n event.type === 'tool_denied' ||\n event.type === 'tool_approval'\n ) {\n const toolName = event.tool;\n const prev = byTool[toolName] ?? { calls: 0, denied: 0, approved: 0 };\n // tool_denied: legacy event for \"tool not available\" path. data.approved\n // distinguishes approvals (true) from denials (absent/false).\n // tool_approval: distinct event from the approval gate with data.approved.\n const isDeniedEvent = event.type === 'tool_denied';\n const isApprovalEvent = event.type === 'tool_approval';\n const eventData =\n isDeniedEvent || isApprovalEvent\n ? (event.data as { approved?: boolean } | undefined)\n : undefined;\n const isApproved =\n (isDeniedEvent && eventData?.approved === true) ||\n (isApprovalEvent && eventData?.approved === true);\n const isDenied =\n (isDeniedEvent && !eventData?.approved) || (isApprovalEvent && eventData?.approved === false);\n byTool[toolName] = {\n calls: prev.calls + (event.type === 'tool_call_end' ? 1 : 0),\n denied: prev.denied + (isDenied ? 1 : 0),\n approved: prev.approved + (isApproved ? 1 : 0),\n };\n }\n\n const retryByAgent = { ...acc.retryByAgent };\n if (event.agent && event.type === 'agent_call_end') {\n const data = event.data as { retryReason?: string } | undefined;\n if (data?.retryReason) {\n const prev = retryByAgent[event.agent] ?? { schema: 0, validate: 0, guardrail: 0 };\n const reason = data.retryReason as 'schema' | 'validate' | 'guardrail';\n if (reason in prev) {\n retryByAgent[event.agent] = { ...prev, [reason]: prev[reason] + 1 };\n }\n }\n }\n\n return {\n eventTypeCounts,\n byTool,\n retryByAgent,\n totalEvents: acc.totalEvents + 1,\n };\n}\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\n\nexport function createHealthRoutes(readOnly: boolean) {\n const app = new Hono<StudioEnv>();\n\n app.get('/health', (c) => {\n const runtime = c.get('runtime');\n return c.json({\n ok: true,\n data: {\n status: 'healthy',\n readOnly,\n workflows: runtime.getWorkflowNames().length,\n agents: runtime.getAgents().length,\n tools: runtime.getTools().length,\n },\n });\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport { zodToJsonSchema } from '@axlsdk/axl';\nimport type { StudioEnv, WorkflowSummary } from '../types.js';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport { redactStreamEvent, redactValue } from '../redact.js';\n\nexport function createWorkflowRoutes(connMgr: ConnectionManager) {\n const app = new Hono<StudioEnv>();\n\n // List all workflows\n app.get('/workflows', (c) => {\n const runtime = c.get('runtime');\n const workflows: WorkflowSummary[] = runtime.getWorkflows().map((w) => ({\n name: w.name,\n hasInputSchema: !!w.inputSchema,\n hasOutputSchema: !!w.outputSchema,\n }));\n return c.json({ ok: true, data: workflows });\n });\n\n // Get workflow detail (including schemas)\n app.get('/workflows/:name', (c) => {\n const runtime = c.get('runtime');\n const name = c.req.param('name');\n const workflow = runtime.getWorkflow(name);\n if (!workflow) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Workflow \"${name}\" not found` } },\n 404,\n );\n }\n\n return c.json({\n ok: true,\n data: {\n name: workflow.name,\n inputSchema: workflow.inputSchema ? zodToJsonSchema(workflow.inputSchema) : null,\n outputSchema: workflow.outputSchema ? zodToJsonSchema(workflow.outputSchema) : null,\n },\n });\n });\n\n // Execute a workflow\n app.post('/workflows/:name/execute', async (c) => {\n const runtime = c.get('runtime');\n const name = c.req.param('name');\n\n const workflow = runtime.getWorkflow(name);\n if (!workflow) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Workflow \"${name}\" not found` } },\n 404,\n );\n }\n\n const body = await c.req.json<{\n input?: unknown;\n stream?: boolean;\n metadata?: Record<string, unknown>;\n }>();\n\n if (body.stream) {\n // Streaming execution — pipe events to WS channel. Under\n // `trace.redact`, scrub each StreamEvent before broadcast so\n // token deltas, tool args/results, and the final `done.data`\n // don't leak raw LLM/user content to WS subscribers.\n // TODO(PR-3-spec-16): the wire emits AxlEvent directly after PR 3 and\n // `redactStreamEvent` is replaced with an AxlEvent-aware scrubber.\n const stream = runtime.stream(name, body.input ?? {}, { metadata: body.metadata });\n const executionId = `stream-${Date.now()}`;\n const redactOn = runtime.isRedactEnabled();\n\n // Forward stream events to WS (error events flow through the iterator)\n (async () => {\n for await (const event of stream) {\n connMgr.broadcastWithWildcard(\n `execution:${executionId}`,\n redactStreamEvent(event, redactOn),\n );\n }\n })();\n\n return c.json({ ok: true, data: { executionId, streaming: true } });\n }\n\n const result = await runtime.execute(name, body.input ?? {}, { metadata: body.metadata });\n return c.json({\n ok: true,\n data: { result: redactValue(result, runtime.isRedactEnabled()) },\n });\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport { redactExecutionInfo, redactExecutionList } from '../redact.js';\n\nconst app = new Hono<StudioEnv>();\n\n// List all executions\napp.get('/executions', async (c) => {\n const runtime = c.get('runtime');\n const executions = await runtime.getExecutions();\n return c.json({\n ok: true,\n data: redactExecutionList(executions, runtime.isRedactEnabled()),\n });\n});\n\n// Get execution by ID.\n//\n// Supports `?since={step}` pagination (spec/16 §5.4) — filters\n// `events` to those with `step > since`. `step` is monotonic\n// per-execution and shared across nested asks (spec §3.7), so\n// polling clients can request only the tail since their last known\n// step without missing events from concurrent branches.\n//\n// Polling pattern: client tracks `lastStep = events[events.length - 1]?.step`\n// and passes `?since=<lastStep>` on the next poll. First poll either\n// omits `since` or passes `-1` for \"everything from step 0 onward\" —\n// `since=0` explicitly means \"I already have step 0, give me step 1+\".\n// This preserves correctness when `workflow_start` lands at step 0.\n//\n// Malformed `since` (non-integer / non-finite) returns 400 — stale or\n// buggy clients get a clear diagnostic instead of silently receiving\n// the full events array and blowing their memory budget.\napp.get('/executions/:id', async (c) => {\n const runtime = c.get('runtime');\n const id = c.req.param('id');\n const execution = await runtime.getExecution(id);\n if (!execution) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Execution \"${id}\" not found` } },\n 404,\n );\n }\n\n const sinceParam = c.req.query('since');\n let paged = execution;\n if (sinceParam !== undefined) {\n const since = Number(sinceParam);\n // Accept any finite integer, including -1 for \"everything\". Reject\n // NaN, Infinity, fractions, and non-numeric strings with a 400.\n if (!Number.isFinite(since) || !Number.isInteger(since)) {\n return c.json(\n {\n ok: false,\n error: {\n code: 'INVALID_PARAM',\n message: `\\`since\\` must be a finite integer (got \"${sinceParam}\")`,\n param: 'since',\n },\n },\n 400,\n );\n }\n paged = {\n ...execution,\n events: execution.events.filter((e) => e.step > since),\n };\n }\n\n return c.json({\n ok: true,\n data: redactExecutionInfo(paged, runtime.isRedactEnabled()),\n });\n});\n\n// Abort a running execution\napp.post('/executions/:id/abort', (c) => {\n const runtime = c.get('runtime');\n const id = c.req.param('id');\n runtime.abort(id);\n return c.json({ ok: true, data: { aborted: true } });\n});\n\nexport default app;\n","import { Hono } from 'hono';\nimport type { StudioEnv, SessionSummary } from '../types.js';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport { redactSessionHistory } from '../redact.js';\n\nexport function createSessionRoutes(connMgr: ConnectionManager) {\n const app = new Hono<StudioEnv>();\n\n // List all sessions\n app.get('/sessions', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n if (!store.listSessions) {\n return c.json({ ok: true, data: [] });\n }\n const ids = await store.listSessions();\n const sessions: SessionSummary[] = [];\n for (const id of ids) {\n const history = await store.getSession(id);\n sessions.push({ id, messageCount: history.length });\n }\n // List endpoint carries no message content — just id + count.\n // Nothing to redact.\n return c.json({ ok: true, data: sessions });\n });\n\n // Get session history\n app.get('/sessions/:id', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n const id = c.req.param('id');\n const history = await store.getSession(id);\n const handoffHistory = await store.getSessionMeta(id, 'handoffHistory');\n return c.json({\n ok: true,\n data: {\n id,\n history: redactSessionHistory(history, runtime.isRedactEnabled()),\n // HandoffRecord has no content fields (source/target/mode/\n // timestamp/duration) — nothing to scrub.\n handoffHistory: handoffHistory ?? [],\n },\n });\n });\n\n // Send message to session (non-streaming)\n app.post('/sessions/:id/send', async (c) => {\n const runtime = c.get('runtime');\n const id = c.req.param('id');\n const body = await c.req.json<{ message: string; workflow: string }>();\n\n const session = runtime.session(id);\n const result = await session.send(body.workflow, body.message);\n return c.json({ ok: true, data: { result } });\n });\n\n // Stream session message\n app.post('/sessions/:id/stream', async (c) => {\n const runtime = c.get('runtime');\n const id = c.req.param('id');\n const body = await c.req.json<{ message: string; workflow: string }>();\n\n const session = runtime.session(id);\n const stream = await session.stream(body.workflow, body.message);\n const executionId = `session-${id}-${Date.now()}`;\n\n // Forward stream events to WS (error events flow through the iterator)\n (async () => {\n for await (const event of stream) {\n connMgr.broadcastWithWildcard(`execution:${executionId}`, event);\n }\n })();\n\n return c.json({ ok: true, data: { executionId, streaming: true } });\n });\n\n // Delete session\n app.delete('/sessions/:id', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n const id = c.req.param('id');\n await store.deleteSession(id);\n return c.json({ ok: true, data: { deleted: true } });\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport { zodToJsonSchema } from '@axlsdk/axl';\nimport type { StudioEnv, AgentSummary } from '../types.js';\n\nconst app = new Hono<StudioEnv>();\n\n// List all agents\napp.get('/agents', (c) => {\n const runtime = c.get('runtime');\n const agents: AgentSummary[] = runtime.getAgents().map((a) => ({\n name: a._name,\n model: a.resolveModel(),\n system: a.resolveSystem(),\n tools: a._config.tools?.map((t) => t.name) ?? [],\n handoffs:\n typeof a._config.handoffs === 'function'\n ? ['(dynamic)']\n : (a._config.handoffs?.map((h) => h.agent._name) ?? []),\n maxTurns: a._config.maxTurns,\n temperature: a._config.temperature,\n maxTokens: a._config.maxTokens,\n effort: a._config.effort,\n thinkingBudget: a._config.thinkingBudget,\n includeThoughts: a._config.includeThoughts,\n toolChoice: a._config.toolChoice,\n stop: a._config.stop,\n }));\n return c.json({ ok: true, data: agents });\n});\n\n// Get agent detail\napp.get('/agents/:name', (c) => {\n const runtime = c.get('runtime');\n const name = c.req.param('name');\n const agent = runtime.getAgent(name);\n if (!agent) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Agent \"${name}\" not found` } },\n 404,\n );\n }\n\n const cfg = agent._config;\n return c.json({\n ok: true,\n data: {\n name: agent._name,\n model: agent.resolveModel(),\n system: agent.resolveSystem(),\n tools:\n cfg.tools?.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: zodToJsonSchema(t.inputSchema),\n })) ?? [],\n handoffs:\n typeof cfg.handoffs === 'function'\n ? [\n {\n agent: '(dynamic)',\n description: 'Resolved at runtime from metadata',\n mode: 'oneway' as const,\n },\n ]\n : (cfg.handoffs?.map((h) => ({\n agent: h.agent._name,\n description: h.description,\n mode: h.mode ?? 'oneway',\n })) ?? []),\n maxTurns: cfg.maxTurns,\n temperature: cfg.temperature,\n maxTokens: cfg.maxTokens,\n effort: cfg.effort,\n thinkingBudget: cfg.thinkingBudget,\n includeThoughts: cfg.includeThoughts,\n toolChoice: cfg.toolChoice,\n stop: cfg.stop,\n timeout: cfg.timeout,\n maxContext: cfg.maxContext,\n version: cfg.version,\n mcp: cfg.mcp,\n mcpTools: cfg.mcpTools,\n hasGuardrails: !!cfg.guardrails,\n guardrails: cfg.guardrails\n ? {\n hasInput: !!cfg.guardrails.input,\n hasOutput: !!cfg.guardrails.output,\n onBlock: cfg.guardrails.onBlock ?? 'throw',\n maxRetries: cfg.guardrails.maxRetries,\n }\n : null,\n },\n });\n});\n\nexport default app;\n","import { Hono } from 'hono';\nimport { zodToJsonSchema } from '@axlsdk/axl';\nimport type { StudioEnv, ToolSummary } from '../types.js';\nimport { redactValue } from '../redact.js';\n\nconst app = new Hono<StudioEnv>();\n\n// List all tools\napp.get('/tools', (c) => {\n const runtime = c.get('runtime');\n const tools: ToolSummary[] = runtime.getTools().map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema ? zodToJsonSchema(t.inputSchema) : {},\n sensitive: t.sensitive ?? false,\n requireApproval: t.requireApproval ?? false,\n }));\n return c.json({ ok: true, data: tools });\n});\n\n// Get tool detail\napp.get('/tools/:name', (c) => {\n const runtime = c.get('runtime');\n const name = c.req.param('name');\n const tool = runtime.getTool(name);\n if (!tool) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Tool \"${name}\" not found` } },\n 404,\n );\n }\n\n return c.json({\n ok: true,\n data: {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema ? zodToJsonSchema(tool.inputSchema) : {},\n sensitive: tool.sensitive,\n requireApproval: tool.requireApproval,\n retry: tool.retry,\n hasHooks: !!tool.hooks,\n hooks: tool.hooks\n ? {\n hasBefore: !!tool.hooks.before,\n hasAfter: !!tool.hooks.after,\n }\n : null,\n },\n });\n});\n\n// Test a tool directly\napp.post('/tools/:name/test', async (c) => {\n const runtime = c.get('runtime');\n const name = c.req.param('name');\n const tool = runtime.getTool(name);\n if (!tool) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Tool \"${name}\" not found` } },\n 404,\n );\n }\n\n const body = await c.req.json<{ input: unknown }>();\n const ctx = runtime.createContext();\n const result = await tool.run(ctx, body.input);\n return c.json({\n ok: true,\n data: { result: redactValue(result, runtime.isRedactEnabled()) },\n });\n});\n\nexport default app;\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport { redactMemoryList, redactMemoryValue } from '../redact.js';\n\nconst app = new Hono<StudioEnv>();\n\n// Get all memory entries for a scope\napp.get('/memory/:scope', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n const scope = c.req.param('scope');\n\n if (!store.getAllMemory) {\n return c.json({ ok: true, data: [] });\n }\n\n const entries = await store.getAllMemory(scope);\n return c.json({ ok: true, data: redactMemoryList(entries, runtime.isRedactEnabled()) });\n});\n\n// Get a specific memory entry\napp.get('/memory/:scope/:key', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n const scope = c.req.param('scope');\n const key = c.req.param('key');\n\n if (!store.getMemory) {\n return c.json(\n { ok: false, error: { code: 'NOT_SUPPORTED', message: 'Memory not supported' } },\n 501,\n );\n }\n\n const value = await store.getMemory(scope, key);\n if (value === null) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Memory \"${scope}/${key}\" not found` } },\n 404,\n );\n }\n\n return c.json({\n ok: true,\n data: { key, value: redactMemoryValue(value, runtime.isRedactEnabled()) },\n });\n});\n\n// Save a memory entry\napp.put('/memory/:scope/:key', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n const scope = c.req.param('scope');\n const key = c.req.param('key');\n\n if (!store.saveMemory) {\n return c.json(\n { ok: false, error: { code: 'NOT_SUPPORTED', message: 'Memory not supported' } },\n 501,\n );\n }\n\n const body = await c.req.json<{ value: unknown }>();\n await store.saveMemory(scope, key, body.value);\n return c.json({ ok: true, data: { saved: true } });\n});\n\n// Delete a memory entry\napp.delete('/memory/:scope/:key', async (c) => {\n const runtime = c.get('runtime');\n const store = runtime.getStateStore();\n const scope = c.req.param('scope');\n const key = c.req.param('key');\n\n if (!store.deleteMemory) {\n return c.json(\n { ok: false, error: { code: 'NOT_SUPPORTED', message: 'Memory not supported' } },\n 501,\n );\n }\n\n await store.deleteMemory(scope, key);\n return c.json({ ok: true, data: { deleted: true } });\n});\n\n// Semantic search\napp.post('/memory/search', async (c) => {\n // TODO: Connect to MemoryManager's vector search once exposed\n return c.json({\n ok: true,\n data: { results: [], message: 'Semantic search requires MemoryManager with vector store' },\n });\n});\n\nexport default app;\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport { redactPendingDecisionList } from '../redact.js';\n\nconst app = new Hono<StudioEnv>();\n\n// List pending decisions\napp.get('/decisions', async (c) => {\n const runtime = c.get('runtime');\n const decisions = await runtime.getPendingDecisions();\n return c.json({\n ok: true,\n data: redactPendingDecisionList(decisions, runtime.isRedactEnabled()),\n });\n});\n\n// Resolve a pending decision\napp.post('/decisions/:executionId/resolve', async (c) => {\n const runtime = c.get('runtime');\n const executionId = c.req.param('executionId');\n const body = await c.req.json<{ approved: boolean; reason?: string }>();\n\n await runtime.resolveDecision(executionId, body);\n return c.json({ ok: true, data: { resolved: true } });\n});\n\nexport default app;\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport type { TraceAggregator } from '../aggregates/trace-aggregator.js';\nimport type { CostData } from '../types.js';\nimport { parseWindowParam } from '../aggregates/aggregate-snapshots.js';\n\nexport function createCostRoutes(costAggregator: TraceAggregator<CostData>) {\n const app = new Hono<StudioEnv>();\n\n app.get('/costs', (c) => {\n // Multi-window debug mode\n if (c.req.query('windows') === 'all') {\n return c.json({ ok: true, data: costAggregator.getAllSnapshots() });\n }\n\n const window = parseWindowParam(c.req.query('window'));\n return c.json({ ok: true, data: costAggregator.getSnapshot(window) });\n });\n\n // Migration stub for the removed `POST /api/costs/reset` endpoint.\n //\n // Pre-0.15 Studio exposed a mutating reset that cleared the in-memory cost\n // aggregator. In 0.15 the dashboard switched to time-window aggregates over\n // StateStore history, so \"reset\" is no longer meaningful — the displayed\n // window simply narrows. Scripts (CI dashboards, ops tooling) that still hit\n // this URL would otherwise get Hono's default 404 with no hint about the\n // migration path. Return a structured 410 Gone with a concrete pointer.\n app.post('/costs/reset', (c) => {\n return c.json(\n {\n ok: false,\n error: {\n code: 'GONE',\n message:\n 'POST /api/costs/reset was removed in @axlsdk/studio 0.15. ' +\n 'Cost aggregates are now time-windowed and rebuilt from StateStore history. ' +\n 'Use GET /api/costs?window=24h|7d|30d|all to narrow the view instead of resetting.',\n },\n },\n 410,\n );\n });\n\n return app;\n}\n","import { randomUUID } from 'node:crypto';\nimport { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport type { EvalResult, Scorer } from '@axlsdk/eval';\nimport { redactEvalHistoryList, redactEvalResult, redactErrorMessage } from '../redact.js';\n\nexport function createEvalRoutes(connMgr: ConnectionManager, evalLoader?: () => Promise<void>) {\n const app = new Hono<StudioEnv>();\n\n // Active streaming eval runs, keyed by evalRunId. Scoped per-middleware\n // instance so multiple `createStudioMiddleware()` mounts in the same process\n // (multi-tenant deployments, concurrent unit tests) don't collide on run IDs\n // or leak AbortControllers across middleware lifecycles.\n const activeRuns = new Map<string, AbortController>();\n\n // List registered eval configs\n app.get('/evals', async (c) => {\n if (evalLoader) await evalLoader();\n const runtime = c.get('runtime');\n const evals = runtime.getRegisteredEvals();\n // Registered eval configs contain dataset definitions — the dataset\n // `.getItems()` contents aren't serialized in this response (we just\n // return names + scorer list), so there's no raw content to scrub.\n return c.json({ ok: true, data: evals });\n });\n\n // Get eval run history\n app.get('/evals/history', async (c) => {\n const runtime = c.get('runtime');\n const history = await runtime.getEvalHistory();\n return c.json({\n ok: true,\n data: redactEvalHistoryList(history, runtime.isRedactEnabled()),\n });\n });\n\n // Delete a single eval history entry by id.\n app.delete('/evals/history/:id', async (c) => {\n const runtime = c.get('runtime');\n const id = c.req.param('id');\n const deleted = await runtime.deleteEvalResult(id);\n if (!deleted) {\n return c.json(\n {\n ok: false,\n error: { code: 'NOT_FOUND', message: `Eval history entry \"${id}\" not found` },\n },\n 404,\n );\n }\n return c.json({ ok: true, data: { id, deleted: true } });\n });\n\n // Run a registered eval by name.\n //\n // Body options:\n // runs?: number — multi-run count (capped at 25)\n // stream?: true — return evalRunId immediately, broadcast progress via WS\n //\n // When stream is false/absent, the endpoint blocks until the eval completes\n // and returns the full result (backward compatible).\n app.post('/evals/:name/run', async (c) => {\n if (evalLoader) await evalLoader();\n const runtime = c.get('runtime');\n const name = c.req.param('name');\n const redactOn = runtime.isRedactEnabled();\n\n const entry = runtime.getRegisteredEval(name);\n if (!entry) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Eval \"${name}\" not found` } },\n 404,\n );\n }\n\n let runs = 1;\n let stream = false;\n let captureTraces = false;\n try {\n const body = (await c.req.json().catch(() => ({}))) as Record<string, unknown>;\n if (typeof body.runs === 'number' && Number.isFinite(body.runs) && body.runs > 1) {\n runs = Math.min(Math.floor(body.runs), 25);\n }\n if (body.stream === true) {\n stream = true;\n }\n if (body.captureTraces === true) {\n captureTraces = true;\n }\n } catch {\n // No body or invalid body — single run, synchronous\n }\n\n // ── Streaming mode ─────────────────────────────────────────────\n if (stream) {\n const evalRunId = `eval-${randomUUID()}`;\n const ac = new AbortController();\n activeRuns.set(evalRunId, ac);\n\n // Fire-and-forget async execution with WS progress broadcasting.\n //\n // NOTE on the done event shape: we deliberately broadcast only a\n // pointer (`evalResultId`, optional `runGroupId`) instead of the\n // full `EvalResult`. A real eval result with ~12 items, per-item\n // score details, and metadata easily exceeds 64KB, which is our\n // WS frame budget. When we previously embedded the whole result,\n // `truncateIfOversized` replaced it with a `{__truncated}` stub\n // and the client rendered a blank screen.\n //\n // Architecturally: WS events are for small notifications,\n // `runRegisteredEval` already persists results to history via the\n // StateStore, and the client can fetch the full payload from\n // `GET /api/evals/history` once notified. This matches the hint\n // text that the truncation placeholder already used to emit.\n (async () => {\n try {\n if (runs > 1) {\n const runGroupId = randomUUID();\n const results: EvalResult[] = [];\n\n for (let r = 0; r < runs; r++) {\n if (ac.signal.aborted) break;\n const result = (await runtime.runRegisteredEval(name, {\n metadata: { runGroupId, runIndex: r },\n signal: ac.signal,\n captureTraces,\n onProgress: (event) => {\n // Library-level `run_done` fires after every iteration with\n // `{ totalItems, failures }`; Studio emits its own wire-level\n // `run_done` below with `{ run, totalRuns }` semantics, so we\n // drop the library variant to avoid collision on the client.\n if (event.type === 'run_done') return;\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {\n ...event,\n run: r + 1,\n totalRuns: runs,\n });\n },\n })) as EvalResult;\n results.push(result);\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {\n type: 'run_done',\n run: r + 1,\n totalRuns: runs,\n });\n }\n\n if (results.length > 0) {\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {\n type: 'done',\n evalResultId: results[0].id,\n runGroupId,\n });\n } else {\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {\n type: 'error',\n message: 'All runs were cancelled',\n });\n }\n } else {\n const result = (await runtime.runRegisteredEval(name, {\n signal: ac.signal,\n captureTraces,\n onProgress: (event) => {\n // Drop library-level `run_done` — Studio's terminal signal for\n // single-run streams is the `done` event below, which carries\n // the `evalResultId` pointer the client uses to refetch.\n if (event.type === 'run_done') return;\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, event);\n },\n })) as EvalResult;\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {\n type: 'done',\n evalResultId: result.id,\n });\n }\n } catch (err) {\n // Eval-channel error event shape is NOT a `StreamEvent`, so it\n // doesn't pass through `redactStreamEvent`. Scrub the message\n // inline so ValidationError/GuardrailError/provider errors don't\n // leak user input on the eval:* channel under redact mode.\n // (StreamEvent itself is legacy — see TODO in redact.ts.)\n connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {\n type: 'error',\n message: redactErrorMessage(err, redactOn),\n });\n } finally {\n activeRuns.delete(evalRunId);\n }\n })();\n\n return c.json({ ok: true, data: { evalRunId } });\n }\n\n // ── Synchronous mode (backward compatible) ─────────────────────\n try {\n if (runs > 1) {\n const { aggregateRuns } = await import('@axlsdk/eval');\n const runGroupId = randomUUID();\n const results = [];\n for (let r = 0; r < runs; r++) {\n const result = await runtime.runRegisteredEval(name, {\n metadata: { runGroupId, runIndex: r },\n captureTraces,\n });\n results.push(result);\n }\n const typedResults = results as EvalResult[];\n const aggregate = aggregateRuns(typedResults);\n const first = typedResults[0]!;\n const result = {\n ...first,\n _multiRun: { aggregate, allRuns: typedResults },\n } as EvalResult;\n return c.json({\n ok: true,\n data: redactEvalResult(result, redactOn),\n });\n } else {\n // Runtime persists eval result to history automatically\n const result = (await runtime.runRegisteredEval(name, { captureTraces })) as EvalResult;\n return c.json({\n ok: true,\n data: redactEvalResult(result, redactOn),\n });\n }\n } catch (err) {\n // Inline error envelope — scrub to keep redaction semantics\n // consistent with the global `errorHandler` middleware.\n return c.json(\n { ok: false, error: { code: 'EVAL_ERROR', message: redactErrorMessage(err, redactOn) } },\n 400,\n );\n }\n });\n\n // Cancel an active streaming eval run.\n app.post('/evals/runs/:evalRunId/cancel', (c) => {\n const evalRunId = c.req.param('evalRunId');\n const ac = activeRuns.get(evalRunId);\n if (!ac) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: 'No active eval run found' } },\n 404,\n );\n }\n ac.abort();\n activeRuns.delete(evalRunId);\n return c.json({ ok: true, data: { cancelled: true } });\n });\n\n // Rescore: re-run scorers on saved outputs\n app.post('/evals/:name/rescore', async (c) => {\n if (evalLoader) await evalLoader();\n const runtime = c.get('runtime');\n const redactOn = runtime.isRedactEnabled();\n const name = c.req.param('name');\n const body = await c.req.json<{ resultId: string }>();\n\n if (!body.resultId || typeof body.resultId !== 'string') {\n return c.json(\n { ok: false, error: { code: 'BAD_REQUEST', message: 'resultId is required' } },\n 400,\n );\n }\n\n const entry = runtime.getRegisteredEval(name);\n if (!entry) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Eval \"${name}\" not found` } },\n 404,\n );\n }\n\n const history = await runtime.getEvalHistory();\n const historyEntry = history.find((h) => h.id === body.resultId);\n if (!historyEntry) {\n return c.json(\n { ok: false, error: { code: 'NOT_FOUND', message: `Result \"${body.resultId}\" not found` } },\n 404,\n );\n }\n\n try {\n const { rescore } = await import('@axlsdk/eval');\n const config = entry.config as { scorers?: unknown[] };\n const result = await rescore(\n historyEntry.data as EvalResult,\n config.scorers as Scorer[],\n runtime,\n );\n await runtime.saveEvalResult({\n id: result.id,\n eval: name,\n timestamp: Date.now(),\n data: result,\n });\n return c.json({\n ok: true,\n data: redactEvalResult(result, redactOn),\n });\n } catch (err) {\n return c.json(\n { ok: false, error: { code: 'EVAL_ERROR', message: redactErrorMessage(err, redactOn) } },\n 400,\n );\n }\n });\n\n // Compare eval results by history ID.\n //\n // Accepts baselineId/candidateId as string (single run) or string[] (pooled\n // multi-run group). IDs are resolved from runtime history server-side so the\n // wire payload stays tiny — this avoids hitting host body-parser limits when\n // Studio is mounted as middleware behind Express/NestJS/Fastify.\n app.post('/evals/compare', async (c) => {\n const runtime = c.get('runtime');\n const redactOn = runtime.isRedactEnabled();\n const body = await c.req.json<{\n baselineId: string | string[];\n candidateId: string | string[];\n options?: { thresholds?: Record<string, number> | number };\n }>();\n\n // Validate ID shapes up front. Each side must be a non-empty string or a\n // non-empty array of non-empty strings. `!body.baselineId` would treat\n // `[]` as truthy, so check explicitly. We also reject arrays that contain\n // any non-string element (e.g. `[null]`), which would otherwise produce a\n // confusing \"Eval result(s) not found in history: null\" error downstream.\n //\n // DoS cap (reviewer HIGH H1): `evalCompare` pools items across all runs\n // for paired bootstrap CI (1000 resamples). An unbounded array lets a\n // readOnly attacker run 500-run × 100-item × 1000-resample comparisons\n // on each request. Cap at 25 to match the multi-run ceiling on\n // `POST /api/evals/:name/run`.\n const MAX_POOLED_RUNS = 25;\n const validateIdParam = (v: unknown, name: string): string | null => {\n if (typeof v === 'string') return v === '' ? `${name} must be non-empty` : null;\n if (Array.isArray(v)) {\n if (v.length === 0) return `${name} must be a non-empty array`;\n if (v.length > MAX_POOLED_RUNS) {\n return `${name} may contain at most ${MAX_POOLED_RUNS} ids (pooled comparison)`;\n }\n for (const elem of v) {\n if (typeof elem !== 'string' || elem === '') {\n return `${name} array must contain only non-empty strings`;\n }\n }\n return null;\n }\n return `${name} is required (string or string[])`;\n };\n const baselineErr = validateIdParam(body.baselineId, 'baselineId');\n const candidateErr = validateIdParam(body.candidateId, 'candidateId');\n if (baselineErr || candidateErr) {\n return c.json(\n {\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: [baselineErr, candidateErr].filter(Boolean).join('; '),\n },\n },\n 400,\n );\n }\n\n const history = await runtime.getEvalHistory();\n const byId = new Map(history.map((h) => [h.id, h.data as EvalResult]));\n\n const missing: string[] = [];\n const resolveOne = (id: string): EvalResult | undefined => {\n const data = byId.get(id);\n if (!data) missing.push(id);\n return data;\n };\n const resolveSelection = (\n idOrIds: string | string[],\n ): EvalResult | EvalResult[] | undefined => {\n if (Array.isArray(idOrIds)) {\n // Dedupe so callers passing [id, id] don't artificially shrink the\n // paired-bootstrap variance in downstream CI computation.\n const unique = Array.from(new Set(idOrIds));\n // Single-element groups are semantically equivalent to a single ID;\n // unwrap so evalCompare uses the simpler single-result code path\n // instead of the multi-run pooling path with one run.\n if (unique.length === 1) return resolveOne(unique[0]);\n const results: EvalResult[] = [];\n for (const id of unique) {\n const data = resolveOne(id);\n if (data) results.push(data);\n }\n return results;\n }\n return resolveOne(idOrIds);\n };\n\n const baseline = resolveSelection(body.baselineId);\n const candidate = resolveSelection(body.candidateId);\n\n if (missing.length > 0) {\n return c.json(\n {\n ok: false,\n error: {\n code: 'NOT_FOUND',\n message: `Eval result(s) not found in history: ${missing.join(', ')}`,\n },\n },\n 404,\n );\n }\n\n try {\n // `missing.length === 0` guarantees both are defined here.\n const result = await runtime.evalCompare(baseline!, candidate!, body.options);\n return c.json({ ok: true, data: result });\n } catch (err) {\n return c.json(\n {\n ok: false,\n error: { code: 'COMPARE_FAILED', message: redactErrorMessage(err, redactOn) },\n },\n 400,\n );\n }\n });\n\n // Import a CLI eval artifact into runtime history.\n //\n // Accepts a parsed EvalResult JSON (typically produced by `axl-eval --output`).\n // Generates a fresh UUID for the history entry (overwriting result.id) so\n // repeated imports of the same file don't collide. The imported entry is\n // indistinguishable from a natively-run result in the history picker, run\n // detail view, and comparison flows.\n //\n // Note: this is the one Studio endpoint whose request bodies can be large.\n // If mounted as middleware and importing sizeable eval files, raise the\n // host framework's JSON body limit on the Studio mount.\n app.post('/evals/import', async (c) => {\n const runtime = c.get('runtime');\n const body = await c.req.json<{\n result: unknown;\n eval?: string;\n }>();\n\n const bad = (message: string) =>\n c.json({ ok: false, error: { code: 'BAD_REQUEST', message } }, 400);\n\n if (!body.result || typeof body.result !== 'object') {\n return bad('result is required');\n }\n\n const result = body.result as Record<string, unknown>;\n\n // Shape validation — catch obvious garbage early with a clear error,\n // rather than letting downstream compare/rescore throw with a confusing\n // stack. Keep the check narrow: verify the fields Studio actually reads.\n if (!Array.isArray(result.items)) {\n return bad('result.items must be an array');\n }\n if (typeof result.summary !== 'object' || result.summary == null) {\n return bad('result.summary must be an object');\n }\n if (typeof result.dataset !== 'string' || !result.dataset) {\n return bad('result.dataset must be a non-empty string (required for compare)');\n }\n const summary = result.summary as Record<string, unknown>;\n if (typeof summary.scorers !== 'object' || summary.scorers == null) {\n return bad('result.summary.scorers must be an object');\n }\n const summaryScorerNames = Object.keys(summary.scorers as Record<string, unknown>);\n\n // Verify that per-item score keys are covered by summary.scorers across\n // ALL items — a heterogeneous artifact where item[0] is well-formed but\n // item[N] references unknown scorers would otherwise break compare\n // downstream with a cryptic error.\n const items = result.items as Array<Record<string, unknown>>;\n const summaryScorerSet = new Set(summaryScorerNames);\n const uncoveredAcrossItems = new Set<string>();\n for (const item of items) {\n const itemScores = item?.scores;\n if (itemScores && typeof itemScores === 'object') {\n for (const name of Object.keys(itemScores as Record<string, unknown>)) {\n if (!summaryScorerSet.has(name)) uncoveredAcrossItems.add(name);\n }\n }\n }\n if (uncoveredAcrossItems.size > 0) {\n return bad(\n `item scores reference scorer(s) not in summary.scorers: ${[...uncoveredAcrossItems].join(', ')}`,\n );\n }\n\n // EvalResult has no eval-name field of its own — the name lives on the\n // history entry. Prefer an explicit body.eval (client may know the\n // registered eval name), then fall back to the first workflow observed\n // in metadata.workflows (primary workflow of the run), then to the\n // legacy top-level workflow field for pre-0.14 CLI artifacts, then to\n // a generic label.\n //\n // Normalize via trim() to reject strings that are whitespace-only or\n // empty (would otherwise silently fall through to the next branch).\n const trim = (v: unknown): string | undefined =>\n typeof v === 'string' && v.trim() !== '' ? v.trim() : undefined;\n\n // metadata.workflows is the canonical source post-0.14.\n const metadataObj =\n typeof result.metadata === 'object' && result.metadata != null\n ? (result.metadata as Record<string, unknown>)\n : {};\n const workflowsFromMeta = Array.isArray(metadataObj.workflows)\n ? (metadataObj.workflows as unknown[])\n : [];\n const primaryWorkflow = workflowsFromMeta.find((w): w is string => typeof w === 'string');\n\n const evalName =\n trim(body.eval) ??\n trim(primaryWorkflow) ??\n // Legacy fallback: pre-0.14 CLI artifacts had workflow at the top level.\n trim((result as { workflow?: unknown }).workflow) ??\n 'imported';\n\n const id = randomUUID();\n const timestamp = Date.now();\n\n // Overwrite id so repeated imports of the same file get distinct entries.\n // Default metadata to {} since downstream code assumes it exists\n // (e.g. evalCompare reads metadata.scorerTypes).\n const imported: EvalResult = {\n ...(result as unknown as EvalResult),\n id,\n metadata:\n typeof result.metadata === 'object' && result.metadata != null\n ? (result.metadata as Record<string, unknown>)\n : {},\n };\n\n await runtime.saveEvalResult({\n id,\n eval: evalName,\n timestamp,\n data: imported,\n });\n\n return c.json({ ok: true, data: { id, eval: evalName, timestamp } });\n });\n\n function closeActiveRuns() {\n for (const ac of activeRuns.values()) ac.abort();\n activeRuns.clear();\n }\n\n return { app, closeActiveRuns };\n}\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport type { ConnectionManager } from '../ws/connection-manager.js';\nimport { redactStreamEvent } from '../redact.js';\nimport type { AxlEvent } from '@axlsdk/axl';\n\nexport function createPlaygroundRoutes(connMgr: ConnectionManager) {\n const app = new Hono<StudioEnv>();\n\n // Chat with an agent directly — no workflow required\n app.post('/playground/chat', async (c) => {\n const runtime = c.get('runtime');\n const body = await c.req.json<{\n sessionId?: string;\n message: string;\n agent?: string;\n }>();\n\n if (!body.message || typeof body.message !== 'string' || !body.message.trim()) {\n return c.json(\n {\n ok: false,\n error: {\n code: 'INVALID_INPUT',\n message: 'message is required and must be a non-empty string',\n },\n },\n 400,\n );\n }\n\n const agents = runtime.getAgents();\n const agent = body.agent ? agents.find((a) => a._name === body.agent) : agents[0];\n if (!agent) {\n return c.json(\n {\n ok: false,\n error: { code: 'NO_AGENT', message: `Agent \"${body.agent ?? ''}\" not found` },\n },\n 400,\n );\n }\n\n const sessionId = body.sessionId ?? `playground-${Date.now()}`;\n const store = runtime.getStateStore();\n\n // Load session history for multi-turn conversations\n const history = await store.getSession(sessionId);\n history.push({ role: 'user', content: body.message });\n\n const redactOn = runtime.isRedactEnabled();\n\n // Create context — its auto-generated executionId becomes the WS channel name.\n // Token events flow through emitEvent → runtime.emit('trace') → our listener below,\n // so no manual onToken needed.\n const ctx = runtime.createContext({ sessionHistory: history });\n const executionId = ctx.executionId;\n\n // Forward ALL AxlEvents from this execution to the WS channel.\n // This gives the playground UI access to ask_start, agent_call, tool_call,\n // handoff, pipeline, etc. — not just tokens.\n const traceListener = (event: AxlEvent) => {\n if (event.executionId !== executionId) return;\n connMgr.broadcastWithWildcard(`execution:${executionId}`, redactStreamEvent(event, redactOn));\n };\n runtime.on('trace', traceListener);\n\n // Run the agent ask asynchronously, stream results via WS\n (async () => {\n let stepCounter = Number.MAX_SAFE_INTEGER - 1;\n const terminalFields = () => ({\n executionId,\n step: stepCounter++,\n timestamp: Date.now(),\n });\n\n try {\n const result = await ctx.ask(agent, body.message);\n const resultText = typeof result === 'string' ? result : JSON.stringify(result);\n\n history.push({ role: 'assistant', content: resultText });\n await store.saveSession(sessionId, history);\n\n const doneEvent: AxlEvent = {\n ...terminalFields(),\n type: 'done',\n data: { result: resultText },\n };\n connMgr.broadcastWithWildcard(\n `execution:${executionId}`,\n redactStreamEvent(doneEvent, redactOn),\n );\n } catch (err) {\n const errorEvent: AxlEvent = {\n ...terminalFields(),\n type: 'error',\n data: { message: err instanceof Error ? err.message : String(err) },\n };\n connMgr.broadcastWithWildcard(\n `execution:${executionId}`,\n redactStreamEvent(errorEvent, redactOn),\n );\n } finally {\n runtime.off('trace', traceListener);\n }\n })();\n\n return c.json({\n ok: true,\n data: { sessionId, executionId, streaming: true },\n });\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport type { EvalAggregator } from '../aggregates/eval-aggregator.js';\nimport type { EvalTrendData } from '../aggregates/reducers.js';\nimport { parseWindowParam } from '../aggregates/aggregate-snapshots.js';\n\nexport function createEvalTrendsRoutes(aggregator: EvalAggregator<EvalTrendData>) {\n const app = new Hono<StudioEnv>();\n\n app.get('/eval-trends', (c) => {\n const window = parseWindowParam(c.req.query('window'));\n return c.json({ ok: true, data: aggregator.getSnapshot(window) });\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport type { ExecutionAggregator } from '../aggregates/execution-aggregator.js';\nimport type { WorkflowStatsData } from '../aggregates/reducers.js';\nimport { enrichWorkflowStats } from '../aggregates/reducers.js';\nimport { parseWindowParam } from '../aggregates/aggregate-snapshots.js';\n\nexport function createWorkflowStatsRoutes(aggregator: ExecutionAggregator<WorkflowStatsData>) {\n const app = new Hono<StudioEnv>();\n\n app.get('/workflow-stats', (c) => {\n const window = parseWindowParam(c.req.query('window'));\n return c.json({ ok: true, data: enrichWorkflowStats(aggregator.getSnapshot(window)) });\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { StudioEnv } from '../types.js';\nimport type { TraceAggregator } from '../aggregates/trace-aggregator.js';\nimport type { TraceStatsData } from '../aggregates/reducers.js';\nimport { parseWindowParam } from '../aggregates/aggregate-snapshots.js';\n\nexport function createTraceStatsRoutes(aggregator: TraceAggregator<TraceStatsData>) {\n const app = new Hono<StudioEnv>();\n\n app.get('/trace-stats', (c) => {\n const window = parseWindowParam(c.req.query('window'));\n return c.json({ ok: true, data: aggregator.getSnapshot(window) });\n });\n\n return app;\n}\n"],"mappings":"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","names":["Hono","byWorkflow","app","Hono","app","Hono","Hono","Hono","Hono","app","Hono","Hono","zodToJsonSchema","app","Hono","zodToJsonSchema","app","Hono","zodToJsonSchema","Hono","app","Hono","Hono","app","Hono","Hono","app","Hono","Hono","app","Hono","result","Hono","app","Hono","Hono","app","Hono","Hono","app","Hono","Hono","app","Hono","app","Hono"]}
|