@w6w/ui 0.2.56 → 0.2.57
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/CHANGELOG.md +8 -0
- package/dist/CallTargetForm.d.ts +10 -0
- package/dist/{CodeBlock-CymlfyeA.cjs → CodeBlock-BSX1pi6W.cjs} +2 -2
- package/dist/{CodeBlock-CymlfyeA.cjs.map → CodeBlock-BSX1pi6W.cjs.map} +1 -1
- package/dist/{CodeBlock-C-oIIYfC.js → CodeBlock-CPKXSNEs.js} +7 -3
- package/dist/{CodeBlock-C-oIIYfC.js.map → CodeBlock-CPKXSNEs.js.map} +1 -1
- package/dist/CodeEditor.d.ts +2 -0
- package/dist/JsonEditor.d.ts +1 -3
- package/dist/Markdown.d.ts +3 -1
- package/dist/StepBuilderModal.d.ts +2 -3
- package/dist/TriggerSampleButton.d.ts +11 -0
- package/dist/WorkflowFlowEditor.d.ts +48 -0
- package/dist/YamlEditor.d.ts +1 -2
- package/dist/callable-fields.d.ts +4 -0
- package/dist/code.cjs +1 -1
- package/dist/code.mjs +1 -1
- package/dist/components/ConfirmModal.d.ts +7 -1
- package/dist/components/DataEntryList.d.ts +2 -0
- package/dist/components/ResultViewer.d.ts +1 -2
- package/dist/connection-app-meta-BeYDm-cs.cjs +24 -0
- package/dist/connection-app-meta-BeYDm-cs.cjs.map +1 -0
- package/dist/{connection-app-meta-ZCPakGjD.js → connection-app-meta-aURFNTx_.js} +6115 -5806
- package/dist/connection-app-meta-aURFNTx_.js.map +1 -0
- package/dist/flow.cjs +4 -3
- package/dist/flow.cjs.map +1 -1
- package/dist/flow.mjs +1820 -1753
- package/dist/flow.mjs.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +306 -305
- package/dist/index.mjs.map +1 -1
- package/dist/provider.d.ts +3 -0
- package/package.json +2 -1
- package/src/code.css +24 -0
- package/src/styles/_code-editor.scss +16 -0
- package/src/styles/_copyable.scss +22 -0
- package/src/styles/_data-vars.scss +11 -0
- package/src/styles.css +54 -0
- package/dist/connection-app-meta-BEXlKBgV.cjs +0 -22
- package/dist/connection-app-meta-BEXlKBgV.cjs.map +0 -1
- package/dist/connection-app-meta-ZCPakGjD.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/createW6WApi.ts","../src/components/ListItem.tsx","../src/ActionTestForm.tsx","../src/YamlEditor.tsx","../src/components/CopyableText.tsx","../src/components/HealthStatusPill.tsx","../src/components/UptimeStrip.tsx","../src/components/server-resources-format.ts","../src/components/ServerResources.tsx","../src/components/history-scale.ts","../src/components/HistoryTimeline.tsx","../src/components/InfoTip.tsx","../src/components/EditButton.tsx","../src/components/RepoSyncIndicator.tsx","../src/components/StepStatusPill.tsx","../src/components/execution-format.ts","../src/components/ExecutionList.tsx","../src/components/ExecutionLogPanel.tsx","../src/components/ExecutionFilters.tsx","../src/components/ExecutionStats.tsx","../src/components/ExecutionDetail.tsx","../src/reliability-board-layout.ts","../src/components/ReliabilityChart.tsx","../src/components/ReliabilityList.tsx","../src/components/DataTable.tsx","../src/components/EmptyState.tsx","../src/components/CallableList.tsx","../src/components/ConnectionList.tsx","../src/EditConnectionModal.tsx","../src/ConnectionHeader.tsx","../src/components/BudgetMeter.tsx","../src/data-stores/data-store-view.ts","../src/components/DataStoreList.tsx","../src/components/ColumnsEditor.tsx","../src/components/CsvPanel.tsx","../src/components/DataEntryList.tsx","../src/components/DataEntryEditor.tsx","../src/components/DataTableGrid.tsx"],"sourcesContent":["/**\n * Default fetch-based W6WApi client. Convenience for partners without their\n * own HTTP client — studio wires react-query around its own implementation\n * and doesn't use this. Every method calls the w6w server directly and\n * throws `ApiError` on non-OK responses so callers can surface the message.\n */\nimport type { NodeSample } from \"./node-samples.ts\";\nimport type { StepMeta, StepTest, TestRunSummary, W6WApi } from \"./provider.tsx\";\nimport type { NodeTestInput } from \"./test-inputs.ts\";\nimport type {\n ActionDef,\n ApiCallRecord,\n AppSummary,\n AuthDef,\n ConnectionSummary,\n CredentialDependents,\n CredentialSummary,\n CredentialTestResult,\n FunctionDetail,\n FunctionSummary,\n SavedTest,\n WorkflowDetail,\n WorkflowSummary,\n} from \"./types.ts\";\n\nexport interface CreateW6WApiOptions {\n /** Absolute URL or path prefix — e.g. `\"https://w6w.example.com\"` or `\"/api\"`. */\n baseUrl: string;\n /**\n * Bearer token to send. Accepts a string (static) or a supplier function so\n * a JWT that rotates on refresh is fetched fresh on every request. The\n * supplier may be sync or return a `Promise` — either way it is awaited\n * once per request. It receives an optional `{ forceRefresh? }` ctx arg\n * (unused by this client today, but part of the shape so a caller's\n * supplier can share one implementation with `@w6w/sdk`'s `TokenProvider`).\n */\n token?:\n | string\n | ((ctx?: { forceRefresh?: boolean }) =>\n | string\n | null\n | undefined\n | Promise<string | null | undefined>);\n /** Optional fetch replacement — handy for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nexport class ApiError extends Error {\n status: number;\n code: string;\n /**\n * The parsed error response body, when the server sent one. Carries the\n * fields that ride alongside an error — e.g. an invoke's `logs` and\n * `apiCalls` — which the message alone would drop.\n */\n body?: unknown;\n\n constructor(status: number, code: string, message: string, body?: unknown) {\n super(message);\n this.name = \"ApiError\";\n this.status = status;\n this.code = code;\n this.body = body;\n }\n}\n\n/** Build a fetch-based W6WApi client bound to a base URL + token supplier. */\nexport function createW6WApi(opts: CreateW6WApiOptions): W6WApi {\n const baseUrl = opts.baseUrl.replace(/\\/$/, \"\");\n const doFetch = opts.fetch ?? globalThis.fetch;\n const getToken = async () => (typeof opts.token === \"function\" ? await opts.token() : opts.token);\n\n // The shared fetch core: auth header, JSON parse, and the one error-shaping\n // idiom every member uses. Exposes the response's own status code (`req<T>`\n // below discards it) — `runWorkflow` is the one caller that needs it, to\n // derive `terminal` from `200` vs the server's own `202` wait-timeout arm.\n async function rawReq(\n path: string,\n init?: RequestInit,\n ): Promise<{ status: number; data: unknown }> {\n const headers = new Headers(init?.headers);\n const token = await getToken();\n if (token) headers.set(\"authorization\", `Bearer ${token}`);\n if (init?.body && !headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n\n let res: Response;\n try {\n res = await doFetch(`${baseUrl}${path}`, { ...init, headers });\n } catch (e) {\n // A failed fetch throws a bare `TypeError: Failed to fetch` — wrap it with\n // the target so callers can tell the server is down vs. a real API error.\n throw new ApiError(\n 0,\n \"network_error\",\n `Could not reach the w6w server (${init?.method ?? \"GET\"} ${baseUrl}${path}). ` +\n `It may be down or unreachable. (${(e as Error).message})`,\n );\n }\n const text = await res.text();\n let data: unknown = null;\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n if (!res.ok) {\n throw new ApiError(\n res.status,\n \"bad_response\",\n `Server returned a non-JSON ${res.status} response: ${text.slice(0, 200)}`,\n );\n }\n }\n }\n if (!res.ok) {\n const err = ((data as { error?: { code?: string; message?: string } } | null)?.error ??\n {}) as { code?: string; message?: string };\n throw new ApiError(res.status, err.code ?? \"error\", err.message ?? res.statusText, data);\n }\n return { status: res.status, data };\n }\n\n async function req<T>(path: string, init?: RequestInit): Promise<T> {\n const { data } = await rawReq(path, init);\n return data as T;\n }\n\n return {\n // A bare GET only returns the server's default page (50) — every consumer\n // of this client treats the result as the complete catalog, so walk one\n // server snapshot by `nextCursor` (opaque; the cursor encodes the\n // snapshot, so `snapshot`/`offset` are never sent). No page cap: the walk\n // ends when the cursor is absent or fails to advance. If the snapshot\n // expired mid-walk (410 `snapshot_expired` / 404 `unknown_snapshot`, alike\n // to a token holder), drop what was gathered and restart once.\n listApps: async () => {\n const walk = async (): Promise<AppSummary[]> => {\n const apps: AppSummary[] = [];\n let cursor: string | undefined;\n for (;;) {\n const qs = new URLSearchParams({ limit: \"200\" });\n if (cursor) qs.set(\"cursor\", cursor);\n const r = await req<{ apps: AppSummary[]; nextCursor?: string }>(`/apps?${qs}`);\n apps.push(...r.apps);\n if (!r.nextCursor || r.nextCursor === cursor) return apps;\n cursor = r.nextCursor;\n }\n };\n try {\n return await walk();\n } catch (e) {\n if (\n e instanceof ApiError &&\n (e.code === \"snapshot_expired\" || e.code === \"unknown_snapshot\")\n ) {\n return await walk();\n }\n throw e;\n }\n },\n\n // Bounded lookup: dedupe; `[]` sends nothing; chunks of <= 100 (the server's\n // `MAX_IDS_PER_QUERY`), each `GET /apps?ids=a,b` with no limit/cursor.\n listAppsByIds: async (ids) => {\n const unique = Array.from(new Set(ids));\n const apps: AppSummary[] = [];\n for (let i = 0; i < unique.length; i += 100) {\n const chunk = unique.slice(i, i + 100);\n const qs = chunk.map(encodeURIComponent).join(\",\");\n const r = await req<{ apps: AppSummary[] }>(`/apps?ids=${qs}`);\n apps.push(...r.apps);\n }\n return apps;\n },\n\n getAppAuth: async (id: string) => {\n const r = await req<{ auths: AuthDef[] }>(`/apps/${encodeURIComponent(id)}/auths`);\n return r.auths ?? [];\n },\n\n createConnection: (appId, body) =>\n req<{ connection: ConnectionSummary }>(`/apps/${encodeURIComponent(appId)}/connections`, {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then((r) => r.connection),\n\n updateConnection: (id, body) =>\n req<{ connection: ConnectionSummary }>(`/connections/${encodeURIComponent(id)}`, {\n method: \"PATCH\",\n body: JSON.stringify(body),\n }).then((r) => r.connection),\n\n listCredentials: (filter) => {\n const qs = new URLSearchParams();\n if (filter?.contract !== undefined) qs.set(\"contract\", filter.contract);\n if (filter?.appId !== undefined) qs.set(\"appId\", filter.appId);\n if (filter?.authKey !== undefined) qs.set(\"authKey\", filter.authKey);\n const q = qs.toString();\n return req<{ credentials: CredentialSummary[] }>(`/credentials${q ? `?${q}` : \"\"}`).then(\n (r) => r.credentials ?? [],\n );\n },\n\n createCredential: (body) =>\n req<{ credential: CredentialSummary }>(\"/credentials\", {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then((r) => r.credential),\n\n getCredential: (id) =>\n req<{ credential: CredentialSummary }>(`/credentials/${encodeURIComponent(id)}`).then(\n (r) => r.credential,\n ),\n\n rotateCredential: (id, body) =>\n req<{ credential: CredentialSummary }>(`/credentials/${encodeURIComponent(id)}/rotate`, {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then((r) => r.credential),\n\n setCredentialStatus: (id, status) =>\n req<{ credential: CredentialSummary }>(\n `/credentials/${encodeURIComponent(id)}/${status === \"disabled\" ? \"disable\" : \"enable\"}`,\n { method: \"POST\" },\n ).then((r) => r.credential),\n\n testCredential: (id) =>\n req<CredentialTestResult>(`/credentials/${encodeURIComponent(id)}/test`, { method: \"POST\" }),\n\n credentialDependents: (id) =>\n req<{ dependents: CredentialDependents }>(\n `/credentials/${encodeURIComponent(id)}/dependents`,\n ).then((r) => r.dependents),\n\n deleteCredential: async (id) => {\n await req<unknown>(`/credentials/${encodeURIComponent(id)}`, { method: \"DELETE\" });\n },\n\n startAppOAuthFlow: (appId, authKey, body) =>\n req<{ authorizationUrl: string }>(\n `/apps/${encodeURIComponent(appId)}/oauth-config/${encodeURIComponent(authKey)}/authorize-url`,\n { method: \"POST\", body: JSON.stringify(body) },\n ),\n\n getAppActions: (appId) =>\n req<{ actions: ActionDef[] }>(`/apps/${encodeURIComponent(appId)}`).then(\n (r) => r.actions ?? [],\n ),\n\n listConnectionsForApp: (appId) =>\n req<{ connections: ConnectionSummary[] }>(\n `/apps/${encodeURIComponent(appId)}/connections`,\n ).then((r) => r.connections ?? []),\n\n listConnections: () =>\n req<{ connections: ConnectionSummary[] }>(\"/connections\").then((r) => r.connections ?? []),\n\n invokeAction: (appId, actionKey, params, opts = {}) =>\n req<{\n value: unknown;\n logs?: string[];\n apiCalls?: ApiCallRecord[];\n meta?: StepMeta;\n }>(\n `/apps/${encodeURIComponent(appId)}/actions/${encodeURIComponent(actionKey)}/invoke`,\n // This body is built KEY BY KEY, not by spreading `opts` — so every new\n // option has to be named here or it is silently dropped before the wire\n // (the caller compiles, the UI looks right, the field never leaves the\n // page). `project` scopes document-expression resolution to the\n // workflow's selected project; `state` is the start state upstream step\n // outputs are seeded from, so `{{ steps.<id>.output.<f> }}` resolves.\n // Undefined keys are dropped by JSON.stringify, so an absent project or\n // state leaves the request byte-identical to one that never had them.\n {\n method: \"POST\",\n body: JSON.stringify({\n params,\n connectionId: opts.connectionId,\n project: opts.project,\n state: opts.state,\n workflowId: opts.workflowId,\n }),\n },\n ),\n\n listSavedTests: (connectionId) =>\n req<{ savedTests: SavedTest[] }>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests`,\n ).then((r) => r.savedTests ?? []),\n\n createSavedTest: (connectionId, body) =>\n req<{ savedTest: SavedTest }>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests`,\n { method: \"POST\", body: JSON.stringify(body) },\n ).then((r) => r.savedTest),\n\n updateSavedTest: (connectionId, id, patch) =>\n req<{ savedTest: SavedTest }>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests/${encodeURIComponent(id)}`,\n { method: \"PATCH\", body: JSON.stringify(patch) },\n ).then((r) => r.savedTest),\n\n deleteSavedTest: (connectionId, id) =>\n req<void>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests/${encodeURIComponent(id)}`,\n { method: \"DELETE\" },\n ).then(() => undefined),\n\n recordTestRun: (connId, body) =>\n req<{ run: unknown }>(`/connections/${encodeURIComponent(connId)}/test-runs`, {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then(() => undefined),\n\n listTestRuns: (connectionId) =>\n req<{ runs: TestRunSummary[] }>(\n `/connections/${encodeURIComponent(connectionId)}/test-runs`,\n ).then((r) => r.runs ?? []),\n\n saveStepTest: (workflowId, stepId, body) =>\n req<{ stepTest: StepTest }>(\n `/workflows/${encodeURIComponent(workflowId)}/steps/${encodeURIComponent(stepId)}/tests`,\n { method: \"POST\", body: JSON.stringify(body) },\n ).then((r) => r.stepTest),\n\n listStepTests: (workflowId, stepId) =>\n req<{ stepTests: StepTest[] }>(\n `/workflows/${encodeURIComponent(workflowId)}/steps/${encodeURIComponent(stepId)}/tests`,\n ).then((r) => r.stepTests ?? []),\n\n loadNodeSamples: (workflowId) =>\n req<{ nodeSamples?: NodeSample[] }>(\n `/workflows/${encodeURIComponent(workflowId)}/node-samples`,\n ).then((r) => r.nodeSamples ?? []),\n\n loadTestInputs: (workflowId) =>\n req<{ testInputs?: NodeTestInput[] }>(\n `/workflows/${encodeURIComponent(workflowId)}/test-inputs`,\n ).then((r) => r.testInputs ?? []),\n\n saveTestInput: (workflowId, nodeId, input) =>\n req<{ ok: boolean }>(\n `/workflows/${encodeURIComponent(workflowId)}/nodes/${encodeURIComponent(nodeId)}/test-input`,\n { method: \"PUT\", body: JSON.stringify({ input }) },\n ).then(() => undefined),\n\n recordStepTestRun: (workflowId, stepId, body) =>\n req<{ run: unknown }>(\n `/workflows/${encodeURIComponent(workflowId)}/steps/${encodeURIComponent(stepId)}/test-runs`,\n { method: \"POST\", body: JSON.stringify(body) },\n ).then(() => undefined),\n\n listFunctions: () =>\n req<{ functions: FunctionSummary[] }>(\"/functions\").then((r) => r.functions ?? []),\n\n getFunction: (id) =>\n req<{ function: Omit<FunctionDetail, \"valid\">; valid: boolean }>(\n `/functions/${encodeURIComponent(id)}`,\n ).then((r) => ({ ...r.function, valid: r.valid })),\n\n // The real synchronous route (`/functions/:id/invoke`) — deliberately NOT\n // `POST /run`, which would give the test stage a different code path than\n // the `@w6w/call` node it's standing in for. Returns the raw output,\n // pinned against the committed `studio/src/repos/functions.ts` signature.\n invokeFunction: (id, inputs) =>\n req<{ output?: unknown }>(`/functions/${encodeURIComponent(id)}/invoke`, {\n method: \"POST\",\n body: JSON.stringify({ inputs }),\n }).then((r) => r.output),\n\n listWorkflows: () =>\n req<{ workflows: WorkflowSummary[] }>(\"/workflows\").then((r) => r.workflows ?? []),\n\n getWorkflow: (id) =>\n req<{ workflow: WorkflowDetail }>(`/workflows/${encodeURIComponent(id)}`).then(\n (r) => r.workflow,\n ),\n\n // `rawReq`, not `req<T>` — the ONE caller that needs the response's own\n // status code: `200` (the run reached a terminal state inside the wait\n // window) vs `202` (the server's own wait-timeout, still running). Both\n // are 2xx successes; `rawReq` already throws on a non-2xx.\n runWorkflow: (id, opts = {}) =>\n rawReq(`/workflows/${encodeURIComponent(id)}/run?wait=true`, {\n method: \"POST\",\n body: JSON.stringify({ variables: opts.variables, input: opts.input }),\n }).then(({ status, data }) => {\n const body = (data ?? {}) as {\n runId: string;\n status: string;\n output?: unknown;\n error?: unknown;\n };\n return { ...body, terminal: status === 200 };\n }),\n };\n}\n","import type { MouseEvent, ReactNode } from \"react\";\n\nexport interface ListItemProps {\n /** Primary label — prominent, single-line with ellipsis overflow. */\n title: ReactNode;\n /** Secondary label under the title — muted, small, truncates. */\n subtitle?: ReactNode;\n /** Leading slot (e.g. an `<AppIcon />` or status glyph). */\n icon?: ReactNode;\n /**\n * Trailing slot pushed to the right (e.g. a badge or chevron). With `href` it sits INSIDE the\n * anchor, so it must stay non-interactive (no buttons or links).\n */\n trailing?: ReactNode;\n /** Highlights the row as selected/current. Reflected as `aria-pressed` when clickable. */\n active?: boolean;\n /**\n * When provided, the row renders as a focusable, keyboard-activatable button — or, with `href`,\n * still fires on a click of the anchor. Receives the click event; ListItem never calls\n * `preventDefault`, so the host decides whether the browser navigates.\n */\n onClick?: (event: MouseEvent<HTMLElement>) => void;\n /** When provided, the row renders as a real `<a href>` (middle-click, copy link, new tab). */\n href?: string;\n /** Accessible label for the clickable row (falls back to the `title` DOM text). */\n ariaLabel?: string;\n}\n\n/**\n * A clean, reusable list row: leading icon · title over subtitle · trailing slot.\n *\n * Mirrors the look/behaviour of the saved-test button rows it replaces. When\n * `onClick` is given it renders a `<button type=\"button\">` (focusable, Enter/Space\n * activatable) with `aria-pressed={active}`; with `href` an `<a href>` (the click still reaches\n * `onClick`); otherwise a plain, non-interactive row.\n */\nexport function ListItem({\n title,\n subtitle,\n icon,\n trailing,\n active = false,\n onClick,\n href,\n ariaLabel,\n}: ListItemProps) {\n const body = (\n <>\n {icon != null && <span className=\"w6w-list-item-icon\">{icon}</span>}\n <span className=\"w6w-list-item-body\">\n <span className=\"w6w-list-item-title\">{title}</span>\n {subtitle != null && <span className=\"w6w-list-item-subtitle\">{subtitle}</span>}\n </span>\n {trailing != null && <span className=\"w6w-list-item-trailing\">{trailing}</span>}\n </>\n );\n\n const className = `w6w-list-item${active ? \" active\" : \"\"}`;\n\n if (href !== undefined) {\n return (\n <a\n className={className}\n href={href}\n aria-current={active ? \"true\" : undefined}\n aria-label={ariaLabel}\n onClick={onClick}\n >\n {body}\n </a>\n );\n }\n\n if (onClick) {\n return (\n <button\n type=\"button\"\n className={className}\n aria-pressed={active}\n aria-label={ariaLabel}\n onClick={onClick}\n >\n {body}\n </button>\n );\n }\n\n return (\n <div className={className} aria-label={ariaLabel}>\n {body}\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { JsonEditor } from \"./JsonEditor.tsx\";\nimport { ParamsForm } from \"./ParamsForm.tsx\";\nimport { ApiCallsPanel } from \"./components/ApiCallsPanel.tsx\";\nimport { Combobox } from \"./components/Combobox.tsx\";\nimport { ConfirmModal } from \"./components/ConfirmModal.tsx\";\nimport { ListItem } from \"./components/ListItem.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport { ResultViewer } from \"./components/ResultViewer.tsx\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport type { RequestOverrides, TestRunSummary } from \"./provider.tsx\";\nimport type { ActionDef, ApiCallRecord, SavedTest, ThemeMode } from \"./types.ts\";\n\nexport interface ActionTestFormProps {\n /** App the action belongs to. */\n appId: string;\n /** The app's actions — the caller already has them from the app detail. */\n actions: ActionDef[];\n /** Fixed connection to run against; its credential is resolved server-side. */\n connectionId?: string;\n /**\n * Pre-selected action (controlled). When provided the built-in action\n * `<select>` is hidden — the caller is already driving the selection.\n */\n action?: ActionDef | null;\n /** Theme hint, accepted for parity with other ui-lib components. */\n theme?: ThemeMode;\n /**\n * Studio-integration seam: when provided (and its reference changes) the\n * current action's params are seeded from a shallow copy of this object, so a\n * host page can \"open\" a saved test pre-filled. The stored object is never\n * mutated; a subsequent user edit is free to diverge. Optional — existing\n * consumers keep compiling.\n */\n seedValues?: Record<string, unknown> | null;\n /**\n * Studio-integration seam: fired after a successful saved-test create/delete\n * so the host page can invalidate its own `[\"saved-tests\", connId]` query.\n * The modal rail still refreshes its own list independently. Optional.\n */\n onSavedTestsChanged?: () => void;\n /**\n * Studio-integration seam (URL-driven host): the id of the saved test being\n * edited, from a studio deep link (`…/test/:testId`). When it changes to a\n * non-null id it is adopted as the current `editingTestId` — so the bottom Save\n * PATCHes that row and the Delete button shows; when null the tester is a\n * fresh/unsaved test. Optional — existing consumers keep compiling.\n */\n seedTestId?: string | null;\n /**\n * Studio-integration seam: fired whenever the current `values` diverge from\n * (or return to) the seeded baseline. This is the unsaved-changes signal the\n * studio host gates modal-close on (its ConfirmModal prompt). Optional.\n */\n onDirtyChange?: (dirty: boolean) => void;\n /**\n * Studio-integration seam: fired after a successful save (POST create or PATCH\n * update) with the resulting `SavedTest`, so the host can sync the URL\n * (`…/test/:id`) and clear its own dirty state. Optional.\n */\n onTestSaved?: (test: SavedTest) => void;\n /**\n * Studio-integration seam: fired after a successful delete of the saved test\n * currently being edited, with the deleted id, so the host can navigate away\n * from a now-dead `…/test/:id` URL. Optional — existing consumers keep compiling.\n */\n onDeleted?: (testId: string) => void;\n /**\n * Host-embedded mode. When `true` the caller already renders this widget inside\n * its own modal (studio's `ConnectionTesterModal`), so the widget suppresses its\n * OWN `<Modal>` + pop-out (⤢) toggle and instead fills the host container as a\n * full-height flex column: the params + saved-tests region scrolls and the\n * action bar is pinned to the bottom. Default `false` — non-embedded (inline /\n * own pop-out) usages are unchanged.\n */\n embedded?: boolean;\n}\n\n/**\n * Minimal relative-time label (\"just now\", \"5m ago\", \"3h ago\", \"2d ago\", or a\n * date for anything older) from an ISO timestamp. Kept inline — no formatter is\n * imported here — and only used for the saved-tests rail subtitle.\n */\nfunction relativeTime(iso: string): string {\n const then = Date.parse(iso);\n if (Number.isNaN(then)) return \"\";\n const secs = Math.max(0, Math.round((Date.now() - then) / 1000));\n if (secs < 45) return \"just now\";\n const mins = Math.round(secs / 60);\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.round(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.round(hours / 24);\n if (days < 7) return `${days}d ago`;\n return new Date(then).toLocaleDateString();\n}\n\n/** Pull default values out of declared params so the form starts populated. */\nfunction defaultParamsFor(action: ActionDef | null | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const p of action?.params ?? []) {\n if (p.key && p.default !== undefined) out[p.key] = p.default;\n }\n return out;\n}\n\n/** A rendered action error: a plain-language headline, an optional fix hint, and the raw provider detail. */\ninterface InvokeError {\n headline: string;\n hint?: string;\n detail?: string;\n}\n\n/**\n * Pull the provider's own human-readable message out of a raw error string. App\n * actions often throw like `SendGrid list index returned 403: {\"errors\":[{\"message\":\"…\"}]}`\n * — parse the trailing JSON and surface just the human message, keeping the\n * `\"<App> … returned <status>\"` prefix.\n */\nfunction extractProviderMessage(msg: string): string {\n const brace = msg.indexOf(\"{\");\n if (brace >= 0) {\n try {\n const j = JSON.parse(msg.slice(brace)) as {\n errors?: { message?: string }[];\n error?: { message?: string } | string;\n message?: string;\n };\n const m =\n j?.errors?.[0]?.message ??\n (typeof j?.error === \"object\" ? j.error?.message : j?.error) ??\n j?.message;\n if (typeof m === \"string\" && m.trim()) {\n const prefix = msg.slice(0, brace).replace(/[:\\s]+$/, \"\");\n return prefix ? `${prefix}: ${m.trim()}` : m.trim();\n }\n } catch {\n // Not JSON — fall through and return the message as-is.\n }\n }\n return msg;\n}\n\n/**\n * A failed-invoke error shape, matched by field rather than class identity —\n * ui's own `ApiError` and `@w6w/sdk`'s are two different classes across the\n * package boundary, and `status`+`code` is what both actually carry.\n * Considered mirroring `packages/wrappers/cli/src/exit.ts:60-63`'s `name ===\n * \"ApiError\"` fallback; not adopted — that solves module DUPLICATION of one\n * class, while ui's problem is cross-package IDENTITY, which `status`+`code`\n * already settles.\n */\nfunction isInvokeApiError(\n e: unknown,\n): e is { status: number; code: string; message?: string; body?: unknown; raw?: unknown } {\n return (\n typeof e === \"object\" &&\n e !== null &&\n typeof (e as { status: unknown }).status === \"number\" &&\n typeof (e as { code: unknown }).code === \"string\"\n );\n}\n\n/**\n * Turn a thrown invoke error into a user-facing message. A permission/credential\n * failure at the underlying provider (HTTP 401/403, or the message mentions\n * scopes/forbidden/unauthorized) is stated plainly with what to fix, so the user\n * isn't left staring at a raw upstream JSON blob.\n */\nfunction describeInvokeError(e: unknown): InvokeError {\n if (!isInvokeApiError(e)) {\n return { headline: (e as Error)?.message ?? \"The action failed to run.\" };\n }\n const detail = extractProviderMessage(e.message ?? \"\");\n const haystack = `${e.status} ${e.code} ${e.message ?? \"\"}`.toLowerCase();\n const isPermission =\n e.status === 401 ||\n e.status === 403 ||\n /\\b(401|403)\\b|forbidden|unauthorized|not authorized|permission|scope|access denied|invalid api key|invalid credential/.test(\n haystack,\n );\n if (isPermission) {\n return {\n headline:\n \"Permission denied by the provider — this is a credential/scope problem, not a w6w error.\",\n hint:\n \"The connection's API key is missing the permissions this action needs. Fix it at the \" +\n \"provider — e.g. SendGrid → Settings → API Keys → give the key the required scopes (or Full \" +\n \"Access), or create a new key — then update this connection's credential and try again.\",\n detail,\n };\n }\n return { headline: \"The action returned an error.\", detail };\n}\n\n/**\n * The captured outbound calls the server attached to a failed invoke — ui's\n * own `ApiError` carries them on `body`, `@w6w/sdk`'s on `raw`; read `body ??\n * raw` so either shape's calls surface.\n */\nfunction apiCallsOf(e: unknown): ApiCallRecord[] {\n const source = isInvokeApiError(e)\n ? ((e.body ?? e.raw) as { apiCalls?: ApiCallRecord[] } | null)\n : null;\n return source?.apiCalls ?? [];\n}\n\n/**\n * One Overrides sub-editor's local state (`body`/`query`/`headers`): raw text\n * (the widget's source of truth), the last value that parsed as a plain JSON\n * object, and whether the CURRENT text is invalid. Empty/whitespace text is\n * always valid and means \"not set\" — never blocks Run — matching the\n * requirement that clearing a field returns to \"no override\", not an error.\n *\n * Deliberately re-parses on every keystroke here rather than wiring\n * `JsonEditor`'s own `onValidChange`/`onValidityChange`: that pair reports an\n * emptied field as `{valid: false, error: \"Empty\"}`, which would wrongly keep\n * Run refusing the moment a touched field is cleared back out.\n */\nfunction useOverrideJsonField() {\n const [text, setText] = useState(\"\");\n const [value, setValue] = useState<Record<string, unknown> | undefined>(undefined);\n const [invalid, setInvalid] = useState(false);\n const onChange = (next: string) => {\n setText(next);\n const trimmed = next.trim();\n if (trimmed === \"\") {\n setInvalid(false);\n return;\n }\n try {\n const parsed = JSON.parse(trimmed);\n if (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n setValue(parsed as Record<string, unknown>);\n setInvalid(false);\n } else {\n setInvalid(true);\n }\n } catch {\n setInvalid(true);\n }\n };\n return { text, value, invalid, onChange } as const;\n}\n\n/**\n * Schema-driven form to test/run a single action against a connection. Renders\n * the action's declared params through {@link ParamsForm} (the same primitive\n * the step builder uses) instead of a raw JSON textarea, invokes the action via\n * `useW6WApi().invokeAction`, and shows the returned value or error.\n *\n * The selected action is either controlled by the caller (`action` prop) or\n * chosen from a built-in `<select>` over `actions`. Param values reset whenever\n * the selected action changes.\n */\nexport function ActionTestForm({\n appId,\n actions,\n connectionId,\n action,\n seedValues,\n onSavedTestsChanged,\n seedTestId,\n onDirtyChange,\n onTestSaved,\n onDeleted,\n embedded = false,\n}: ActionTestFormProps) {\n const api = useW6WApi();\n\n // Actions sorted for the built-in picker (only used when uncontrolled).\n const sortedActions = useMemo(() => {\n const list = [...actions];\n list.sort((a, b) => (a.title || a.key).localeCompare(b.title || b.key));\n return list;\n }, [actions]);\n\n // Internal selection, used only when the caller doesn't control `action`.\n const [pickedKey, setPickedKey] = useState<string>(action?.key ?? \"\");\n const selectedAction: ActionDef | null =\n action ?? actions.find((a) => a.key === pickedKey) ?? null;\n\n const [running, setRunning] = useState(false);\n const [error, setError] = useState<InvokeError | null>(null);\n const [result, setResult] = useState<unknown>(undefined);\n // The outbound HTTP calls the last run made (redacted request + response).\n // Populated on success AND failure — a wrong payload is usually only visible\n // on the wire, not in the value.\n const [apiCalls, setApiCalls] = useState<ApiCallRecord[]>([]);\n\n // Overrides region (T2.1.1): a RequestOverrides envelope submitted as a\n // fourth field alongside params — architecturally NOT a Param (it never\n // enters `resolveParams`), so it is a SIBLING region to `paramsRegion`\n // rather than a slot inside `ParamsForm`'s \"Additional parameters\"\n // disclosure. See `.claude/docs/overrides.md`.\n const ovBody = useOverrideJsonField();\n const ovQuery = useOverrideJsonField();\n const ovHeaders = useOverrideJsonField();\n const [ovTarget, setOvTarget] = useState<\"\" | \"first\" | \"first-write\" | \"all\">(\"\");\n const [ovMatch, setOvMatch] = useState(\"\");\n // Any sub-editor currently holding invalid JSON blocks the run outright —\n // never send a half-parsed envelope.\n const overridesInvalid = ovBody.invalid || ovQuery.invalid || ovHeaders.invalid;\n // Built fresh from current state on every call — an untouched (or cleared)\n // control leaves every field empty, so this returns `undefined` and the run\n // sends no `overrides` key at all: byte-identical to a request from before\n // this control existed.\n const currentOverrides = (): RequestOverrides | undefined => {\n const out: RequestOverrides = {};\n if (ovBody.text.trim() !== \"\" && ovBody.value !== undefined) out.body = ovBody.value;\n if (ovQuery.text.trim() !== \"\" && ovQuery.value !== undefined) {\n out.query = ovQuery.value as Record<string, string | number | boolean | null>;\n }\n if (ovHeaders.text.trim() !== \"\" && ovHeaders.value !== undefined) {\n out.headers = ovHeaders.value as Record<string, string>;\n }\n if (ovTarget) out.target = ovTarget;\n if (ovMatch.trim() !== \"\") out.match = ovMatch.trim();\n return Object.keys(out).length > 0 ? out : undefined;\n };\n\n // Params view: the schema-driven form, or the whole `values` object as raw JSON.\n const [viewMode, setViewMode] = useState<\"form\" | \"json\">(\"form\");\n const [jsonText, setJsonText] = useState(\"\");\n const [jsonInvalid, setJsonInvalid] = useState(false);\n\n // Pop-out: when open, the params region moves into a larger `Modal` canvas.\n // It is the SAME region bound to the SAME `values`/`setValues`, just relocated,\n // so edits stay in sync with the inline view.\n const [modalOpen, setModalOpen] = useState(false);\n\n // Param values, re-seeded from defaults whenever the selected action changes.\n // On a FRESH MOUNT with `seedValues` present (e.g. a deep-linked saved test),\n // seed from a shallow copy of it rather than defaults — otherwise the seed guard\n // below never fires on first render (`lastSeed` inits to the same ref) and the\n // seeded values are dropped.\n const selectedKey = selectedAction?.key ?? null;\n const initialValues = seedValues ? { ...seedValues } : defaultParamsFor(selectedAction);\n const [valuesByAction, setValuesByAction] = useState<{\n key: string | null;\n values: Record<string, unknown>;\n }>(() => ({\n key: selectedKey,\n values: initialValues,\n }));\n\n // The id of the saved test currently being edited, or `null` for an unsaved\n // test. Drives the PATCH-vs-POST decision in `submitSaveTest`: a set id updates\n // that row in place, `null` creates a new named row. Seeded from `seedTestId`\n // so a studio deep link (`…/test/:testId`) mounts already in edit mode.\n const [editingTestId, setEditingTestId] = useState<string | null>(seedTestId ?? null);\n\n // Dirty baseline: the values as last seeded/loaded/saved. `values` is compared\n // against this to derive the host-facing `dirty` signal (`onDirtyChange`). Reset\n // wherever a fresh set of values is adopted (action change, seed, load, save).\n const [baseline, setBaseline] = useState<Record<string, unknown>>(initialValues);\n\n if (valuesByAction.key !== selectedKey) {\n // Selection changed (controlled or via the picker, without a remount) — reset the\n // form values AND clear any stale result/error carried over from the previously\n // selected action (a 403 from `list-get` must not linger while `mail-send` shows).\n // Editing id: a genuine action-switch starts a fresh unsaved test (→ null), BUT a\n // deep-link whose action arrives AFTER mount is NOT an action-switch — the selected\n // action IS the seeded test's action. A truthy `seedTestId` therefore wins here, so\n // the late null→key transition keeps `editingTestId === seedTestId` (Save PATCHes,\n // Delete shows) instead of clobbering it to null and POSTing a duplicate row.\n const fresh = defaultParamsFor(selectedAction);\n setValuesByAction({ key: selectedKey, values: fresh });\n setBaseline(fresh);\n setEditingTestId(seedTestId ?? null);\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n }\n\n // Studio seam: adopt a deep-linked saved-test id. When `seedTestId` changes to a\n // non-null id, make it the current editing id (bottom Save PATCHes, Delete\n // shows); a change to null returns the tester to a fresh/unsaved test.\n const [lastSeedTestId, setLastSeedTestId] = useState<string | null | undefined>(seedTestId);\n if (seedTestId !== lastSeedTestId) {\n setLastSeedTestId(seedTestId);\n setEditingTestId(seedTestId ?? null);\n }\n\n // Studio seam: when a new `seedValues` reference arrives (e.g. \"open a saved\n // test\"), seed the current action's params from a SHALLOW COPY of it. Applied\n // as a render-phase guard like the action-change reseed above; the passed\n // object is never mutated and later edits are free to diverge.\n const [lastSeed, setLastSeed] = useState<Record<string, unknown> | null | undefined>(seedValues);\n if (seedValues !== lastSeed) {\n // Content-aware, not reference-keyed: a `[\"saved-tests\"]` invalidation (fired by\n // onTestSaved/onSavedTestsChanged after a Save) hands back a fresh OBJECT with the\n // SAME content — that must NOT reseed the draft or clear the on-screen Run\n // result/error. Reseed only when the incoming values differ STRUCTURALLY from the\n // last applied seed. `lastSeed` advances to the new ref regardless, so we don't\n // re-compare the same pair every render.\n const structurallyChanged =\n JSON.stringify(seedValues ?? null) !== JSON.stringify(lastSeed ?? null);\n setLastSeed(seedValues);\n if (seedValues && structurallyChanged) {\n const seeded = { ...seedValues };\n setValuesByAction({ key: selectedKey, values: seeded });\n setBaseline(seeded);\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n }\n }\n\n const values = valuesByAction.values;\n const setValues = (next: Record<string, unknown>) =>\n setValuesByAction({ key: selectedKey, values: next });\n\n // Host-facing dirty signal: do the current values diverge from the seeded\n // baseline? Compared by structural JSON so a load→edit→revert cycle clears it.\n const dirty = useMemo(\n () => JSON.stringify(values) !== JSON.stringify(baseline),\n [values, baseline],\n );\n // biome-ignore lint/correctness/useExhaustiveDependencies: fire only when `dirty` flips, not on every `onDirtyChange` identity change.\n useEffect(() => {\n onDirtyChange?.(dirty);\n }, [dirty]);\n\n // Entering the JSON view seeds the editor from the current values; edits that\n // parse to a plain object round-trip straight back into `values`.\n const enterJsonView = () => {\n setJsonText(JSON.stringify(values, null, 2));\n setJsonInvalid(false);\n setViewMode(\"json\");\n };\n\n // The single invoke path — used by \"Run action\" and by re-running a saved test.\n const runWith = async (params: Record<string, unknown>) => {\n if (!selectedAction) return;\n // An invalid Overrides sub-editor refuses the run outright — the Run\n // button is also disabled for this, but guard here too so a saved-test\n // re-run (which bypasses the button) can't slip a half-parsed envelope\n // through either.\n if (overridesInvalid) return;\n const actionKey = selectedAction.key;\n setRunning(true);\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n let outcome: { ok: boolean; summary: string; result?: unknown };\n const overrides = currentOverrides();\n try {\n const r = await api.invokeAction(appId, actionKey, params, {\n connectionId,\n ...(overrides ? { overrides } : {}),\n });\n setResult(r.value);\n setApiCalls(r.apiCalls ?? []);\n outcome = { ok: true, summary: \"OK\", result: r.value };\n } catch (e) {\n const err = describeInvokeError(e);\n setError(err);\n // The server returns the captured calls on the error body too — the\n // request that failed is the thing worth looking at.\n setApiCalls(apiCallsOf(e));\n outcome = { ok: false, summary: err.headline };\n } finally {\n setRunning(false);\n }\n // Log every run (success or failure) against the connection, and update the\n // saved test's last-run when this run came from an editing session. Best\n // effort — a logging failure must not mask the run's own result.\n if (connectionId) {\n try {\n await api.recordTestRun(connectionId, {\n savedTestId: editingTestId ?? null,\n actionKey,\n ok: outcome.ok,\n summary: outcome.summary.slice(0, 200),\n result: outcome.result,\n });\n refreshSavedTests();\n refreshRunHistory();\n onSavedTestsChanged?.();\n } catch {\n // Ignore — the run itself already surfaced via result/error.\n }\n }\n };\n const run = () => runWith(values);\n\n // Saved tests for this connection. `nonce` re-triggers the fetch after a\n // create/delete so the rail reflects the change without a full remount.\n const [savedTests, setSavedTests] = useState<SavedTest[] | null>(null);\n const [savedTestsError, setSavedTestsError] = useState<string | null>(null);\n const [savedTestsNonce, setSavedTestsNonce] = useState(0);\n // Name-a-saved-test dialog (in-app Modal — never the browser's prompt()).\n const [nameModalOpen, setNameModalOpen] = useState(false);\n const [pendingName, setPendingName] = useState(\"\");\n // Delete-confirm dialog (in-app ConfirmModal — never the browser's confirm()).\n const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);\n const refreshSavedTests = () => setSavedTestsNonce((n) => n + 1);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `savedTestsNonce` is a deliberate re-fetch trigger, not read inside the effect.\n useEffect(() => {\n if (!connectionId) {\n setSavedTests(null);\n return;\n }\n let canceled = false;\n setSavedTestsError(null);\n api\n .listSavedTests(connectionId)\n .then((list) => !canceled && setSavedTests(list))\n .catch((e) => !canceled && setSavedTestsError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, connectionId, savedTestsNonce]);\n\n // Only this action's saved tests belong on the rail.\n const railTests = selectedKey\n ? (savedTests ?? []).filter((t) => t.actionKey === selectedKey)\n : [];\n\n // Connection run history from the unified `run_log` ledger (F-1). Complements\n // the per-saved-test `lastRun*` badge with the full recent-run list. Fetched\n // via the OPTIONAL `api.listTestRuns` — a consumer that doesn't implement it\n // (studio, until T2.2.2) simply shows no history. `runHistoryNonce` re-triggers\n // the fetch after a run is recorded so the list stays current.\n const [runHistory, setRunHistory] = useState<TestRunSummary[] | null>(null);\n const [runHistoryNonce, setRunHistoryNonce] = useState(0);\n const refreshRunHistory = () => setRunHistoryNonce((n) => n + 1);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `runHistoryNonce` is a deliberate re-fetch trigger, not read inside the effect.\n useEffect(() => {\n const load = api.listTestRuns;\n if (!connectionId || !load) {\n setRunHistory(null);\n return;\n }\n let canceled = false;\n load(connectionId)\n .then((list) => !canceled && setRunHistory(list))\n // Best-effort: a history load failure must never break the tester.\n .catch(() => !canceled && setRunHistory(null));\n return () => {\n canceled = true;\n };\n }, [api, connectionId, runHistoryNonce]);\n\n // History rows for the current action (mirrors the saved-tests rail filter),\n // most-recent first — the server orders newest-first but we don't rely on it.\n const railRunHistory = selectedKey\n ? (runHistory ?? [])\n .filter((r) => r.actionKey === selectedKey)\n .slice()\n .sort((a, b) => Date.parse(b.occurredAt) - Date.parse(a.occurredAt))\n : [];\n\n // Open the in-app name dialog to save the current params as a NEW named test.\n const openSaveModal = () => {\n if (!connectionId || !selectedAction) return;\n setPendingName(\"\");\n setSavedTestsError(null);\n setNameModalOpen(true);\n };\n // Bottom Save affordance. When a saved test is loaded for editing\n // (`editingTestId` set) the save is a silent PATCH — no throwaway name dialog\n // (FU-1). With no editing id, open the name dialog to create a new named row.\n const handleSaveClick = () => {\n if (!connectionId || !selectedAction) return;\n if (editingTestId) {\n void submitSaveTest();\n } else {\n openSaveModal();\n }\n };\n // Persist the current params. When a saved test is loaded for editing\n // (`editingTestId` set), PATCH that row in place — updating only `values` keeps\n // its name and sidesteps the 409 duplicate-name guard a re-POST would trip.\n // With no editing id, create a new named row from the dialog and remember its\n // id so the next save updates in place rather than spawning a second row.\n const submitSaveTest = async () => {\n if (!connectionId || !selectedAction) return;\n try {\n let saved: SavedTest;\n if (editingTestId) {\n saved = await api.updateSavedTest(connectionId, editingTestId, { values });\n } else {\n const name = pendingName.trim();\n if (!name) return;\n saved = await api.createSavedTest(connectionId, {\n actionKey: selectedAction.key,\n name,\n values,\n });\n setEditingTestId(saved.id);\n }\n // The just-saved values are the new clean baseline (dirty → false).\n setBaseline({ ...values });\n setNameModalOpen(false);\n setPendingName(\"\");\n refreshSavedTests();\n onSavedTestsChanged?.();\n onTestSaved?.(saved);\n } catch (e) {\n setSavedTestsError((e as Error).message);\n }\n };\n\n // Load a saved test's values into the form (shallow copy — never mutate the\n // stored row). Clicking a saved test's name loads it for editing: values +\n // editing id are adopted and the load becomes the new clean baseline.\n const loadSavedTest = (t: SavedTest) => {\n const loaded = { ...t.values };\n setValuesByAction({ key: selectedKey, values: loaded });\n setBaseline(loaded);\n // Remember which row is being edited so a subsequent save PATCHes it in place.\n setEditingTestId(t.id);\n setViewMode(\"form\");\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n };\n // Delete the saved test currently being edited (Delete only shows with an\n // editing id set). Clears the editing id so the form drops to unsaved state.\n const deleteCurrentTest = async () => {\n if (!connectionId || !editingTestId) return;\n const deletedId = editingTestId;\n try {\n await api.deleteSavedTest(connectionId, deletedId);\n setEditingTestId(null);\n refreshSavedTests();\n onSavedTestsChanged?.();\n // Host hook: let the URL-driven host (studio's ConnectionTesterModal) navigate\n // away from the now-dead `…/test/:deletedId` deep link.\n onDeleted?.(deletedId);\n } catch (e) {\n setSavedTestsError((e as Error).message);\n }\n };\n\n // The params region: the form↔JSON toggle plus the ParamsForm/JsonEditor block.\n // Rendered in exactly one place at a time — inline when the pop-out is closed,\n // inside the `Modal` when it's open — so there's a single instance bound to the\n // single `values`/`setValues` state (no copy-on-open, edits stay in sync).\n const paramsRegion = (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-1-5)\" }}>\n <div\n className=\"w6w-field-labelrow\"\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}\n >\n <span className=\"w6w-muted w6w-small\">Parameters</span>\n <div style={{ display: \"flex\", gap: \"var(--w6w-sp-1)\" }}>\n <button\n type=\"button\"\n className={`w6w-btn w6w-btn-sm w6w-btn-ghost${viewMode === \"form\" ? \" active\" : \"\"}`}\n aria-pressed={viewMode === \"form\"}\n onClick={() => setViewMode(\"form\")}\n >\n Form\n </button>\n <button\n type=\"button\"\n className={`w6w-btn w6w-btn-sm w6w-btn-ghost${viewMode === \"json\" ? \" active\" : \"\"}`}\n aria-pressed={viewMode === \"json\"}\n onClick={enterJsonView}\n >\n JSON\n </button>\n {/* Pop-out toggle — suppressed in embedded mode: the host already\n provides full-screen modal chrome, so a modal-in-modal ⤢ is redundant. */}\n {!embedded && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-sm w6w-btn-ghost\"\n aria-pressed={modalOpen}\n title={\n modalOpen ? \"Collapse the params editor\" : \"Open the params editor in a larger view\"\n }\n aria-label={\n modalOpen ? \"Collapse the params editor\" : \"Open the params editor in a larger view\"\n }\n onClick={() => setModalOpen((v) => !v)}\n >\n {modalOpen ? \"⤡\" : \"⤢\"}\n </button>\n )}\n </div>\n </div>\n\n {viewMode === \"form\" ? (\n <ParamsForm\n params={selectedAction?.params ?? []}\n values={values}\n onChange={setValues}\n dynamic={\n selectedAction ? { appId, actionKey: selectedAction.key, connectionId } : undefined\n }\n />\n ) : (\n <>\n <JsonEditor\n value={jsonText}\n onChange={setJsonText}\n minHeight={modalOpen ? \"50vh\" : \"200px\"}\n aria-label=\"Params JSON\"\n onValidChange={(parsed) => {\n // Only a JSON object maps onto the params `values` record; ignore a\n // bare array/scalar so `values` stays a plain key→value object.\n if (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n setValues(parsed as Record<string, unknown>);\n }\n }}\n onValidityChange={({ valid }) => setJsonInvalid(!valid)}\n />\n {jsonInvalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </>\n )}\n </div>\n );\n\n // The Overrides region: a sibling to `paramsRegion`, never nested inside it\n // (and never inside `ParamsForm`'s own \"Additional parameters\" disclosure —\n // `overrides` is not a Param). Collapsed by default via `<details>`, reusing\n // the same `.w6w-section` disclosure `SectionField` renders for a\n // `section: \"collapsible\"` param, since this is the identical visual shape\n // (titled, collapsed-by-default disclosure) applied to a hand-built control\n // instead of a schema-driven one.\n const overridesRegion = (\n <details className=\"w6w-section\" data-testid=\"overrides-region\">\n <summary className=\"w6w-section-summary\">\n <span className=\"w6w-section-title\">Overrides</span>\n <span className=\"w6w-section-subtitle\">\n Reach a vendor field this action's own params don't declare\n </span>\n </summary>\n <div className=\"w6w-stack w6w-section-body\" style={{ gap: \"var(--w6w-sp-2)\" }}>\n <div className=\"w6w-field\">\n <span>Body</span>\n <JsonEditor\n value={ovBody.text}\n onChange={ovBody.onChange}\n minHeight=\"80px\"\n aria-label=\"Overrides body (JSON)\"\n />\n {ovBody.invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </div>\n <div className=\"w6w-field\">\n <span>Query</span>\n <JsonEditor\n value={ovQuery.text}\n onChange={ovQuery.onChange}\n minHeight=\"80px\"\n aria-label=\"Overrides query (JSON)\"\n />\n {ovQuery.invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </div>\n <div className=\"w6w-field\">\n <span>Headers</span>\n <JsonEditor\n value={ovHeaders.text}\n onChange={ovHeaders.onChange}\n minHeight=\"80px\"\n aria-label=\"Overrides headers (JSON)\"\n />\n {ovHeaders.invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </div>\n <label className=\"w6w-field\">\n <span>Target</span>\n <select\n aria-label=\"Overrides target\"\n value={ovTarget}\n onChange={(e) => setOvTarget(e.target.value as typeof ovTarget)}\n >\n <option value=\"\">— default (first) —</option>\n <option value=\"first\">first</option>\n <option value=\"first-write\">first-write</option>\n <option value=\"all\">all</option>\n </select>\n </label>\n <label className=\"w6w-field\">\n <span>Match</span>\n <input\n type=\"text\"\n aria-label=\"Overrides match\"\n value={ovMatch}\n placeholder=\"Restrict to requests whose URL contains…\"\n onChange={(e) => setOvMatch(e.target.value)}\n />\n </label>\n <span className=\"w6w-hint\">\n Merged onto the outbound request at the wire, never into the params above — name a field\n the way the vendor's own API documents it.\n </span>\n </div>\n </details>\n );\n\n // The saved-tests rail — the right pane of the pop-out. Only meaningful when a\n // connection is fixed; hidden entirely otherwise (guarded on `connectionId`).\n const savedTestsRail = connectionId ? (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-1-5)\" }}>\n <div\n className=\"w6w-field-labelrow\"\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}\n >\n <span className=\"w6w-muted w6w-small\">Saved tests</span>\n </div>\n {savedTestsError && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n {savedTestsError}\n </span>\n )}\n {railTests.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">No saved tests for this action yet.</p>\n ) : (\n <ul\n className=\"w6w-stack\"\n style={{ listStyle: \"none\", margin: 0, padding: 0, gap: \"var(--w6w-sp-1-5)\" }}\n >\n {railTests.map((t) => (\n <li key={t.id}>\n {/* Clicking a saved test loads it for editing — no per-row\n Load/Run/Delete buttons; those actions live at the modal bottom.\n Subtitle shows the last run (✓/✗ + relative time), falling back\n to the last-saved time when the test has never been run. */}\n <ListItem\n title={t.name}\n subtitle={\n t.lastRunAt ? (\n <span>\n <span\n style={{ color: t.lastRunOk ? \"var(--w6w-success)\" : \"var(--w6w-danger)\" }}\n >\n {t.lastRunOk ? \"✓\" : \"✗\"}\n </span>{\" \"}\n {t.lastRunSummary ? `${t.lastRunSummary} · ` : \"\"}\n {relativeTime(t.lastRunAt)}\n </span>\n ) : (\n `saved ${relativeTime(t.updatedAt)}`\n )\n }\n active={t.id === editingTestId}\n onClick={() => loadSavedTest(t)}\n />\n </li>\n ))}\n </ul>\n )}\n\n {/* Run history (F-1): the connection's recent tester runs for this action,\n from the unified `run_log` ledger. Read-only rows (no onClick) — this is\n a log, not a loadable input like the saved tests above. Only rendered\n when the api exposes `listTestRuns` (optional member) and there is\n history to show, so a consumer without it degrades to no section. */}\n {api.listTestRuns && railRunHistory.length > 0 && (\n <>\n <div\n className=\"w6w-field-labelrow\"\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}\n >\n <span className=\"w6w-muted w6w-small\">Recent runs</span>\n </div>\n <ul\n className=\"w6w-stack\"\n style={{ listStyle: \"none\", margin: 0, padding: 0, gap: \"var(--w6w-sp-1-5)\" }}\n >\n {railRunHistory.map((r) => (\n <li key={r.id}>\n <ListItem\n title={\n <span>\n <span style={{ color: r.ok ? \"var(--w6w-success)\" : \"var(--w6w-danger)\" }}>\n {r.ok ? \"✓\" : \"✗\"}\n </span>{\" \"}\n {r.actionKey}\n </span>\n }\n subtitle={\n <span>\n {r.summary ? `${r.summary} · ` : \"\"}\n {relativeTime(r.occurredAt)}\n </span>\n }\n />\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n ) : null;\n\n // Nullable: `editingTestId` can be seeded from a studio deep link before\n // `savedTests` itself has finished fetching, so this may not resolve yet.\n const deletingTestName = savedTests?.find((t) => t.id === editingTestId)?.name;\n\n return (\n <div className={`w6w-stack${embedded ? \" w6w-tester-embedded-root\" : \"\"}`}>\n {/* Action picker — only when the caller isn't controlling the selection. */}\n {!action &&\n (actions.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">This app exposes no actions.</p>\n ) : (\n // biome-ignore lint/a11y/noLabelWithoutControl: Combobox renders its own <select>/<input> INSIDE this label, so the field text labels the control at runtime; the rule cannot see through the component boundary.\n <label className=\"w6w-field\">\n <span>Action{selectedKey ? \"\" : \" *\"}</span>\n <Combobox\n value={pickedKey}\n placeholder=\"— pick an action —\"\n onChange={setPickedKey}\n options={sortedActions.map((a) => ({\n value: a.key,\n label: `${a.title ?? a.key} (${a.key})`,\n }))}\n />\n </label>\n ))}\n\n {selectedAction ? (\n <>\n <div>\n <strong>\n {selectedAction.title ?? selectedAction.key}{\" \"}\n <code className=\"w6w-muted\">{selectedAction.key}</code>\n </strong>\n {selectedAction.description && (\n <p className=\"w6w-muted w6w-small\" style={{ margin: \"var(--w6w-sp-0-5) 0 0\" }}>\n {selectedAction.description}\n </p>\n )}\n </div>\n\n {(() => {\n // The scrollable tester content: params editor + error + result. Shared\n // by every layout (inline body, pop-out modal, embedded footer layout)\n // so it stays a single instance bound to the single `values` state.\n const errorBox = error ? (\n <div className=\"w6w-result w6w-error\">\n <strong>{error.headline}</strong>\n {error.hint && <div style={{ marginTop: \"var(--w6w-sp-1-5)\" }}>{error.hint}</div>}\n {error.detail && (\n <div\n className=\"w6w-muted w6w-small\"\n style={{\n marginTop: \"var(--w6w-sp-1-5)\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n }}\n >\n {error.detail}\n </div>\n )}\n </div>\n ) : null;\n const resultBlock =\n result !== undefined ? (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-1)\" }}>\n <strong className=\"w6w-small\">Result</strong>\n <ResultViewer value={result} />\n </div>\n ) : null;\n const paramsAndResult = (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {paramsRegion}\n {overridesRegion}\n {errorBox}\n {resultBlock}\n <ApiCallsPanel calls={apiCalls} />\n </div>\n );\n // Bottom-anchored actions: Run / Save always; Delete only when an\n // editing id is set (an already-saved test is loaded). In embedded mode\n // this becomes a bottom-pinned footer outside the scroll region.\n const actionBar = (\n <div\n className={`w6w-tester-actions${\n embedded || modalOpen ? \" w6w-tester-actions-footer\" : \"\"\n }`}\n style={{ display: \"flex\", gap: \"var(--w6w-sp-2)\" }}\n >\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={running || overridesInvalid}\n onClick={run}\n >\n {running ? \"Running…\" : \"Run action\"}\n </button>\n {connectionId && (\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={handleSaveClick}>\n Save test\n </button>\n )}\n {connectionId && editingTestId && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n style={{ marginLeft: \"auto\", color: \"var(--w6w-danger)\" }}\n onClick={() => setConfirmDeleteOpen(true)}\n >\n Delete\n </button>\n )}\n </div>\n );\n // The tester body: params + result + actions, stacked. Rendered inline\n // when the pop-out modal is closed, and inside the pop-out modal (left\n // pane, saved-tests rail on the right) when open.\n const body = (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {paramsAndResult}\n {actionBar}\n </div>\n );\n // Host-embedded: the host owns the modal chrome, so fill it as a\n // full-height flex column — params + saved-tests rail scroll, the action\n // bar is pinned to the bottom as a non-scrolling footer.\n if (embedded) {\n return (\n <div className=\"w6w-tester-embedded\">\n <div className=\"w6w-tester-embedded-scroll\">\n {/* Card layout: params, result and (with a connection) saved\n tests + history each in a `.card`, stacked in one column. */}\n <div className=\"w6w-card-stack\">\n <div className=\"card\">\n <div className=\"section-head\">\n <h3>Parameters</h3>\n </div>\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {paramsRegion}\n {overridesRegion}\n {errorBox}\n </div>\n </div>\n {(resultBlock || apiCalls.length > 0) && (\n <div className=\"card\">\n <div className=\"section-head\">\n <h3>Result</h3>\n </div>\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {result !== undefined && <ResultViewer value={result} />}\n <ApiCallsPanel calls={apiCalls} />\n </div>\n </div>\n )}\n {savedTestsRail && (\n <div className=\"card\">\n <div className=\"section-head\">\n <h3>Saved tests and history</h3>\n </div>\n {savedTestsRail}\n </div>\n )}\n </div>\n </div>\n {actionBar}\n </div>\n );\n }\n return modalOpen ? (\n <Modal\n title={`Edit params — ${selectedAction.title ?? selectedAction.key}`}\n onClose={() => setModalOpen(false)}\n size=\"full\"\n >\n {/* The pop-out's own internal scroll boundary (T1.4.1 round 2): with\n `-full`'s `overflow: hidden` live, the dialog itself no longer\n scrolls, so params + result (+ the saved-tests rail) get a\n dedicated scroll region here and the action bar stays a pinned\n footer below it — mirrors `.w6w-tester-embedded-scroll`'s\n mechanism (see styles.css), just for this own-pop-out layout\n instead of the host-embedded one. */}\n <div className=\"w6w-tester-popout\">\n <div className=\"w6w-tester-popout-scroll\">\n {savedTestsRail ? (\n <div\n style={{\n display: \"flex\",\n gap: \"var(--w6w-sp-4)\",\n alignItems: \"flex-start\",\n }}\n >\n <div style={{ flex: 1, minWidth: 0 }}>{paramsAndResult}</div>\n <div style={{ width: 260, flexShrink: 0 }}>{savedTestsRail}</div>\n </div>\n ) : (\n paramsAndResult\n )}\n </div>\n {actionBar}\n </div>\n </Modal>\n ) : (\n body\n );\n })()}\n\n {nameModalOpen && (\n <Modal title=\"Save test\" onClose={() => setNameModalOpen(false)}>\n <form\n className=\"w6w-stack\"\n style={{ gap: \"var(--w6w-sp-3)\" }}\n onSubmit={(e) => {\n e.preventDefault();\n void submitSaveTest();\n }}\n >\n <label className=\"w6w-field\">\n <span>Name this saved test</span>\n <input\n type=\"text\"\n value={pendingName}\n placeholder=\"e.g. valid sender\"\n onChange={(e) => setPendingName(e.target.value)}\n />\n </label>\n {savedTestsError && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n {savedTestsError}\n </span>\n )}\n <div\n style={{ display: \"flex\", gap: \"var(--w6w-sp-2)\", justifyContent: \"flex-end\" }}\n >\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setNameModalOpen(false)}\n >\n Cancel\n </button>\n <button type=\"submit\" className=\"w6w-btn\" disabled={!pendingName.trim()}>\n Save\n </button>\n </div>\n </form>\n </Modal>\n )}\n\n {confirmDeleteOpen && (\n <ConfirmModal\n title=\"Delete saved test\"\n message={\n deletingTestName\n ? `Delete \"${deletingTestName}\"? This cannot be undone.`\n : \"Delete this saved test? This cannot be undone.\"\n }\n confirmLabel=\"Delete\"\n onConfirm={() => {\n setConfirmDeleteOpen(false);\n void deleteCurrentTest();\n }}\n onClose={() => setConfirmDeleteOpen(false)}\n />\n )}\n </>\n ) : (\n !action && <p className=\"w6w-muted w6w-small\">Pick an action above to test it.</p>\n )}\n </div>\n );\n}\n","import { yaml } from \"@codemirror/lang-yaml\";\nimport { EditorView } from \"@codemirror/view\";\nimport CodeMirror from \"@uiw/react-codemirror\";\nimport { useMemo } from \"react\";\nimport { CheckGlyph, CopyGlyph } from \"./components/Copyable.tsx\";\nimport { useCopyToClipboard } from \"./components/use-copy.ts\";\nimport { EDITOR_THEME_SPEC } from \"./editor-theme.ts\";\nimport { useEffectiveTheme } from \"./theme.ts\";\nimport type { ThemeMode } from \"./types.ts\";\n\nexport interface YamlEditorProps {\n value: string;\n onChange: (value: string) => void;\n\n /** Placeholder text shown when value is empty. */\n placeholder?: string;\n /** Minimum editor height. Defaults to \"240px\". */\n minHeight?: string;\n /** Maximum editor height before scrolling. Defaults to no cap. */\n maxHeight?: string;\n /**\n * Explicit editor height. Pass `\"100%\"` to fill a flex parent (the whole-config\n * \"code\" view). Omit to let the editor grow with its content between\n * `minHeight` and `maxHeight` — an inline YAML/group field wants this.\n */\n height?: string;\n\n /** Read-only mode — useful for previewing a stored definition. */\n readOnly?: boolean;\n\n /**\n * Explicit theme. If omitted, the editor auto-detects `data-theme` on\n * `<html>` and falls back to `prefers-color-scheme` — same behavior as\n * `<AppIcon>`. Uses CodeMirror's built-in one-dark for dark mode.\n */\n theme?: ThemeMode;\n\n /** Accessible label for the editor. */\n \"aria-label\"?: string;\n\n /**\n * Render an in-box copy-to-clipboard button, a direct child of this\n * component's own `.w6w-yaml-editor` wrapper (sibling to the CodeMirror\n * mount — no extra DOM node). Copies the current `value` verbatim.\n *\n * Off by default: the other mounts of this component must render byte-\n * identically to before this prop existed.\n */\n copyable?: boolean;\n}\n\n/**\n * YAML editor built on CodeMirror 6. Syntax highlighting, folding, gutter,\n * and line numbers. Themed with the `--w6w-*` custom properties so it\n * inherits from the consumer's palette.\n *\n * ```tsx\n * <YamlEditor value={text} onChange={setText} minHeight=\"320px\" />\n * ```\n */\nexport function YamlEditor(props: YamlEditorProps) {\n const theme = useEffectiveTheme(props.theme);\n // Only mounted when `copyable` is on, but the hook itself must run\n // unconditionally (Rules of Hooks) — it is inert (no button, no listener)\n // until `copy()` is actually invoked from the button below.\n const { copied, copy } = useCopyToClipboard(props.value);\n const extensions = useMemo(() => [yaml(), EditorView.theme(EDITOR_THEME_SPEC)], []);\n\n function handleChange(next: string) {\n props.onChange(next);\n }\n\n return (\n <div className=\"w6w-yaml-editor\" aria-label={props[\"aria-label\"] ?? \"YAML editor\"}>\n <CodeMirror\n value={props.value}\n onChange={handleChange}\n extensions={extensions}\n placeholder={props.placeholder}\n readOnly={props.readOnly}\n // `readOnly` alone only blocks CodeMirror's own transactions\n // (`EditorState.readOnly`) — it leaves the content DOM\n // `contenteditable=\"true\"`, so a screen reader / a11y test still sees\n // it as an editable field. `editable` is the separate switch that\n // actually sets `contenteditable` (`EditorView.editable`); tying it to\n // `readOnly` here makes the prop mean what its name says.\n editable={!props.readOnly}\n theme={theme}\n height={props.height}\n minHeight={props.minHeight ?? \"240px\"}\n maxHeight={props.maxHeight}\n basicSetup={{\n lineNumbers: true,\n foldGutter: true,\n highlightActiveLine: !props.readOnly,\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n }}\n />\n {props.copyable && (\n <>\n <button\n type=\"button\"\n className={`w6w-icon-btn w6w-copyable-btn${copied ? \" is-copied\" : \"\"}`}\n aria-label=\"Copy\"\n onClick={() => void copy()}\n >\n {copied ? <CheckGlyph /> : <CopyGlyph />}\n </button>\n {/* Same live-region convention as `Copyable.tsx:141-147`: the\n button's accessible name stays constant, so this announces the\n result. */}\n <span className=\"w6w-copyable-status\" aria-live=\"polite\">\n {copied ? \"Copied\" : \"\"}\n </span>\n </>\n )}\n </div>\n );\n}\n","import { Copyable } from \"./Copyable.tsx\";\n\n/** The single truncation marker every crop arm uses — matches\n * `studio/src/lib/page-title.ts:53-56`'s convention (one `…`, U+2026, never\n * three periods). */\nconst MARKER = \"…\";\n\n/**\n * Truncate `value` on a character budget, keeping `chars` VALUE characters and\n * adding {@link MARKER} on top (the marker is extra, not counted against\n * `chars`) — mirrors `page-title.ts`'s `clamp()` in STYLE (a single budget,\n * slice + marker, pure) but NOT its arithmetic: `clamp` slices at\n * `MAX - 1` so its marker counts inside the budget, which is the wrong shape\n * here (see `CopyableText.test.ts`'s fixture table).\n *\n * `chars` omitted, less than 1, or covering the whole value: returned as-is,\n * no marker.\n */\nexport function cropText(\n value: string,\n chars?: number,\n crop: \"start\" | \"end\" | \"middle\" = \"end\",\n): string {\n if (chars === undefined || chars < 1 || chars >= value.length) return value;\n\n if (crop === \"start\") {\n return `${MARKER}${value.slice(value.length - chars)}`;\n }\n if (crop === \"end\") {\n return `${value.slice(0, chars)}${MARKER}`;\n }\n\n // middle\n const head = Math.ceil(chars / 2);\n const tail = chars - head;\n return `${value.slice(0, head)}${MARKER}${value.slice(value.length - tail)}`;\n}\n\nexport interface CopyableTextProps {\n /** The full string. Always what gets written to the clipboard, regardless\n * of how much of it the cropped display shows. */\n value: string;\n /** How many VALUE characters to show. Omitted, `< 1`, or `>= value.length`\n * ⇒ shown in full. */\n chars?: number;\n /** Where the marker goes. Default `\"end\"`. */\n crop?: \"start\" | \"end\" | \"middle\";\n /** Accessible name of the copy button. Default \"Copy\" (per `Copyable`). */\n label?: string;\n className?: string;\n /** Forwarded to `Copyable`. See its own doc for the revert-delay caveat. */\n copiedMs?: number;\n}\n\n/**\n * A chrome-less, croppable copy-to-clipboard text — for a value too long to\n * show in full inline (an id, a token, a URL fragment) that still needs to be\n * copyable exactly.\n *\n * Composes `Copyable` rather than widening it (`Copyable`'s box chrome has 9\n * existing call sites depending on it) — `readOnly` + the\n * `.w6w-copyable--bare` modifier (`_copyable.scss`) strip the box, and the\n * FULL `value` is what `Copyable` receives, so a click always copies the\n * whole string even when the display is cropped. No `navigator.clipboard`\n * call lives in this file — that stays `Copyable`'s alone.\n */\nexport function CopyableText(props: CopyableTextProps) {\n const { value, chars, crop = \"end\", label, className, copiedMs } = props;\n const cropped = cropText(value, chars, crop);\n const classes = [\"w6w-copyable--bare\", className].filter(Boolean).join(\" \");\n\n return (\n <Copyable value={value} readOnly label={label} className={classes} copiedMs={copiedMs}>\n <span>{cropped}</span>\n </Copyable>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * The four health states a probe can report — a thin LOCAL copy of the RFC's\n * `HealthReport.state` union. `@w6w/ui` deliberately keeps a small literal type\n * here rather than depend on `@w6w/types`, so the display component stays a\n * pure-presentation leaf with no transport/spec coupling.\n */\nexport type HealthPillState = \"ok\" | \"degraded\" | \"down\" | \"unknown\";\n\nexport interface HealthStatusPillProps {\n /** Which health state to render — drives the colour + default label. */\n state: HealthPillState;\n /** Override the visible text (defaults to a humanised form of `state`). */\n label?: ReactNode;\n /** Accessible label for the pill (falls back to the visible text). */\n ariaLabel?: string;\n}\n\nconst DEFAULT_LABELS: Record<HealthPillState, string> = {\n ok: \"Operational\",\n degraded: \"Degraded\",\n down: \"Down\",\n unknown: \"Unknown\",\n};\n\n/**\n * A small, theme-aware status pill for a single health state.\n *\n * Renders a coloured dot + label using the `--w6w-health-*` tokens, so a host\n * can restyle every state by overriding those custom properties (see\n * `styles.css`). Colour is never the only signal — the text label carries the\n * same meaning for accessibility.\n */\nexport function HealthStatusPill({ state, label, ariaLabel }: HealthStatusPillProps) {\n const text = label ?? DEFAULT_LABELS[state];\n\n return (\n <span className={`w6w-health-pill w6w-health-pill-${state}`} aria-label={ariaLabel}>\n <span className=\"w6w-health-pill-dot\" aria-hidden=\"true\" />\n <span className=\"w6w-health-pill-label\">{text}</span>\n </span>\n );\n}\n","/**\n * The four states a single day of the strip can be in — a thin LOCAL copy of the\n * RFC's `HealthReport.state` union, exactly as `HealthStatusPill` keeps one. The\n * duplication is deliberate: it keeps `@w6w/ui` a pure-presentation leaf with no\n * transport/spec coupling, so nothing here has to move when the spec package does.\n *\n * There is no fifth state. A day on which the account made no calls at all is\n * `unknown`, never `ok` — an unverified day must never be presented as a healthy\n * one (`rfcs/healthcheck.md`: `unknown` ranks above `ok` for that reason).\n */\nexport type UptimeCellState = \"ok\" | \"degraded\" | \"down\" | \"unknown\";\n\n/** One cell: the day it stands for, and the state already decided for it. */\nexport interface UptimeDay {\n /** The day this cell represents, e.g. `2026-07-27`. Shown verbatim in the tooltip. */\n day: string;\n /** The state for that day. The strip renders it; it never decides it. */\n state: UptimeCellState;\n /** Tooltip override. Defaults to `<day> — <state label>`. */\n label?: string;\n}\n\nexport interface UptimeStripProps {\n /**\n * The days to render, oldest first, one cell each. The component makes no\n * assumption about how many there are — a caller showing a 30-day window\n * passes 30, and a younger account can pass fewer.\n */\n days: UptimeDay[];\n /**\n * Accessible label for the strip as a whole (it is exposed as one image, not\n * as N unlabelled boxes). Defaults to `<n>-day status`.\n */\n ariaLabel?: string;\n}\n\nconst STATE_LABELS: Record<UptimeCellState, string> = {\n ok: \"Operational\",\n degraded: \"Degraded\",\n down: \"Down\",\n unknown: \"Unknown\",\n};\n\n/**\n * A fixed-height strip of one cell per day, for \"how has this service behaved\n * lately\" at a glance.\n *\n * Purely presentational — it is handed an array of ALREADY-DECIDED states and\n * renders exactly those. No rules, no roll-up and no judgement about what counts\n * as broken live in this package; whatever decided the states owns that.\n *\n * Colour is never the only signal (same rule as `HealthStatusPill`, which pairs\n * its dot with a text label). Thirty cells cannot carry thirty labels, so the\n * strip signals twice in two other ways:\n * - every cell carries a `title` with its day and state, and\n * - the FILL HEIGHT encodes severity, so the row survives greyscale and\n * colour-blind viewing: `ok` is a short baseline bar, `degraded` a taller\n * one, `down` fills the cell, and `unknown` is a hatched outline with no\n * solid fill at all (nothing was measured — it is not a good day and not a\n * bad one).\n *\n * Colour itself comes from the shared `--w6w-health-*` tokens through the single\n * `--w6w-health-color` indirection the health pill uses, so a host that\n * overrides a token restyles the pill and the strip together.\n */\nexport function UptimeStrip({ days, ariaLabel }: UptimeStripProps) {\n if (days.length === 0) return null;\n\n return (\n <div\n className=\"w6w-uptime-strip\"\n role=\"img\"\n aria-label={ariaLabel ?? `${days.length}-day status`}\n >\n {days.map((entry, i) => (\n <span\n // Days are expected to be unique, but the index keeps the key stable\n // even if a caller repeats one — same guard as `ApiCallsPanel`.\n key={`${entry.day}-${i}`}\n className={`w6w-uptime-cell w6w-uptime-cell-${entry.state}`}\n title={entry.label ?? `${entry.day} — ${STATE_LABELS[entry.state]}`}\n />\n ))}\n </div>\n );\n}\n","/**\n * Pure formatting + geometry helpers for the server-resources family, kept in\n * their own module so they carry no React and can be unit-tested on their own.\n *\n * `ServerResourceSample` is a thin LOCAL copy of the sampler's wire sample\n * (`plan.md` §Pinned wire) — the same deliberate duplication `UptimeStrip.tsx`\n * keeps of the health union, and for the same reason: it keeps `@w6w/ui` a\n * pure-presentation leaf with no transport/spec coupling, so nothing here has\n * to move when the server's payload grows a field.\n *\n * Every helper is TOTAL: an unknown number is never rendered as `0`, it is\n * rendered as an em dash. A node whose CPU reading is missing must not read as\n * an idle node.\n */\n\n/** One sample of the host's resource usage, exactly as the server sends it. */\nexport interface ServerResourceSample {\n /** ISO-8601 instant the sample was taken. */\n ts: string;\n cpus: number | null;\n cpuLimit: number | null;\n load1: number | null;\n load5: number | null;\n load15: number | null;\n memoryTotal: number | null;\n memoryAvailable: number | null;\n memoryLimit: number | null;\n processRss: number | null;\n processHeapUsed: number | null;\n processHeapTotal: number | null;\n}\n\n/** What an unknown value renders as. Never `0`, never an empty cell. */\nconst UNKNOWN = \"—\";\n\n/** Binary magnitude suffixes, index-aligned with the 1024ᵏ divisor. */\nconst BYTE_UNITS = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\"] as const;\n\n/**\n * A byte count as a short human string: exact bytes below 1 KiB (`1023 B`),\n * one decimal place per binary magnitude from KiB up (`1.5 KiB`, `15.6 GiB`).\n * `null` (nothing measured) is `—`.\n */\nexport function formatBytes(n: number | null): string {\n if (n === null || !Number.isFinite(n)) return UNKNOWN;\n if (n < 1024) return `${Math.round(n)} B`;\n\n let value = n;\n let unit = 0;\n while (value >= 1024 && unit < BYTE_UNITS.length - 1) {\n value /= 1024;\n unit += 1;\n }\n return `${value.toFixed(1)} ${BYTE_UNITS[unit]}`;\n}\n\n/**\n * A 0…1-ish fraction as a whole-percent string (`0.123` → `12%`). Not clamped:\n * a load above the CPU count is real and reads `135%`. `null` is `—`.\n */\nexport function formatPercent(f: number | null): string {\n if (f === null || !Number.isFinite(f)) return UNKNOWN;\n return `${Math.round(f * 100)}%`;\n}\n\n/**\n * `load1` against the effective CPU budget — the container's `cpuLimit` when\n * the server set one, otherwise the host CPU count. `null` when either operand\n * is unknown or the divisor is ≤ 0 (a zero-CPU budget is not \"0% busy\", it is\n * \"not measurable\").\n */\nexport function cpuLoadFraction(s: ServerResourceSample | undefined): number | null {\n if (s === undefined) return null;\n if (s.load1 === null) return null;\n const divisor = s.cpuLimit ?? s.cpus;\n if (divisor === null || divisor <= 0) return null;\n return s.load1 / divisor;\n}\n\n/**\n * Used memory as a fraction of total: `(memoryTotal − memoryAvailable) /\n * memoryTotal`. `null` when either operand is unknown or the total is ≤ 0.\n */\nexport function memoryUsedFraction(s: ServerResourceSample | undefined): number | null {\n if (s === undefined) return null;\n const { memoryTotal, memoryAvailable } = s;\n if (memoryTotal === null || memoryAvailable === null) return null;\n if (memoryTotal <= 0) return null;\n return (memoryTotal - memoryAvailable) / memoryTotal;\n}\n\n/** `v` pinned into `[lo, hi]`. */\nfunction clamp(v: number, lo: number, hi: number): number {\n if (v < lo) return lo;\n return v > hi ? hi : v;\n}\n\n/**\n * The `points` attribute of a sparkline polyline, hand-drawn — this package\n * has no chart dependency on purpose (D-5), and a polyline over ~60 samples\n * does not justify one.\n *\n * The x axis is positional (`i / (n − 1) · width`), so a gap in the series\n * still advances the line; `y` is inverted (SVG grows downward) and scaled\n * against `max`. Nulls are SKIPPED, not plotted as zero, and a series of fewer\n * than two values has no line at all (`\"\"` — a single point is not a shape).\n * `max ≤ 0` flattens the line along the baseline rather than dividing by it.\n *\n * Every coordinate is rounded to two decimals so the attribute stays short and\n * a snapshot of it stays readable.\n */\nexport function sparklinePoints(\n values: readonly (number | null)[],\n width: number,\n height: number,\n max: number,\n): string {\n const n = values.length;\n if (n < 2) return \"\";\n\n const points: string[] = [];\n for (let i = 0; i < n; i++) {\n const v = values[i];\n if (v === null) continue;\n const x = (i / (n - 1)) * width;\n const y = max <= 0 ? height : height - (clamp(v, 0, max) / max) * height;\n points.push(`${Number(x.toFixed(2))},${Number(y.toFixed(2))}`);\n }\n return points.join(\" \");\n}\n","/**\n * The server-resources display family — four PURE PRESENTATIONAL variants over\n * the same array of samples: a large card, a small card, a left-rail strip and\n * a header badge.\n *\n * There is no data layer here, on purpose (plan.md §Pinned decisions: \"no\n * transport in ui\"): every variant is handed `samples` and renders the LAST\n * one, plus a sparkline drawn from the whole array. Nothing in this file reads\n * a network, a context or a host API — the caller owns the stream and the\n * operator gate.\n *\n * The sparkline is hand-rolled inline SVG rather than a chart dependency: a\n * polyline over ~60 points is a dozen lines of arithmetic (see\n * `sparklinePoints`), and `@w6w/ui` carrying recharts or d3 for it would be\n * unjustified weight for every consumer (D-5).\n *\n * An unknown value is never rendered as `0` — it is the em dash `formatBytes` /\n * `formatPercent` return for `null`. An unreported CPU reading must not read as\n * an idle node. The same applies to `samples: []`: every variant still renders\n * (all dashes, no line), so a caller never has to branch before mounting.\n */\nimport {\n type ServerResourceSample,\n cpuLoadFraction,\n formatBytes,\n formatPercent,\n memoryUsedFraction,\n sparklinePoints,\n} from \"./server-resources-format.ts\";\n\nexport interface ServerResourcesProps {\n /**\n * The samples to render, oldest first. The LAST entry is the current reading;\n * the whole array is the sparkline's series. May be empty — then every value\n * reads `—` and no line is drawn.\n */\n samples: readonly ServerResourceSample[];\n}\n\nexport interface ServerResourcesCardProps extends ServerResourcesProps {\n /** Heading text. Defaults to `Server resources`. */\n title?: string;\n /** The sampler's cadence, in ms. When given, the card shows `Sampled every Ns`. */\n intervalMs?: number;\n}\n\nexport interface ServerResourcesRailProps extends ServerResourcesProps {\n /**\n * When given, the rail shows one button that asks the caller to open the full\n * view. The rail never opens anything itself — mounting is the caller's job.\n */\n onExpand?: () => void;\n}\n\n/** What an unknown value renders as — the same dash the format helpers return. */\nconst UNKNOWN = \"—\";\n\n/** Sparkline geometry. The viewBox is 100 × 24 units, scaled by CSS. */\nconst SPARK_WIDTH = 100;\nconst SPARK_HEIGHT = 24;\n\n/** The sparkline. Deliberately NOT the shared `Icon` (`../components/Icon.tsx`):\n * nothing here is a fixed glyph — `points` is computed from the data, the\n * viewBox is this chart's own 100 × 24 units (scaled by CSS) rather than a\n * 24 × 24 icon box, and the stroke is the accent token, not `currentColor`. */\nfunction Sparkline({\n values,\n max,\n className,\n}: {\n values: readonly (number | null)[];\n max: number;\n className: string;\n}) {\n const points = sparklinePoints(values, SPARK_WIDTH, SPARK_HEIGHT, max);\n if (points === \"\") return null;\n\n return (\n <svg\n className={className}\n viewBox={`0 0 ${SPARK_WIDTH} ${SPARK_HEIGHT}`}\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <polyline\n points={points}\n fill=\"none\"\n stroke=\"var(--w6w-accent)\"\n strokeWidth={2}\n vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n );\n}\n\n/**\n * A fraction as a two-decimal string (`0.5` → `0.50`), or `—` when unknown.\n * The fixed precision is what keeps the three load averages visually aligned.\n */\nfunction formatLoad(n: number | null): string {\n return n === null ? UNKNOWN : n.toFixed(2);\n}\n\n/**\n * The largest value a series of fractions is drawn against — at least 1, so a\n * quiet host draws a flat-ish line near the baseline instead of amplifying\n * its own noise to a full-height sawtooth.\n */\nfunction fractionMax(values: readonly (number | null)[]): number {\n let max = 1;\n for (const v of values) if (v !== null && v > max) max = v;\n return max;\n}\n\n/** A labelled reading plus the sparkline of its series. */\nfunction MetricRow({\n label,\n value,\n values,\n max,\n}: {\n label: string;\n value: string;\n values: readonly (number | null)[];\n max: number;\n}) {\n return (\n <li className=\"w6w-server-resources__row\">\n <span className=\"w6w-server-resources__label\">{label}</span>\n <span className=\"w6w-server-resources__value\">{value}</span>\n <Sparkline className=\"w6w-server-resources__spark\" values={values} max={max} />\n </li>\n );\n}\n\n/** The one-sample readings every variant shows, computed once per render. */\nfunction readings(samples: readonly ServerResourceSample[]) {\n const last = samples[samples.length - 1];\n const cpuValues = samples.map((s) => cpuLoadFraction(s));\n const memoryValues = samples.map((s) => memoryUsedFraction(s));\n const rssValues = samples.map((s) => s.processRss);\n return { last, cpuValues, memoryValues, rssValues };\n}\n\n/**\n * The large variant: three readings (CPU, memory, process RSS), each with its\n * own sparkline, plus the load averages and — when the caller knows it — the\n * sampling cadence. This is the Console/Modal body.\n */\nexport function ServerResourcesCard({\n samples,\n title = \"Server resources\",\n intervalMs,\n}: ServerResourcesCardProps) {\n const { last, cpuValues, memoryValues, rssValues } = readings(samples);\n\n return (\n <section className=\"w6w-server-resources w6w-server-resources--card\" aria-label={title}>\n <h3 className=\"w6w-server-resources__title\">{title}</h3>\n <ul className=\"w6w-server-resources__rows\">\n <MetricRow\n label=\"CPU\"\n value={formatPercent(cpuLoadFraction(last))}\n values={cpuValues}\n max={fractionMax(cpuValues)}\n />\n <MetricRow\n label=\"Memory\"\n value={formatPercent(memoryUsedFraction(last))}\n values={memoryValues}\n max={1}\n />\n <MetricRow\n label=\"Process\"\n value={formatBytes(last?.processRss ?? null)}\n values={rssValues}\n max={fractionMax(rssValues)}\n />\n </ul>\n <p className=\"w6w-server-resources__meta\">\n {`Load ${formatLoad(last?.load1 ?? null)} / ${formatLoad(last?.load5 ?? null)} / ${formatLoad(\n last?.load15 ?? null,\n )}`}\n </p>\n {intervalMs !== undefined && (\n <p className=\"w6w-server-resources__meta\">{`Sampled every ${intervalMs / 1000}s`}</p>\n )}\n </section>\n );\n}\n\n/**\n * The small variant: CPU and memory only, one sparkline (CPU). For a compact\n * surface that has room for a headline and a shape, but not for a third\n * reading or the load breakdown.\n */\nexport function ServerResourcesCardSmall({ samples, title = \"Server\" }: ServerResourcesCardProps) {\n const { last, cpuValues } = readings(samples);\n\n return (\n <section className=\"w6w-server-resources w6w-server-resources--small\" aria-label={title}>\n <h3 className=\"w6w-server-resources__title\">{title}</h3>\n <ul className=\"w6w-server-resources__rows\">\n <MetricRow\n label=\"CPU\"\n value={formatPercent(cpuLoadFraction(last))}\n values={cpuValues}\n max={fractionMax(cpuValues)}\n />\n <li className=\"w6w-server-resources__row\">\n <span className=\"w6w-server-resources__label\">Memory</span>\n <span className=\"w6w-server-resources__value\">\n {formatPercent(memoryUsedFraction(last))}\n </span>\n </li>\n </ul>\n </section>\n );\n}\n\n/**\n * The left-rail variant: a stacked CPU and MEM reading, each with a sparkline,\n * sized to fit a ~200 px column. When the caller passes `onExpand` it also\n * shows the single \"show me the rest\" button; without one it is read-only\n * decoration and renders no interactive element at all.\n */\nexport function ServerResourcesRail({ samples, onExpand }: ServerResourcesRailProps) {\n const { last, cpuValues, memoryValues } = readings(samples);\n\n return (\n <aside className=\"w6w-server-resources w6w-server-resources--rail\">\n <div className=\"w6w-server-resources__rail-row\">\n <span className=\"w6w-server-resources__label\">CPU</span>\n <span className=\"w6w-server-resources__value\">{formatPercent(cpuLoadFraction(last))}</span>\n <Sparkline\n className=\"w6w-server-resources__spark\"\n values={cpuValues}\n max={fractionMax(cpuValues)}\n />\n </div>\n <div className=\"w6w-server-resources__rail-row\">\n <span className=\"w6w-server-resources__label\">MEM</span>\n <span className=\"w6w-server-resources__value\">\n {formatPercent(memoryUsedFraction(last))}\n </span>\n <Sparkline className=\"w6w-server-resources__spark\" values={memoryValues} max={1} />\n </div>\n {onExpand !== undefined && (\n <button\n type=\"button\"\n className=\"w6w-server-resources__expand\"\n aria-label=\"Show server resources\"\n onClick={onExpand}\n >\n Details\n </button>\n )}\n </aside>\n );\n}\n\n/**\n * The header badge: one line, `CPU <pct> · MEM <pct>`, no sparkline (a badge is\n * a fixed-height strip of text, and a line there would be unreadable). The\n * whole string is a single text node so assistive tech reads it as one phrase.\n */\nexport function ServerResourcesBadge({ samples }: ServerResourcesProps) {\n const last = samples[samples.length - 1];\n const cpu = formatPercent(cpuLoadFraction(last));\n const mem = formatPercent(memoryUsedFraction(last));\n\n return (\n <span className=\"w6w-server-resources w6w-server-resources--badge\">\n {`CPU ${cpu} · MEM ${mem}`}\n </span>\n );\n}\n","/**\n * Pure geometry for `HistoryTimeline`'s vendor lane — positioning a vendor\n * incident bar on the SAME percentage scale the execution lane's day cells\n * use, so the two series can never drift apart (`HistoryTimeline.tsx`'s\n * alignment invariant). Deliberately split out of the component: a function\n * that reads a clock itself makes that invariant unobservable to a gate, so\n * `nowMs` is always a parameter here, never `Date.now()`.\n *\n * No JSX, no React import — this file is imported directly by its own test\n * (`__tests__/HistoryTimeline.test.ts`) with no transpile step.\n */\nimport type { HistoryWindow, VendorIncidentBar } from \"./HistoryTimeline.tsx\";\n\n/**\n * Minimum visible width for a bar, as a percentage of the window's span. A\n * point-in-time entry (no `startedAt`) has zero duration and would otherwise\n * be invisible; a very short span is floored to the same width so it never\n * shrinks below it either.\n */\nexport const MIN_BAR_WIDTH_PCT = 1;\n\nexport interface BarPlacement {\n /** Left edge, as a percentage of the window's span, clamped to `[0, 100]`. */\n leftPct: number;\n /** Width, as a percentage of the window's span. Never below `MIN_BAR_WIDTH_PCT`. */\n widthPct: number;\n /** `true` if the bar's start was clamped to the window's left edge. */\n clippedStart: boolean;\n /** `true` if the bar's end was clamped to the window's right edge. */\n clippedEnd: boolean;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Places one vendor incident bar on the window's `[from T00:00:00Z, to+1 day\n * T00:00:00Z)` span.\n *\n * - A bar's start is `startedAt ?? updatedAt`; with neither present there is\n * nothing to place, so this returns `null` (B5).\n * - Its end is `resolvedAt ?? (startedAt !== undefined ? nowMs : start)` — an\n * open incident (has `startedAt`, no `resolvedAt`) therefore runs to\n * `nowMs`, and a feed-only entry with no `startedAt` is a point in time,\n * not a span (B3).\n * - A bar wholly outside the window (ends before it starts, or starts at or\n * after it ends) returns `null` (B4). One overlapping an edge is clamped\n * into the window, with `clippedStart`/`clippedEnd` set accordingly.\n */\nexport function placeIncidentBar(\n window: HistoryWindow,\n bar: VendorIncidentBar,\n nowMs: number,\n): BarPlacement | null {\n const start = bar.startedAt ?? bar.updatedAt;\n if (start === undefined) return null;\n\n const startMs = Date.parse(start);\n const endMs =\n bar.resolvedAt !== undefined\n ? Date.parse(bar.resolvedAt)\n : bar.startedAt !== undefined\n ? nowMs\n : startMs;\n\n const windowStartMs = Date.parse(`${window.from}T00:00:00.000Z`);\n const windowEndMs = Date.parse(`${window.to}T00:00:00.000Z`) + DAY_MS;\n const spanMs = windowEndMs - windowStartMs;\n\n if (endMs < windowStartMs || startMs >= windowEndMs) return null;\n\n const clippedStart = startMs < windowStartMs;\n const clippedEnd = endMs > windowEndMs;\n\n // The clamp to [0, 100] (B2) happens HERE, on the raw timestamps, and is\n // the ONLY place either bound is clamped — `leftPct`/`widthPct` below are\n // plain arithmetic on the clamped values, so there is no second, redundant\n // clamp for a mutation to skip past undetected.\n const clampedStartMs = Math.max(startMs, windowStartMs);\n const clampedEndMs = Math.min(endMs, windowEndMs);\n\n const leftPct = ((clampedStartMs - windowStartMs) / spanMs) * 100;\n const rawWidthPct = ((clampedEndMs - clampedStartMs) / spanMs) * 100;\n const widthPct = Math.max(rawWidthPct, MIN_BAR_WIDTH_PCT);\n\n return { leftPct, widthPct, clippedStart, clippedEnd };\n}\n","import type { UptimeCellState, UptimeDay } from \"./UptimeStrip.tsx\";\nimport { placeIncidentBar } from \"./history-scale.ts\";\n\n/** The calendar window both lanes are plotted against. Both bounds inclusive. */\nexport interface HistoryWindow {\n /** Inclusive first calendar day, `YYYY-MM-DD`. */\n from: string;\n /** Inclusive last calendar day, `YYYY-MM-DD`. */\n to: string;\n}\n\n/** One entry in the vendor's incident feed. */\nexport interface VendorIncidentBar {\n id?: string;\n title: string;\n state: UptimeCellState;\n /** ISO instant. Absent = a point-in-time update, not a span. */\n startedAt?: string;\n updatedAt?: string;\n /** ISO instant. Absent WITH `startedAt` present = still open. */\n resolvedAt?: string;\n components?: string[];\n link?: string;\n}\n\nexport interface HistoryTimelineProps {\n window: HistoryWindow;\n /** Execution lane, oldest first, one entry per calendar day. */\n days: UptimeDay[];\n /** Vendor lane. `undefined` = this vendor publishes no incident history at all. */\n incidents?: VendorIncidentBar[];\n /** Overrides the vendor lane's empty text. */\n vendorEmptyLabel?: string;\n /** Clock injection for tests and for an open incident's right edge. Defaults to `Date.now()`. */\n nowMs?: number;\n ariaLabel?: string;\n}\n\nconst STATE_LABELS: Record<UptimeCellState, string> = {\n ok: \"Operational\",\n degraded: \"Degraded\",\n down: \"Down\",\n unknown: \"Unknown\",\n};\n\nconst NO_FEED_LABEL = \"This vendor publishes no incident history.\";\nconst QUIET_LABEL = \"No incidents in this window.\";\n\nfunction barTitle(bar: VendorIncidentBar): string {\n const start = bar.startedAt ?? bar.updatedAt;\n const parts = [bar.title];\n if (bar.components !== undefined && bar.components.length > 0) {\n parts.push(`(${bar.components.join(\", \")})`);\n }\n if (start !== undefined) {\n parts.push(\n bar.resolvedAt !== undefined ? `${start} – ${bar.resolvedAt}` : `${start} – ongoing`,\n );\n }\n return parts.join(\" \");\n}\n\n/**\n * Two time series — our per-day execution history and the vendor's incident\n * history — plotted on one shared x-axis, so \"our calls failed *during* that\n * vendor incident\" is a visible alignment rather than a claim.\n *\n * Purely presentational, same discipline as `UptimeStrip`: `days` is already\n * one already-decided state per calendar day (no sort, no reverse, no gap\n * fill), and `incidents` is already the vendor's own feed. This component\n * places them; it makes no judgement about what counts as an incident.\n *\n * `incidents === undefined` (\"this vendor publishes no incident history\") and\n * `incidents === []` (\"nothing happened in this window\") are different facts\n * and render different empty-row text — Stripe is the first, a quiet Slack\n * window is the second. Either way the axis and the execution lane render in\n * full, at full width: a vendor with no feed never shrinks the half of the\n * chart that does have data.\n *\n * Severity is encoded twice, same rule as `UptimeStrip` and `HealthStatusPill`:\n * a per-state class AND a geometry difference (fill height on a day cell,\n * clip markers on a bar), never colour alone. Every cell and every bar\n * carries a `title`.\n */\nexport function HistoryTimeline({\n window: win,\n days,\n incidents,\n vendorEmptyLabel,\n nowMs = Date.now(),\n ariaLabel,\n}: HistoryTimelineProps) {\n const n = days.length;\n const cellWidthPct = n > 0 ? 100 / n : 0;\n\n const emptyLabel =\n incidents === undefined\n ? (vendorEmptyLabel ?? NO_FEED_LABEL)\n : incidents.length === 0\n ? (vendorEmptyLabel ?? QUIET_LABEL)\n : null;\n\n return (\n <div className=\"w6w-history-timeline\" role=\"img\" aria-label={ariaLabel ?? `${n}-day history`}>\n <div className=\"w6w-history-plot\">\n <div className=\"w6w-history-lane w6w-history-lane-execution\">\n {days.map((entry, i) => (\n <span\n // Days are expected to be unique, but the index keeps the key\n // stable even if a caller repeats one — same guard `UptimeStrip` uses.\n key={`${entry.day}-${i}`}\n className={`w6w-history-cell w6w-history-cell-${entry.state}`}\n style={{ left: `${i * cellWidthPct}%`, width: `${cellWidthPct}%` }}\n title={entry.label ?? `${entry.day} — ${STATE_LABELS[entry.state]}`}\n />\n ))}\n </div>\n <div className=\"w6w-history-lane w6w-history-lane-vendor\">\n {emptyLabel !== null ? (\n <span className=\"w6w-history-empty\" title={emptyLabel}>\n {emptyLabel}\n </span>\n ) : (\n incidents?.map((bar, i) => {\n const placement = placeIncidentBar(win, bar, nowMs);\n if (placement === null) return null;\n const clipClass = [\n placement.clippedStart ? \"w6w-history-bar-clip-start\" : \"\",\n placement.clippedEnd ? \"w6w-history-bar-clip-end\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n return (\n <span\n key={bar.id ?? `${bar.title}-${i}`}\n className={`w6w-history-bar w6w-history-bar-${bar.state}${clipClass ? ` ${clipClass}` : \"\"}`}\n style={{ left: `${placement.leftPct}%`, width: `${placement.widthPct}%` }}\n title={barTitle(bar)}\n />\n );\n })\n )}\n </div>\n <div className=\"w6w-history-axis\">\n <span className=\"w6w-history-tick w6w-history-tick-start\" style={{ left: \"0%\" }}>\n {win.from}\n </span>\n <span className=\"w6w-history-tick w6w-history-tick-end\" style={{ left: \"100%\" }}>\n {win.to}\n </span>\n </div>\n </div>\n </div>\n );\n}\n","import { type ReactNode, useId, useState } from \"react\";\nimport { IconButton } from \"./IconButton.tsx\";\n\nexport interface InfoTipProps {\n /** Accessible name AND tooltip of the toggle button (e.g. \"About client secrets\"). */\n label: string;\n /** The explanation, rendered only while expanded. */\n children: ReactNode;\n className?: string;\n}\n\n/**\n * A small \"i\" button that reveals a muted explanation block on click — for\n * copy that would otherwise clutter a modal. Collapsed by default; the button\n * carries `aria-expanded` and `aria-controls` pointing at the block, and the\n * block is not rendered at all while collapsed.\n */\nexport function InfoTip({ label, children, className }: InfoTipProps) {\n const [open, setOpen] = useState(false);\n const id = useId();\n return (\n <span className={[\"w6w-info-tip\", className ?? \"\"].filter(Boolean).join(\" \")}>\n <IconButton\n label={label}\n icon=\"info\"\n aria-expanded={open}\n aria-controls={id}\n onClick={() => setOpen((o) => !o)}\n />\n {open && (\n <span id={id} className=\"w6w-info-tip-body w6w-muted w6w-small\">\n {children}\n </span>\n )}\n </span>\n );\n}\n","import { IconButton } from \"./IconButton.tsx\";\n\nexport interface EditButtonProps {\n label: string;\n onClick: () => void;\n disabled?: boolean;\n className?: string;\n \"data-testid\"?: string;\n}\n\n/** An `IconButton` bundling the canonical pencil glyph — `icons.tsx`'s `edit`,\n * the two-path Feather pencil — with no `danger` styling. */\nexport function EditButton(props: EditButtonProps) {\n const { label, onClick, disabled, className, ...rest } = props;\n return (\n <IconButton\n label={label}\n onClick={onClick}\n disabled={disabled}\n className={className}\n icon=\"edit\"\n data-testid={rest[\"data-testid\"]}\n />\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { Icon } from \"./Icon.tsx\";\n\nexport interface RepoSyncIndicatorProps {\n /** Branch name, e.g. \"main\". */\n branch: string;\n /** Already-shortened commit sha (the consumer formats it — D-6). `null` renders no sha. */\n shortSha: string | null;\n /** Already-formatted last-sync text, e.g. \"3/9/2026, 12:16:29 PM\" or \"Never synced\".\n * `null` renders no time row. */\n lastSyncLabel: string | null;\n /** Fired when the flyout's \"Sync now\" item is activated. The consumer owns the mutation. */\n onSyncNow: () => void;\n /** True while the consumer's sync is in flight. */\n syncing?: boolean;\n className?: string;\n \"data-testid\"?: string;\n}\n\n/**\n * A compact header control showing a repo glyph, a branch name and a short\n * commit sha, with an inline flyout menu carrying the sync detail and a\n * \"Sync now\" action the consumer wires.\n *\n * `@w6w/ui` never fetches and holds no studio policy\n * (`studio/src/ui/ExpressionScope.tsx:40-41`, extended by D-6) — this\n * component takes already-formatted strings and a callback.\n *\n * The open/close + outside-click + Escape state machine mirrors\n * `studio/src/components/Layout.tsx:222-328`'s `ProjectMenu()` (D-3: no\n * shared Menu/Popover/Dropdown primitive — there is exactly one consumer).\n */\nexport function RepoSyncIndicator(props: RepoSyncIndicatorProps) {\n const { branch, shortSha, lastSyncLabel, onSyncNow, syncing, className, ...rest } = props;\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onDown = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && setOpen(false);\n document.addEventListener(\"mousedown\", onDown);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"mousedown\", onDown);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [open]);\n\n return (\n <div\n className={`w6w-repo-sync${className ? ` ${className}` : \"\"}`}\n ref={ref}\n data-testid={rest[\"data-testid\"]}\n >\n <button\n type=\"button\"\n className=\"w6w-repo-sync-trigger\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-busy={syncing}\n onClick={() => setOpen((v) => !v)}\n >\n <span className=\"w6w-repo-sync-icon\">\n {/* The connection provider's mark — `icons.tsx`'s `github` (`RepoBinding.provider`\n is always `\"github\"` today), 16px, the set's default. */}\n <Icon name=\"github\" />\n {/* The in-flight badge over the mark while `syncing`: `icons.tsx`'s `sync`\n (Feather `refresh-cw`), shrunk to 10×10 for this corner use and spun by\n `.w6w-repo-sync-spin`, which `Icon` merges with `w6w-icon`. */}\n {syncing && <Icon name=\"sync\" size={10} className=\"w6w-repo-sync-spin\" />}\n </span>\n <span className=\"w6w-repo-sync-branch\">{branch}</span>\n {shortSha != null && <code className=\"w6w-repo-sync-sha\">{shortSha}</code>}\n </button>\n {open && (\n <div className=\"w6w-repo-sync-menu\" role=\"menu\">\n <div className=\"w6w-repo-sync-detail\">\n <span>{branch}</span>\n {shortSha != null && <code>{shortSha}</code>}\n {lastSyncLabel != null && <span>{lastSyncLabel}</span>}\n </div>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"w6w-repo-sync-item\"\n data-testid=\"repo-sync-now\"\n disabled={syncing}\n onClick={onSyncNow}\n >\n {syncing ? \"Syncing…\" : \"Sync now\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * The five states a workflow step's execution can be in — a thin LOCAL copy\n * of the workflow spec's `StepStatus` union\n * (`packages/w6w-workflow/packages/types/mod.ts`). `@w6w/ui` deliberately\n * keeps a small literal type here rather than depend on `@w6w/workflow-types`,\n * so this stays a pure-presentation leaf with no transport/spec coupling —\n * the same precedent `HealthStatusPill`'s `HealthPillState` establishes.\n */\nexport type StepStatus = \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n\n/**\n * Why a `skipped` step did not run — the engine's `NodeExecution.skipReason`, again a thin\n * LOCAL literal. `not_on_path`: the step is not downstream of the fired trigger (or outside a\n * run-from-node scope), so it was never part of the run; the other three are real skips. A\n * record from before the engine stamped reasons has none.\n */\nexport type SkipReason = \"not_on_path\" | \"condition\" | \"stopped\" | \"disabled\";\n\n/**\n * The five states a whole EXECUTION (an invocation, an endpoint call, a\n * workflow run) can be in — the run-level sibling of `StepStatus`, and again a\n * thin LOCAL literal rather than an import of any spec/wire type. The two\n * unions differ exactly where runs and steps differ: a run can be `queued`\n * before it starts and `canceled` after it started, while a step inside a run\n * can be `pending` or `skipped` (a run is never either). They are deliberately\n * NOT merged into one five/six-member union — `ExecutionList` and the step\n * panel must each accept only their own vocabulary.\n */\nexport type ExecutionStatus = \"queued\" | \"running\" | \"succeeded\" | \"failed\" | \"canceled\";\n\nexport interface StepStatusPillProps {\n /**\n * Which state to render — drives the colour + default label. Accepts both\n * vocabularies: a workflow step's `StepStatus` and a whole run's\n * `ExecutionStatus` (the pill is only a coloured label, so it does not care\n * which of the two a host is describing).\n */\n state: StepStatus | ExecutionStatus;\n /** Override the visible text (defaults to a humanised form of `state`). */\n label?: ReactNode;\n /** Accessible label for the pill (falls back to the visible text). */\n ariaLabel?: string;\n}\n\nconst DEFAULT_LABELS: Record<StepStatus | ExecutionStatus, string> = {\n pending: \"Pending\",\n running: \"Running\",\n succeeded: \"Succeeded\",\n failed: \"Failed\",\n skipped: \"Skipped\",\n queued: \"Queued\",\n canceled: \"Canceled\",\n};\n\n/**\n * A small, theme-aware status pill for one workflow step's execution state.\n *\n * Mirrors `HealthStatusPill` shape for shape: a state union, a\n * `DEFAULT_LABELS` record, a coloured dot + text label using one\n * `--w6w-step-color` custom property per modifier class, and the\n * `w6w-step-pill w6w-step-pill-${state}` className convention. Colour is\n * never the only signal — the text label carries the same meaning for\n * accessibility. Five states rather than `HealthStatusPill`'s four, so this\n * is a mirror of that shape, not a shared implementation.\n *\n * Renders BOTH vocabularies through the one prop: `StepStatus` (a step inside\n * a run) and `ExecutionStatus` (a whole run). The union is widened at the\n * PROP only — `StepStatus` itself is unchanged, so the step panel's own type\n * cannot silently grow run-only states.\n */\nexport function StepStatusPill({ state, label, ariaLabel }: StepStatusPillProps) {\n const text = label ?? DEFAULT_LABELS[state];\n\n return (\n <span className={`w6w-step-pill w6w-step-pill-${state}`} aria-label={ariaLabel}>\n <span className=\"w6w-step-pill-dot\" aria-hidden=\"true\" />\n <span className=\"w6w-step-pill-label\">{text}</span>\n </span>\n );\n}\n","/**\n * Pure duration/time formatters for the execution-history family, kept in\n * their own module so they carry no React and can be unit-tested on their own\n * — the same split `server-resources-format.ts` establishes.\n *\n * Both are TOTAL: a duration that was never measured (a still-running or\n * queued run) is rendered as an em dash, never as `0 ms` — \"unknown\" must not\n * read as \"instant\".\n */\n\n/** What an unmeasured/unknown value renders as. Never `0`. */\nconst UNKNOWN = \"—\";\n\nconst MS_PER_SECOND = 1000;\nconst MS_PER_MINUTE = 60_000;\n\n/**\n * A run duration as a short human string: whole milliseconds below a second\n * (`999 ms`), one decimal place in seconds below a minute (`1.5 s`), and\n * `2m 5s` from a minute up. `null`/`undefined` (nothing measured), `NaN` and\n * negatives are all `—`.\n */\nexport function formatDurationMs(ms: number | null | undefined): string {\n if (ms == null || !Number.isFinite(ms) || ms < 0) return UNKNOWN;\n if (ms < MS_PER_SECOND) return `${Math.round(ms)} ms`;\n if (ms < MS_PER_MINUTE) return `${(ms / MS_PER_SECOND).toFixed(1)} s`;\n return `${Math.floor(ms / MS_PER_MINUTE)}m ${Math.round((ms % MS_PER_MINUTE) / MS_PER_SECOND)}s`;\n}\n\n/**\n * An ISO-8601 instant as a short, locale-formatted date+time (`Sep 22, 2026,\n * 10:00 AM` under the default locale). The locale is the HOST's\n * (`undefined`), so the string follows the viewer's own settings rather than\n * baking one in. A string `Date` cannot parse is returned UNCHANGED — an\n * unrenderable timestamp is shown as the wire value, never as \"Invalid Date\".\n */\nexport function formatExecutionTime(iso: string): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return iso;\n return date.toLocaleString(undefined, { dateStyle: \"medium\", timeStyle: \"short\" });\n}\n","import type { ReactNode } from \"react\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { ListItem } from \"./ListItem.tsx\";\nimport type { ExecutionStatus } from \"./StepStatusPill.tsx\";\nimport { StepStatusPill } from \"./StepStatusPill.tsx\";\nimport { formatDurationMs, formatExecutionTime } from \"./execution-format.ts\";\n\n/** What kind of callable a run belongs to. A thin LOCAL literal — the same\n * deliberate duplication `StepStatusPill`'s unions keep. */\nexport type ExecutionKind = \"function\" | \"endpoint\" | \"workflow\";\n\n/** One past execution's display row — an already-mapped slice of the host's\n * history payload. The HOST maps its own record into this shape (the same\n * \"host owns the data, the list is presentational\" split `ExecutionLogPanel`\n * establishes): this component never fetches, paginates or reaches for an SDK. */\nexport interface ExecutionListItem {\n /** Stable id for this row — what `onSelect` reports and `selectedId` matches. */\n id: string;\n kind: ExecutionKind;\n /** The callable's name/key this run belongs to. */\n callableName: string;\n status: ExecutionStatus;\n /** ISO-8601 instant the run started. */\n startedAt: string;\n /** Wall-clock duration once the run has finished; `null` while it is still\n * queued/running (rendered as `—`). */\n durationMs: number | null;\n /** The execution this one is a re-run of — the row then carries a \"Re-run\"\n * tag. `null`/omitted ⇒ an ordinary execution. */\n rerunOf?: string | null;\n /** How the run was started (`manual`, `schedule`, `webhook`, `event`, `replay`, or any other\n * value the host passes through). `null`/omitted ⇒ no trigger segment. */\n trigger?: string | null;\n /** The trigger node the run entered through, shown beside the trigger. */\n triggerNodeId?: string | null;\n /** The start of the run's input as JSON text, shown as a one-line snippet. `null`/omitted ⇒\n * no snippet. */\n inputPreview?: string | null;\n}\n\nexport interface ExecutionListProps {\n /** The page of past executions, rendered in exactly this order — never re-sorted. */\n items: ExecutionListItem[];\n /** The row to highlight as current. `null`/omitted ⇒ no row is active. */\n selectedId?: string | null;\n /** Supplied ⇒ rows are clickable and report their id here. Omitted ⇒ every\n * row is a plain, non-interactive row. */\n onSelect?: (id: string) => void;\n /**\n * `true` ⇒ each row's title is the callable's name and its subtitle carries\n * the kind + start time (the project-wide history view). `false` ⇒ the title\n * is the start time and the subtitle is the run id (the per-callable view,\n * where the callable is already known). Defaults to `false`.\n */\n showCallable?: boolean;\n /** `true` ⇒ the loading branch while there is nothing to show yet. */\n loading?: boolean;\n /** Shown instead of the list when `items` is empty. */\n emptyLabel?: ReactNode;\n /** Whether a previous page exists — drives the pager's `Previous` state. */\n hasPrev?: boolean;\n /** Whether a next page exists — drives the pager's `Next` state. */\n hasNext?: boolean;\n /** Supplied ⇒ the pager renders and `Previous` calls this. */\n onPrev?: () => void;\n /** Supplied ⇒ the pager renders and `Next` calls this. */\n onNext?: () => void;\n /** Supplied ⇒ every row gets a \"Re-run\" control beside it that reports the\n * row's id here. Omitted ⇒ no control. */\n onRerun?: (id: string) => void;\n /** The row whose re-run is in flight — its control is disabled. While any\n * re-run is in flight every row's control is disabled, so two can never\n * overlap. `null`/omitted ⇒ none. */\n rerunningId?: string | null;\n}\n\n/** Row subtitle's kind prefix, in the `showCallable` view. */\nconst KIND_LABEL: Record<ExecutionKind, string> = {\n function: \"Function\",\n endpoint: \"Endpoint\",\n workflow: \"Workflow\",\n};\n\n/** Known trigger kinds' labels; any other value is shown as given. */\nconst TRIGGER_LABEL: Record<string, string> = {\n manual: \"Manual\",\n schedule: \"Schedule\",\n webhook: \"Webhook\",\n event: \"Event\",\n replay: \"Replay\",\n};\n\n/** The row's trigger segment — `Event · order_placed_1` — or `null` when the host gave none. */\nfunction triggerText(item: ExecutionListItem): string | null {\n if (!item.trigger) return null;\n const label = TRIGGER_LABEL[item.trigger] ?? item.trigger;\n return item.triggerNodeId ? `${label} · ${item.triggerNodeId}` : label;\n}\n\n/**\n * A paged list of past executions: one row per run, click-to-select, with a\n * prev/next pager.\n *\n * A pure display leaf — no fetching, no polling, no sorting, no local\n * selection state. It renders `items` in the order given, reports a click, and\n * reports a page request; the host owns which page is loaded and which row is\n * selected.\n */\nexport function ExecutionList({\n items,\n selectedId = null,\n onSelect,\n showCallable = false,\n loading = false,\n emptyLabel,\n hasPrev,\n hasNext,\n onPrev,\n onNext,\n onRerun,\n rerunningId = null,\n}: ExecutionListProps) {\n // Rendered in EVERY branch below, deliberately: a host that reports it can\n // go back to a previous page must still offer that control from an empty\n // page (the state reached by paging past the last run) and while a page is\n // loading.\n const pager =\n onPrev || onNext ? (\n <div className=\"w6w-execution-list-pager\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-list-prev\"\n disabled={!hasPrev}\n onClick={onPrev}\n >\n Previous\n </button>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-list-next\"\n disabled={!hasNext}\n onClick={onNext}\n >\n Next\n </button>\n </div>\n ) : null;\n\n let body: ReactNode;\n if (loading && items.length === 0) {\n body = <p data-testid=\"execution-list-loading\">Loading…</p>;\n } else if (items.length === 0) {\n body = <p data-testid=\"execution-list-empty\">{emptyLabel ?? \"No executions yet.\"}</p>;\n } else {\n body = (\n <ul className=\"w6w-execution-list-rows\">\n {items.map((item) => (\n <li key={item.id} data-testid=\"execution-row\" data-execution-id={item.id}>\n <ListItem\n icon={<StepStatusPill state={item.status} />}\n title={\n <>\n {showCallable ? item.callableName : formatExecutionTime(item.startedAt)}\n {item.rerunOf && (\n <span\n className=\"w6w-execution-rerun-tag\"\n data-testid=\"execution-row-rerun-tag\"\n title={`Re-run of ${item.rerunOf}`}\n >\n Re-run\n </span>\n )}\n </>\n }\n subtitle={\n <>\n {showCallable\n ? `${KIND_LABEL[item.kind]} · ${formatExecutionTime(item.startedAt)}`\n : item.id}\n {triggerText(item) && (\n <span className=\"w6w-execution-trigger\" data-testid=\"execution-row-trigger\">\n {` · ${triggerText(item)}`}\n </span>\n )}\n {item.inputPreview && (\n <>\n {\" · \"}\n <code\n className=\"w6w-execution-input-preview\"\n data-testid=\"execution-row-input\"\n title={item.inputPreview}\n >\n {item.inputPreview}\n </code>\n </>\n )}\n </>\n }\n trailing={formatDurationMs(item.durationMs)}\n active={item.id === selectedId}\n onClick={onSelect ? () => onSelect(item.id) : undefined}\n />\n {onRerun && (\n <IconButton\n icon=\"sync\"\n label=\"Re-run\"\n title={item.id === rerunningId ? \"Re-running…\" : \"Re-run with the same input\"}\n className=\"w6w-execution-list-rerun\"\n data-testid=\"execution-row-rerun\"\n disabled={rerunningId !== null}\n onClick={() => onRerun(item.id)}\n />\n )}\n </li>\n ))}\n </ul>\n );\n }\n\n return (\n <div className=\"w6w-execution-list\" data-testid=\"execution-list\">\n {body}\n {pager}\n </div>\n );\n}\n","import type { StateWarningCode } from \"@w6w/expr\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { CodeBlock } from \"../CodeBlock.tsx\";\nimport { conditionCombinatorLabel, conditionOperatorLabel } from \"../condition-editor.ts\";\nimport { internalNodeDef } from \"../flow-types.ts\";\nimport type { StepMeta } from \"../provider.tsx\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { ResultViewer } from \"./ResultViewer.tsx\";\nimport { StepStatusPill } from \"./StepStatusPill.tsx\";\nimport type { SkipReason, StepStatus } from \"./StepStatusPill.tsx\";\n\n/** What a step is: the app and action it uses, and whether it is a trigger (`uses.trigger`). */\nexport interface ExecutionLogNode {\n app: string;\n action: string;\n trigger?: boolean;\n appName?: string;\n actionName?: string;\n}\n\n/** A node's kind and display names, a built-in `@w6w/*` node resolved from its own definition. */\nfunction describeNode(node: ExecutionLogNode): {\n trigger: boolean;\n appName: string;\n actionName: string;\n} {\n const builtin = internalNodeDef(node.app, node.action);\n return {\n trigger: node.trigger === true || builtin?.group === \"trigger\",\n appName: node.appName ?? builtin?.displayName ?? node.app,\n actionName: node.actionName ?? builtin?.label ?? node.action,\n };\n}\n\n/**\n * A step's or run's failure, already normalised by the HOST from the workflow\n * spec's `StepError` (`code`/`message`/`phase`/`retryable`). The panel never\n * parses an `unknown` error itself — same \"host owns the data\" split as the\n * rest of this file. Rendered in `TriggerFillForm`'s error visual: a\n * `.w6w-result.w6w-error` box, an optional `<code>` badge line, then the message.\n */\nexport interface ExecutionLogError {\n /** `StepError.code`. Optional: the host may normalise an error that carries no code. */\n code?: string;\n /** The human-readable reason. Never empty when the host supplies it. */\n message: string;\n /** `StepError.phase`, when known. Carried for the host; not rendered. */\n phase?: string;\n /** `StepError.retryable`, when known. Carried for the host; not rendered. */\n retryable?: boolean;\n}\n\n/**\n * One entry of `RunState.stepErrors` — a step failure the run recorded and\n * moved past (`onError: \"continue-record\"`, or a failure an error edge\n * handled), so the run itself may still have succeeded.\n */\nexport interface ExecutionLogRecordedError {\n /** The step the error belongs to. */\n stepId: string;\n /** Human-readable step name. Falls back to `stepId` when rendered. */\n label?: string;\n error: ExecutionLogError;\n}\n\n/**\n * One step's display row — an already-mapped, already-resolved slice of a\n * `RunState`/`StepExecution` (workflow spec). The HOST maps its own run\n * state into this shape (same \"host owns the data, the panel is\n * presentational\" split `readOnly` already establishes elsewhere in this\n * package) — this component never fetches, polls, or reaches for an SDK.\n */\nexport interface ExecutionLogStep {\n /** Stable id for this row — typically the step id from the workflow definition. */\n id: string;\n /** Human-readable step name. Falls back to `id` when omitted. */\n label?: string;\n status: StepStatus;\n /**\n * Why a `skipped` step did not run (`StepExecution.skipReason`). `not_on_path` rows leave the\n * list for the \"other paths\" footer; the rest show a short reason beside the Skipped pill.\n * Absent (a run recorded before reasons existed) ⇒ a plain Skipped row, as before.\n */\n skipReason?: SkipReason;\n /** ISO-8601 timestamp the step started, once it has. */\n startedAt?: string;\n /** ISO-8601 timestamp the step finished, once it has. */\n finishedAt?: string;\n /** The resolved input sent to the step's action, once it is known. */\n input?: unknown;\n /** The step's output, once it has one. */\n output?: unknown;\n /** Captured console output (also present when a script throws). */\n logs?: string[];\n /**\n * What ran (`StepExecution.meta`): app, version, action and connection id. Shown as a\n * Metadata block after Output. Absent or `null` ⇒ no block at all (R-12: no filler).\n */\n meta?: StepMeta | null;\n /**\n * What this step IS, from the workflow definition — shown on the row itself so a run reads as\n * \"Trigger · Cohost · Order Placed\" rather than a bare node id. `appName`/`actionName` are the\n * host's display names for a registered app; a built-in `@w6w/*` node is named here from its\n * own definition, and anything unnamed falls back to the raw id. Absent ⇒ the row shows its\n * label alone, as before.\n */\n node?: ExecutionLogNode;\n /**\n * Why the step failed (`StepExecution.error`, \"present on failed\"). Rendered\n * below the row's box and outside its lazy `<details>` body, so the reason\n * reads without expanding the row.\n */\n error?: ExecutionLogError;\n /** For each only (I4): the per-iteration body-step records, index ascending. */\n iterations?: ExecutionLogIteration[];\n /** Distinct iteration indices the run recorded (may exceed `iterations.length`). */\n iterationsTotal?: number;\n /** How many of those iterations failed. */\n iterationsFailed?: number;\n /** `true` when `iterations` holds fewer than `iterationsTotal`. */\n iterationsTruncated?: boolean;\n /**\n * The step's state writes (`stateWrites`, the run's state log rows for this step), in write\n * order: `state.<path>: old → new`, or a warning when `warning` is set (a `StateWarningCode`).\n * `item` is the For each item a hoisted body write came from. Absent, `null` or `[]` ⇒ no rows.\n */\n stateWrites?: Array<{\n path: string[];\n item?: number;\n old?: unknown;\n new?: unknown;\n warning?: string;\n }> | null;\n /**\n * The run's state tree after this step, shown as \"State after this step\" in the State block.\n * Absent or `null` ⇒ not shown; `{}` shows only alongside writes.\n */\n stateAfter?: Record<string, unknown> | null;\n}\n\n/** One For each iteration: its status and the body-step records, in execution order. */\nexport interface ExecutionLogIteration {\n /** 0-based; the same number as `foreach.index` in that iteration's expressions. */\n index: number;\n status: \"succeeded\" | \"failed\" | \"running\";\n /** The body step that failed, when one did. */\n failedNodeId?: string;\n steps: ExecutionLogStep[];\n}\n\n/** Server record key order is not execution order. Keep ties stable and never mutate props. */\nfunction chronologicalSteps(steps: readonly ExecutionLogStep[]): ExecutionLogStep[] {\n const time = (step: ExecutionLogStep) => {\n for (const value of [step.startedAt, step.finishedAt]) {\n const parsed = Date.parse(value ?? \"\");\n if (Number.isFinite(parsed)) return parsed;\n }\n return Number.POSITIVE_INFINITY;\n };\n return steps\n .map((step) => ({ step, time: time(step) }))\n .sort((a, b) => (a.time === b.time ? 0 : a.time - b.time))\n .map(({ step }) => step);\n}\n\nexport interface ExecutionLogPanelProps {\n /** Rendered earliest first by start time (finish time as fallback), then untimed steps. */\n steps: ExecutionLogStep[];\n /** Shown instead of the list when `steps` is empty. */\n emptyLabel?: ReactNode;\n /**\n * Supplied ⇒ the panel grows a header row carrying a dismiss control that\n * calls this and nothing else (T1.1.1). Omitted ⇒ no header row at all, no\n * extra DOM node. The panel still owns no run state — it only reports the\n * click; the host decides what dismissing means.\n */\n onDismiss?: () => void;\n /**\n * The run's own failure (`RunState.error`). Rendered below the dismiss head\n * and above the steps — in the empty branch too, since a run that failed\n * before any step ran has nothing else to say why.\n */\n runError?: ExecutionLogError;\n /**\n * Step failures the run recorded and moved past (`RunState.stepErrors`),\n * one error block each, in the order given, after `runError`.\n */\n stepErrors?: ExecutionLogRecordedError[];\n}\n\n/**\n * Read-only log of a workflow run's steps, in ascending execution time: each row is\n * the step's status pill, its timing, and its resolved input/output.\n *\n * A pure display leaf — no data fetching, no polling, no layout media\n * queries (the host docks the panel; see `_scale.scss`'s breakpoint\n * docstring). Fills whatever box its host gives it.\n */\nexport function ExecutionLogPanel({\n steps,\n emptyLabel,\n onDismiss,\n runError,\n stepErrors,\n}: ExecutionLogPanelProps) {\n // Rendered by BOTH branches below, deliberately: the reported repro (T-1) is\n // a canvas whose log panel shows \"No nodes have run yet.\" — a header mounted\n // only above the `<ol>` would be invisible in exactly that state, and that is\n // the state the dismiss control exists to get the user out of.\n const head = onDismiss ? (\n <div className=\"w6w-execution-log-head\">\n <IconButton label=\"Dismiss run log\" data-testid=\"execution-log-dismiss\" onClick={onDismiss}>\n ×\n </IconButton>\n </div>\n ) : null;\n\n // Same both-branches rule as `head`: a run that failed before its first step\n // is exactly the empty branch. Nothing to report ⇒ no wrapper node at all.\n const recorded = stepErrors ?? [];\n const errors =\n runError || recorded.length > 0 ? (\n <div className=\"w6w-execution-log-errors w6w-stack\">\n {runError && <ExecutionLogErrorBlock error={runError} />}\n {recorded.map((entry, index) => (\n <ExecutionLogErrorBlock\n // `stepId` alone may repeat (a step retried into the record twice).\n key={`${entry.stepId}:${index}`}\n label={entry.label ?? entry.stepId}\n error={entry.error}\n />\n ))}\n </div>\n ) : null;\n\n // A step on another path (not downstream of the fired trigger) was never part of this run:\n // it is not a skip, so it leaves the list for one collapsed footer line.\n const inRun = chronologicalSteps(steps.filter((s) => !isOffPath(s)));\n const offPath = steps.filter(isOffPath);\n const footer = offPath.length > 0 ? <ExecutionLogOffPath steps={offPath} /> : null;\n\n if (inRun.length === 0) {\n return (\n <>\n {head}\n {errors}\n <div className=\"w6w-execution-log-empty\">\n <p className=\"w6w-muted w6w-small\">{emptyLabel ?? \"No nodes have run yet.\"}</p>\n </div>\n {footer}\n </>\n );\n }\n\n return (\n <>\n {head}\n {errors}\n <ol className=\"w6w-execution-log\">\n {inRun.map((step) => (\n <ExecutionLogRow key={step.id} step={step} />\n ))}\n </ol>\n {footer}\n </>\n );\n}\n\nconst isOffPath = (step: ExecutionLogStep) =>\n step.status === \"skipped\" && step.skipReason === \"not_on_path\";\n\n/** The short reason shown beside a real skip's pill. */\nconst SKIP_REASON_LABELS: Record<Exclude<SkipReason, \"not_on_path\">, string> = {\n condition: \"condition false\",\n stopped: \"run stopped\",\n disabled: \"disabled\",\n};\n\n/** \"N steps on other paths, not part of this run\" — collapsed; expands to their names. */\nfunction ExecutionLogOffPath({ steps }: { steps: ExecutionLogStep[] }) {\n const n = steps.length;\n return (\n <details className=\"w6w-execution-log-off-path\" data-testid=\"execution-log-off-path\">\n <summary className=\"w6w-muted w6w-small\">\n {`${n} ${n === 1 ? \"step\" : \"steps\"} on other paths, not part of this run`}\n </summary>\n <ul className=\"w6w-muted w6w-small\">\n {steps.map((s) => (\n <li key={s.id}>{s.label ?? s.id}</li>\n ))}\n </ul>\n </details>\n );\n}\n\n/**\n * Collapsed-by-default disclosure per step (REVIEW.md R-1) — reuses\n * `.w6w-section`'s bordered `<details>` idiom (`ApiCallsPanel.tsx`,\n * `ParamsForm.tsx`'s `section: \"collapsible\"`), not a bespoke card. The\n * `<summary>` is the one-line scan line (pill + label + timing, unchanged\n * content from the old always-visible row header); Input/Output move inside\n * the details body, and are only mounted into the DOM once opened — a\n * closed run of N steps costs N compact rows, not N×2 rendered JSON blocks.\n *\n * A step with neither `input` nor `output` has nothing to disclose: it\n * renders a plain, non-interactive row (still `.w6w-section`-styled for\n * visual consistency with its siblings) rather than an empty `<details>` a\n * user opens only to find \"Not available.\" twice (A3). An `error` alone is\n * not something to disclose either: it renders on every row as a sibling\n * AFTER the row's box — outside the lazily mounted `<details>` body (so it\n * reads while collapsed and never mounts twice once opened) and outside the\n * `<summary>` (whose phrasing-content model and click-to-toggle make it the\n * wrong home for a selectable block of text).\n */\nfunction ExecutionLogRow({ step }: { step: ExecutionLogStep }) {\n const [open, setOpen] = useState(false);\n const node = step.node ? describeNode(step.node) : null;\n const header = (\n <div className=\"w6w-execution-log-row-header\">\n <StepStatusPill state={step.status} />\n {node && (\n <span\n className={`w6w-execution-log-kind${node.trigger ? \" w6w-execution-log-kind-trigger\" : \"\"}`}\n data-testid=\"execution-log-kind\"\n >\n {node.trigger ? \"Trigger\" : \"Node\"}\n </span>\n )}\n <span className=\"w6w-execution-log-row-title\">\n <span className=\"w6w-execution-log-row-label\">{step.label ?? step.id}</span>\n {node && (\n <span className=\"w6w-execution-log-row-uses\" data-testid=\"execution-log-uses\">\n {node.appName === node.actionName\n ? node.appName\n : `${node.appName} · ${node.actionName}`}\n </span>\n )}\n </span>\n {step.status === \"skipped\" && step.skipReason && step.skipReason !== \"not_on_path\" && (\n <span className=\"w6w-execution-log-skip-reason\" data-testid=\"execution-log-skip-reason\">\n {SKIP_REASON_LABELS[step.skipReason]}\n </span>\n )}\n <StepTiming startedAt={step.startedAt} finishedAt={step.finishedAt} />\n </div>\n );\n\n const error = step.error ? <ExecutionLogErrorBlock error={step.error} /> : null;\n const loop = Array.isArray(step.iterations) ? <ExecutionLogIterations step={step} /> : null;\n\n const state = hasStateBlock(step) ? <ExecutionLogState step={step} /> : null;\n\n if (\n step.input === undefined &&\n step.output === undefined &&\n !step.meta &&\n !state &&\n !step.logs?.length\n ) {\n return (\n <li className=\"w6w-execution-log-row\">\n <div className=\"w6w-section\">{header}</div>\n {error}\n {loop}\n </li>\n );\n }\n\n return (\n <li className=\"w6w-execution-log-row\">\n <details className=\"w6w-section\" open={open} onToggle={(e) => setOpen(e.currentTarget.open)}>\n <summary className=\"w6w-section-summary\">{header}</summary>\n {open && (\n <div className=\"w6w-execution-log-row-body w6w-section-body w6w-stack\">\n <ExecutionLogConditions input={step.input} />\n <ExecutionLogJson title=\"Input\" value={step.input} />\n <ExecutionLogJson title=\"Output\" value={step.output} />\n {!!step.logs?.length && (\n <div className=\"w6w-execution-log-json w6w-stack\">\n <strong className=\"w6w-small\">Console</strong>\n <CodeBlock code={step.logs.join(\"\\n\")} language=\"plaintext\" />\n </div>\n )}\n {step.meta && (\n <div className=\"w6w-execution-log-json w6w-stack\">\n <strong className=\"w6w-small\">Metadata</strong>\n <CodeBlock code={JSON.stringify(step.meta, null, 2)} language=\"json\" />\n </div>\n )}\n {state}\n </div>\n )}\n </details>\n {error}\n {loop}\n </li>\n );\n}\n\n/**\n * A For each row's per-iteration view: a summary (count, failures, pointer at the\n * failing body step), one presentational chip per served iteration, and one\n * sub-row per body step with its own iteration `<select>` (failed iteration\n * preselected, else the last served one). Pure props -> DOM; no fetching.\n */\nfunction ExecutionLogIterations({ step }: { step: ExecutionLogStep }) {\n const iterations = [...(step.iterations ?? [])].sort((a, b) => a.index - b.index);\n const total = step.iterationsTotal ?? iterations.length;\n const failedCount =\n step.iterationsFailed ?? iterations.filter((it) => it.status === \"failed\").length;\n const firstFailed = iterations.find((it) => it.status === \"failed\");\n const defaultIndex = firstFailed?.index ?? iterations[iterations.length - 1]?.index;\n\n const bodyIds: string[] = [];\n const labels = new Map<string, string>();\n for (const s of chronologicalSteps(iterations.flatMap((it) => it.steps))) {\n if (!labels.has(s.id)) {\n bodyIds.push(s.id);\n labels.set(s.id, s.label ?? s.id);\n }\n }\n const failedId =\n firstFailed?.failedNodeId ?? firstFailed?.steps.find((s) => s.status === \"failed\")?.id;\n\n return (\n <div className=\"w6w-execution-log-foreach w6w-stack\">\n <div className=\"w6w-small\" data-testid=\"execution-log-foreach-summary\">\n <span>\n {total === 1 ? \"1 item\" : `${total} items`}\n {failedCount > 0 ? ` · ${failedCount} failed` : \"\"}\n </span>\n {firstFailed && failedId !== undefined && (\n <div>\n {labels.get(failedId) ?? failedId} failed in iteration {firstFailed.index}\n </div>\n )}\n {step.iterationsTruncated === true && (\n <div className=\"w6w-muted\">{`showing ${iterations.length} of ${total}`}</div>\n )}\n </div>\n <div className=\"w6w-execution-log-iteration-chips\">\n {iterations.map((it) => (\n <span\n key={it.index}\n className={`w6w-execution-log-iteration-chip w6w-execution-log-iteration-chip-${it.status}`}\n data-testid=\"execution-log-iteration-chip\"\n data-status={it.status}\n >\n {it.index} · {it.status}\n </span>\n ))}\n </div>\n <ul className=\"w6w-execution-log-subrows\">\n {bodyIds.map((id) => (\n <ExecutionLogBodyStep\n key={id}\n id={id}\n label={labels.get(id) ?? id}\n iterations={iterations}\n initial={defaultIndex}\n />\n ))}\n </ul>\n </div>\n );\n}\n\nfunction ExecutionLogBodyStep({\n id,\n label,\n iterations,\n initial,\n}: {\n id: string;\n label: string;\n iterations: ExecutionLogIteration[];\n initial: number | undefined;\n}) {\n const [selected, setSelected] = useState<number | undefined>(initial);\n const record = iterations.find((it) => it.index === selected)?.steps.find((s) => s.id === id);\n return (\n <li className=\"w6w-execution-log-subrow w6w-stack\">\n <div className=\"w6w-execution-log-subrow-head\">\n <strong className=\"w6w-small\">{label}</strong>\n <select\n className=\"w6w-select\"\n aria-label={`Iteration for ${label}`}\n data-testid=\"execution-log-iteration-select\"\n value={selected === undefined ? \"\" : String(selected)}\n onChange={(e) => setSelected(Number(e.currentTarget.value))}\n >\n {iterations.map((it) => (\n <option key={it.index} value={String(it.index)}>\n {`iteration ${it.index} (${it.status})`}\n </option>\n ))}\n </select>\n </div>\n {record ? (\n <ol className=\"w6w-execution-log\">\n <ExecutionLogRow key={selected} step={record} />\n </ol>\n ) : (\n <p className=\"w6w-muted w6w-small\">Did not run in this iteration.</p>\n )}\n </li>\n );\n}\n\n/**\n * `TriggerFillForm`'s StepError visual, reused rather than re-invented: the\n * `.w6w-result.w6w-error` box, an optional muted `<code>` line, then the\n * message. `label` (recorded step errors only) names the step on a line above.\n * The code line's spacing lives in `_execution-log.scss` as tokens instead of\n * `TriggerFillForm`'s inline style — same values (`0.75` opacity, a 4px gap).\n */\nfunction ExecutionLogErrorBlock({ error, label }: { error: ExecutionLogError; label?: string }) {\n return (\n <div className=\"w6w-result w6w-error\">\n {label !== undefined && <strong className=\"w6w-execution-log-error-label\">{label}</strong>}\n {error.code && (\n <div className=\"w6w-small w6w-execution-log-error-code\">\n <code>{error.code}</code>\n </div>\n )}\n {error.message}\n </div>\n );\n}\n\n/**\n * \"started / finished, or elapsed\" (A2): both timestamps render verbatim\n * plus the computed elapsed duration between them; only `startedAt` renders\n * as \"Started <ts>\"; neither renders as a plain dash. Never a live-ticking\n * clock — a `setInterval` would make this component a timer owner rather\n * than a pure function of its props.\n */\nfunction StepTiming({ startedAt, finishedAt }: { startedAt?: string; finishedAt?: string }) {\n if (startedAt && finishedAt) {\n const elapsed = formatElapsed(startedAt, finishedAt);\n return (\n <span className=\"w6w-execution-log-timing\">\n {startedAt} → {finishedAt}\n {elapsed && <span> ({elapsed})</span>}\n </span>\n );\n }\n if (startedAt) {\n return <span className=\"w6w-execution-log-timing\">Started {startedAt}</span>;\n }\n return <span className=\"w6w-execution-log-timing\">—</span>;\n}\n\nfunction formatElapsed(startedAt: string, finishedAt: string): string | null {\n const startMs = Date.parse(startedAt);\n const endMs = Date.parse(finishedAt);\n if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || endMs < startMs) return null;\n const ms = endMs - startMs;\n if (ms < 1000) return `${ms}ms`;\n const totalSeconds = ms / 1000;\n if (totalSeconds < 60) return `${totalSeconds.toFixed(1)}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = Math.round(totalSeconds % 60);\n return `${minutes}m ${seconds}s`;\n}\n\n/** Each payload starts collapsed and mounts its read-only JSON tree on demand.\n * The shared viewer provides key folding, Expand/Collapse all and full-value copy.\n * Force JSON so an output string stays a string, even when it contains HTML or JSON text. */\nfunction ExecutionLogJson({ title, value }: { title: string; value: unknown }) {\n const [open, setOpen] = useState(false);\n if (value === undefined) {\n return (\n <div className=\"w6w-execution-log-json w6w-stack\">\n <strong className=\"w6w-small\">{title}</strong>\n <p className=\"w6w-muted w6w-small\">Not available.</p>\n </div>\n );\n }\n return (\n <details\n className=\"w6w-execution-log-json\"\n open={open}\n onToggle={(e) => {\n if (e.target === e.currentTarget) setOpen(e.currentTarget.open);\n }}\n >\n <summary>\n <strong className=\"w6w-small\">{title}</strong>\n </summary>\n {open && <ResultViewer value={value} format=\"json\" />}\n </details>\n );\n}\n\ninterface ConditionRow {\n left: unknown;\n op: string;\n right: unknown;\n result: boolean;\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** The engine's `{ conditions, combinator? }` trace on a record, if it carries one, with the\n * record's own resolved `condition` as the overall result. */\nfunction conditionTrace(\n v: unknown,\n): { rows: ConditionRow[]; combinator?: string; result?: boolean } | undefined {\n if (!isRecord(v) || !Array.isArray(v.conditions)) return;\n const rows = v.conditions.filter(\n (r): r is ConditionRow => isRecord(r) && typeof r.op === \"string\" && \"result\" in r,\n );\n if (rows.length === 0) return;\n return {\n rows,\n combinator: typeof v.combinator === \"string\" ? v.combinator : undefined,\n result: typeof v.condition === \"boolean\" ? v.condition : undefined,\n };\n}\n\n/**\n * An If / Stop workflow / Router input's resolved comparisons as a left | operator | right |\n * result table — what was compared, not only `condition: true`. The engine records them\n * beside the boolean (`{ conditions: [{ left, op, right, result }], combinator? }`; a Router\n * per route); a record without that trace renders nothing, and the raw Input below still\n * shows everything.\n */\nfunction ExecutionLogConditions({ input }: { input: unknown }) {\n const groups: { title?: string; trace: NonNullable<ReturnType<typeof conditionTrace>> }[] = [];\n const own = conditionTrace(input);\n if (own) groups.push({ trace: own });\n if (isRecord(input) && Array.isArray(input.routes)) {\n for (const route of input.routes) {\n const trace = conditionTrace(route);\n if (!trace || !isRecord(route)) continue;\n groups.push({ title: String(route.label ?? route.id ?? \"Route\"), trace });\n }\n }\n if (groups.length === 0) return null;\n return (\n <div className=\"w6w-execution-log-json w6w-stack\" data-testid=\"execution-log-conditions\">\n <strong className=\"w6w-small\">Condition</strong>\n {groups.map(({ title, trace }, g) => (\n <div key={title ?? g} className=\"w6w-stack\">\n {title && <span className=\"w6w-small w6w-muted\">{title}</span>}\n {((trace.combinator && trace.rows.length > 1) || trace.result !== undefined) && (\n <span className=\"w6w-small w6w-muted\" data-testid=\"execution-log-condition-summary\">\n {trace.combinator &&\n trace.rows.length > 1 &&\n conditionCombinatorLabel(trace.combinator)}\n {trace.combinator && trace.rows.length > 1 && trace.result !== undefined && \" · \"}\n {trace.result !== undefined && (\n <>\n Result:{\" \"}\n <span\n className={\n trace.result\n ? \"w6w-execution-log-condition-true\"\n : \"w6w-execution-log-condition-false\"\n }\n >\n {trace.result ? \"true\" : \"false\"}\n </span>\n </>\n )}\n </span>\n )}\n <div className=\"w6w-data-table-frame\">\n <table className=\"w6w-data-table w6w-execution-log-conditions\">\n <thead>\n <tr>\n <th>Left</th>\n <th>Operator</th>\n <th>Right</th>\n <th>Result</th>\n </tr>\n </thead>\n <tbody>\n {trace.rows.map((row, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and never reorder.\n <tr key={i}>\n <td>\n <code>{operandText(row.left)}</code>\n </td>\n <td>{conditionOperatorLabel(row.op)}</td>\n <td>\n <code>{operandText(row.right)}</code>\n </td>\n <td\n className={\n row.result\n ? \"w6w-execution-log-condition-true\"\n : \"w6w-execution-log-condition-false\"\n }\n >\n {row.result ? \"true\" : \"false\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n ))}\n </div>\n );\n}\n\n/** A resolved operand as JSON, so `\"\"`, `\"5\"` vs `5` and `null` read apart. */\nfunction operandText(value: unknown): string {\n return JSON.stringify(value) ?? \"undefined\";\n}\n\n/** Plain-language text for each state-write warning code — never the raw code. */\nconst STATE_WARNING_LABELS: Record<StateWarningCode, string> = {\n not_object: \"Not written — the output isn't an object, so it can't be merged at the root\",\n missing_source: \"Not written — the output has no value at that field\",\n null_append: \"Not appended — the value was null\",\n append_not_array: \"Not appended — the existing value isn't a list\",\n write_too_large: \"Not written — the value is too large\",\n run_too_large: \"Not written — the run's state would grow past its size limit\",\n too_deep: \"Not written — the value is nested too deeply\",\n key_too_long: \"Not written — a key in the value is too long\",\n forbidden_key: \"Not written — the value uses a reserved key name\",\n log_truncated: \"Later state changes aren't shown — the run's state log reached its limit\",\n};\n\nfunction stateWarningLabel(code: string): string {\n return Object.hasOwn(STATE_WARNING_LABELS, code)\n ? STATE_WARNING_LABELS[code as StateWarningCode]\n : code;\n}\n\nfunction hasStateBlock(step: ExecutionLogStep): boolean {\n const hasWrites = Array.isArray(step.stateWrites) && step.stateWrites.length > 0;\n const after = step.stateAfter;\n const hasAfter = typeof after === \"object\" && after !== null;\n return hasWrites || (hasAfter && Object.keys(after).length > 0);\n}\n\nconst STATE_VALUE_MAX = 120;\n\nfunction stateValueText(v: unknown): string {\n if (v === undefined) return \"(not set)\";\n const text = JSON.stringify(v) ?? String(v);\n return text.length > STATE_VALUE_MAX ? `${text.slice(0, STATE_VALUE_MAX)}…` : text;\n}\n\n/**\n * The State block: one row per state write in the order the run recorded them\n * (`state.<path>: old → new`, or the warning that stopped it), then the run's\n * state tree after this step. Rendered only when there is something to show.\n */\nfunction ExecutionLogState({ step }: { step: ExecutionLogStep }) {\n const writes = Array.isArray(step.stateWrites) ? step.stateWrites : [];\n const after = step.stateAfter;\n return (\n <div className=\"w6w-execution-log-state w6w-stack\" data-testid=\"execution-log-state\">\n <strong className=\"w6w-small\">State</strong>\n {writes.length > 0 && (\n <ul className=\"w6w-execution-log-state-writes\">\n {writes.map((w, i) => {\n const path = Array.isArray(w.path) ? w.path : [];\n const label = `state${path.length ? `.${path.join(\".\")}` : \"\"}${w.item !== undefined ? ` (item ${w.item})` : \"\"}`;\n return w.warning !== undefined ? (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional, never reordered\n key={i}\n className=\"w6w-execution-log-state-write w6w-execution-log-state-warning w6w-small\"\n data-testid=\"execution-log-state-write\"\n data-warning={w.warning}\n >\n {`${label}: ${stateWarningLabel(w.warning)}`}\n </li>\n ) : (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional, never reordered\n key={i}\n className=\"w6w-execution-log-state-write w6w-small\"\n data-testid=\"execution-log-state-write\"\n >\n {`${label}: ${stateValueText(w.old)} → ${stateValueText(w.new)}`}\n </li>\n );\n })}\n </ul>\n )}\n {typeof after === \"object\" && after !== null && (\n <div className=\"w6w-stack\" data-testid=\"execution-log-state-after\">\n <span className=\"w6w-small w6w-muted\">State after this step</span>\n <CodeBlock code={JSON.stringify(after, null, 2)} language=\"json\" />\n </div>\n )}\n </div>\n );\n}\n","import type { ExecutionKind } from \"./ExecutionList.tsx\";\nimport type { ExecutionStatus } from \"./StepStatusPill.tsx\";\n\n/**\n * The filter/search state of the history view — one plain object, owned by the\n * HOST. This component is fully controlled: it holds no state of its own, it\n * only renders `value` and reports the next one. Same \"host owns the data, the\n * control is presentational\" split `ExecutionList` establishes, and the same\n * reason: the host owns where the filters live (URL search params today, a\n * query cache tomorrow) and this leaf must not disagree with it.\n */\nexport interface ExecutionFilterValue {\n /** `\"\"` = \"no status filter\" (the `Any status` option), never `null`. */\n status: ExecutionStatus | \"\";\n /** `\"\"` = \"no kind filter\" (the `Any type` option). Only reachable when the\n * host renders the kind select (`showKind`). */\n kind: ExecutionKind | \"\";\n /** Inclusive lower bound on the run's start, as `YYYY-MM-DD` — exactly what\n * `input[type=date]` reports and accepts. `\"\"` = unbounded. */\n from: string;\n /** Inclusive upper bound on the run's start, same format. `\"\"` = unbounded. */\n to: string;\n /** Free-text query. D3: the server matches execution id + callable name/key,\n * never payload JSON. */\n q: string;\n}\n\nexport interface ExecutionFiltersProps {\n /** The current filter state — rendered verbatim, never re-derived. */\n value: ExecutionFilterValue;\n /** Called ONCE per user interaction with the ONE field that changed:\n * `{ ...value, <that field>: next }`. No debounce, no batching — the host\n * decides when a request is worth making (it may debounce `q` itself). */\n onChange: (next: ExecutionFilterValue) => void;\n /** `true` ⇒ the kind select renders between the status select and the date\n * bounds. Defaults to `false`: the per-callable history view already knows\n * the kind, so a kind filter there would be a control of one option. */\n showKind?: boolean;\n /** Placeholder for the search box. Defaults to `\"Search by id or name\"` —\n * the same two fields D3 pins the server-side search to. */\n searchPlaceholder?: string;\n /** `true` ⇒ every control (the clear button included) renders disabled — the\n * state a host uses while a request is already in flight. */\n disabled?: boolean;\n}\n\n/** The \"nothing filtered\" state — what Clear reports, and what a host starts\n * from. Kept module-local: it is one object literal, and a host that needs its\n * own initial value should own it (it must be encoded into a URL anyway). */\nconst EMPTY: ExecutionFilterValue = { status: \"\", kind: \"\", from: \"\", to: \"\", q: \"\" };\n\n/** `\"\"` first (the \"any\" option), then one entry per run state, capitalised. */\nconst STATUS_OPTIONS: Array<{ value: ExecutionStatus | \"\"; label: string }> = [\n { value: \"\", label: \"Any status\" },\n { value: \"queued\", label: \"Queued\" },\n { value: \"running\", label: \"Running\" },\n { value: \"succeeded\", label: \"Succeeded\" },\n { value: \"failed\", label: \"Failed\" },\n { value: \"canceled\", label: \"Canceled\" },\n];\n\nconst KIND_OPTIONS: Array<{ value: ExecutionKind | \"\"; label: string }> = [\n { value: \"\", label: \"Any type\" },\n { value: \"function\", label: \"Function\" },\n { value: \"endpoint\", label: \"Endpoint\" },\n { value: \"workflow\", label: \"Workflow\" },\n];\n\n/**\n * The history view's filter/search bar: free text, status, (optionally) kind,\n * and a start-date window, plus a Clear control that appears only once there is\n * something to clear.\n *\n * A pure controlled leaf. Every change reports exactly one field's new value,\n * spread over the value it was given — a control that rebuilt the whole object\n * would silently drop a sibling filter the moment the two are edited close\n * together, and the host is the only party that knows the authoritative value.\n *\n * Each control carries its own `aria-label`: the visible layout is one dense\n * row of heterogeneous controls (a search box, three or four dropdowns, two\n * date pickers) with no room for a label per control, so the accessible name is\n * what tells them apart.\n */\nexport function ExecutionFilters({\n value,\n onChange,\n showKind = false,\n searchPlaceholder = \"Search by id or name\",\n disabled = false,\n}: ExecutionFiltersProps) {\n const clearable =\n value.status !== \"\" ||\n value.kind !== \"\" ||\n value.from !== \"\" ||\n value.to !== \"\" ||\n value.q !== \"\";\n\n return (\n <div className=\"w6w-execution-filters\" data-testid=\"execution-filters\">\n <input\n type=\"search\"\n className=\"w6w-execution-filters-search\"\n data-testid=\"execution-filter-q\"\n aria-label=\"Search executions\"\n placeholder={searchPlaceholder}\n value={value.q}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, q: e.target.value })}\n />\n <select\n className=\"w6w-execution-filters-select\"\n data-testid=\"execution-filter-status\"\n aria-label=\"Status\"\n value={value.status}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, status: e.target.value as ExecutionStatus | \"\" })}\n >\n {STATUS_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {showKind && (\n <select\n className=\"w6w-execution-filters-select\"\n data-testid=\"execution-filter-kind\"\n aria-label=\"Type\"\n value={value.kind}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, kind: e.target.value as ExecutionKind | \"\" })}\n >\n {KIND_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n )}\n <input\n type=\"date\"\n className=\"w6w-execution-filters-date\"\n data-testid=\"execution-filter-from\"\n aria-label=\"From date\"\n value={value.from}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, from: e.target.value })}\n />\n <input\n type=\"date\"\n className=\"w6w-execution-filters-date\"\n data-testid=\"execution-filter-to\"\n aria-label=\"To date\"\n value={value.to}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, to: e.target.value })}\n />\n {clearable && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-execution-filters-clear\"\n data-testid=\"execution-filter-clear\"\n disabled={disabled}\n onClick={() => onChange({ ...EMPTY })}\n >\n Clear\n </button>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { formatDurationMs } from \"./execution-format.ts\";\n\n/**\n * The aggregate numbers of a history view — the same rows the list shows,\n * rolled up (D1: stats are computed over the same visibility the list uses, so\n * the two can never disagree about who may see what).\n *\n * `succeeded`/`canceled` are carried even though the strip renders no card for\n * them today: the host's payload has them, the breakdown is what a host needs\n * for a chart or a chip row, and a host re-deriving them from the list would be\n * computing the same total a second time.\n */\nexport interface ExecutionStatsValue {\n /** Every run in the current filter — the denominator of `successRate`. */\n total: number;\n succeeded: number;\n failed: number;\n canceled: number;\n /** Runs that are queued or running right now. `> 0` is what makes the\n * `In flight` card exist at all. */\n inFlight: number;\n /** `0…1`, or `null` when the host has no rate to report (no runs at all —\n * a rate over zero runs is not 0%). */\n successRate: number | null;\n /** Mean wall-clock duration of the FINISHED runs, or `null` when none has\n * finished. */\n avgDurationMs: number | null;\n}\n\nexport interface ExecutionStatsProps {\n /** The aggregate, or `null` while nothing has loaded yet — rendered as `—`\n * per card rather than as a spinner, so the strip never changes height. */\n stats: ExecutionStatsValue | null;\n /** Caption above the cards, e.g. the window they cover (\"Last 7 days\").\n * Omitted ⇒ no node at all. */\n label?: ReactNode;\n}\n\n/** What an absent/unknown number renders as — never `0`, which would read as a\n * measured result. Same em dash `execution-format.ts` uses for the same\n * reason. */\nconst UNKNOWN = \"—\";\n\ninterface Card {\n testid: string;\n label: string;\n value: string;\n}\n\n/**\n * A headline strip of run aggregates: one big value over a muted label per\n * card.\n *\n * Promotes studio `DashboardPage.tsx`'s page-local `StatCard` into `ui`, with\n * two differences that come from this being a shared component rather than one\n * page's private helper: the values are pre-formatted here (a rate as `67%`, a\n * duration through `formatDurationMs`) so every consumer renders the same\n * string, and each card carries `data-stat-value` so a host can assert on the\n * value without re-parsing its own formatting.\n */\nexport function ExecutionStats({ stats, label }: ExecutionStatsProps) {\n const cards: Card[] = [\n {\n testid: \"execution-stat-total\",\n label: \"Executions\",\n value: stats ? String(stats.total) : UNKNOWN,\n },\n {\n testid: \"execution-stat-success-rate\",\n label: \"Success rate\",\n value: formatSuccessRate(stats?.successRate),\n },\n {\n testid: \"execution-stat-failed\",\n label: \"Failed\",\n value: stats ? String(stats.failed) : UNKNOWN,\n },\n {\n testid: \"execution-stat-avg-duration\",\n label: \"Avg duration\",\n value: stats ? formatDurationMs(stats.avgDurationMs) : UNKNOWN,\n },\n ];\n\n // The one CONDITIONAL card: a zero in-flight count is the steady state, and a\n // permanent \"In flight 0\" would draw the eye to the least interesting number\n // in the strip. A missing `stats` counts as zero, so the strip keeps four\n // cards while loading instead of five-then-four.\n if (stats && stats.inFlight > 0) {\n cards.push({\n testid: \"execution-stat-in-flight\",\n label: \"In flight\",\n value: String(stats.inFlight),\n });\n }\n\n return (\n <section className=\"w6w-execution-stats\" data-testid=\"execution-stats\">\n {label != null && <p className=\"w6w-execution-stats-label\">{label}</p>}\n <div className=\"w6w-execution-stats-cards\">\n {cards.map((card) => (\n <div key={card.testid} className=\"w6w-execution-stat\" data-testid={card.testid}>\n <span className=\"w6w-execution-stat-value\" data-stat-value={card.value}>\n {card.value}\n </span>\n <span className=\"w6w-execution-stat-label\">{card.label}</span>\n </div>\n ))}\n </div>\n </section>\n );\n}\n\n/**\n * A `0…1` rate as a whole-percent string (`0.666…` → `\"67%\"`, rounded rather\n * than floored so `2/3` does not read as `66%`).\n *\n * `null` (nothing to report) and a non-finite rate (a host dividing by zero\n * somewhere upstream) are both `—` — the same totality `formatDurationMs`\n * keeps, so no input can render `NaN%`.\n */\nfunction formatSuccessRate(rate: number | null | undefined): string {\n if (rate == null || !Number.isFinite(rate)) return UNKNOWN;\n return `${Math.round(rate * 100)}%`;\n}\n","import type { ReactNode } from \"react\";\nimport { CodeBlock } from \"../CodeBlock.tsx\";\nimport type { ExecutionKind } from \"./ExecutionList.tsx\";\nimport { ExecutionLogPanel } from \"./ExecutionLogPanel.tsx\";\nimport type { ExecutionLogStep } from \"./ExecutionLogPanel.tsx\";\nimport { Icon } from \"./Icon.tsx\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { StepStatusPill } from \"./StepStatusPill.tsx\";\nimport type { ExecutionStatus } from \"./StepStatusPill.tsx\";\nimport { formatDurationMs, formatExecutionTime } from \"./execution-format.ts\";\n\n/**\n * One past execution in full — an already-mapped slice of the host's history\n * payload, the detail-level sibling of `ExecutionListItem`. The HOST maps its\n * own record into this shape; this component never fetches, polls or reaches\n * for an SDK.\n *\n * D2: there is no log-line field anywhere in this shape, on purpose — \"logs\"\n * for an execution ARE its status, timing, input, output and error, and for a\n * workflow that is the per-step `steps` list below.\n */\nexport interface ExecutionDetailValue {\n id: string;\n kind: ExecutionKind;\n callableName: string;\n status: ExecutionStatus;\n /** ISO-8601 instant the run started. */\n startedAt: string;\n /** ISO-8601 instant the run finished, or `null` while it is still\n * queued/running (rendered as `—`). */\n finishedAt: string | null;\n /** Wall-clock duration once the run has finished, or `null` while it has not\n * (rendered as `—`). */\n durationMs: number | null;\n /** The run's own input, once it is known. `undefined` = \"not available\" (no\n * section); `null` = \"available, and it is null\" (section renders `null`). */\n input?: unknown;\n output?: unknown;\n /** The failure's payload for a failed run. `null`/`undefined` = no error\n * section at all — the reverse gate to `input`/`output`, because an error\n * that is `null` is the absence of an error. */\n error?: unknown;\n /** A workflow run's steps. `undefined` = not a step-bearing run (no section);\n * `[]` = it ran and no step did (the panel's own empty state). */\n steps?: ExecutionLogStep[];\n /** The execution this one is a re-run of — shown as \"Re-run of <id>\".\n * `null`/omitted ⇒ an ordinary execution, no line. */\n rerunOf?: string | null;\n}\n\nexport interface ExecutionDetailProps {\n /** The execution to show, or `null` when there is nothing to show yet. */\n execution: ExecutionDetailValue | null;\n /** `true` while the fetch for a `null` `execution` is still in flight —\n * renders the loading branch. Once an `execution` is present it is rendered\n * as-is: a host re-fetching (polling a running run) keeps showing the last\n * known state rather than flashing back to \"Loading…\". */\n loading?: boolean;\n /** A failure to surface, e.g. the fetch for this execution failed. Rendered\n * as an alert in EVERY branch — it is about the view, not about the run. */\n errorMessage?: ReactNode;\n /** Supplied ⇒ a dismiss control renders and calls this. Omitted ⇒ no\n * control. */\n onClose?: () => void;\n /** Supplied ⇒ the \"Open in visual editor\" button renders and calls this.\n * Omitted ⇒ no button (a function/endpoint run has no visual editor to open). */\n onOpenInEditor?: () => void;\n /** Supplied ⇒ a \"Back\" control renders above everything else and calls this\n * — for a host that shows this detail IN PLACE of the list it was opened\n * from. Omitted ⇒ no control. Rendered in every branch, so a view whose\n * fetch failed can still be left. */\n onBack?: () => void;\n /** Supplied ⇒ the \"Re-run\" button renders and calls this. Omitted ⇒ no button. */\n onRerun?: () => void;\n /** `true` while the host's re-run is in flight — the button is disabled and\n * says so. */\n rerunning?: boolean;\n /** Supplied ⇒ the \"Re-run of <id>\" id is a link that calls this with that\n * id, to open the original. Omitted ⇒ plain text. */\n onOpenExecution?: (id: string) => void;\n}\n\nconst KIND_LABEL: Record<ExecutionKind, string> = {\n function: \"Function\",\n endpoint: \"Endpoint\",\n workflow: \"Workflow\",\n};\n\n/** A value the section is showing that JSON cannot serialise (`undefined`,\n * a function, a symbol) renders as `null` rather than an empty block. */\nfunction toJson(value: unknown): string {\n return JSON.stringify(value, null, 2) ?? \"null\";\n}\n\n/**\n * Everything known about one past execution: which callable it was and how it\n * went, its timing, its own input/output/error, and — for a workflow run — the\n * per-step list.\n *\n * The per-step list sits directly under the timing, above the run's own\n * payloads: for a workflow it is the substance of the view (D2), and burying it\n * under three JSON blocks would make the run read as a function call with\n * appendices.\n *\n * A pure display leaf — no fetching, no polling, no live-ticking timer.\n */\nexport function ExecutionDetail({\n execution,\n loading = false,\n errorMessage,\n onClose,\n onOpenInEditor,\n onBack,\n onRerun,\n rerunning = false,\n onOpenExecution,\n}: ExecutionDetailProps) {\n return (\n <section className=\"w6w-execution-detail w6w-stack\" data-testid=\"execution-detail\">\n {onBack && (\n <div className=\"w6w-execution-detail-back\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-detail-back\"\n onClick={onBack}\n >\n <span aria-hidden=\"true\">←</span> Back\n </button>\n </div>\n )}\n {errorMessage != null && (\n <p\n role=\"alert\"\n className=\"w6w-execution-detail-error-message\"\n data-testid=\"execution-detail-error-message\"\n >\n {errorMessage}\n </p>\n )}\n {execution ? (\n <Body\n execution={execution}\n onClose={onClose}\n onOpenInEditor={onOpenInEditor}\n onRerun={onRerun}\n rerunning={rerunning}\n onOpenExecution={onOpenExecution}\n />\n ) : loading ? (\n <p className=\"w6w-muted\" data-testid=\"execution-detail-loading\">\n Loading…\n </p>\n ) : (\n <p className=\"w6w-muted\" data-testid=\"execution-detail-empty\">\n No execution selected.\n </p>\n )}\n </section>\n );\n}\n\nfunction Body({\n execution,\n onClose,\n onOpenInEditor,\n onRerun,\n rerunning,\n onOpenExecution,\n}: {\n execution: ExecutionDetailValue;\n onClose?: () => void;\n onOpenInEditor?: () => void;\n onRerun?: () => void;\n rerunning: boolean;\n onOpenExecution?: (id: string) => void;\n}) {\n const rerunOf = execution.rerunOf;\n return (\n <>\n <div className=\"w6w-execution-detail-head\">\n <div className=\"w6w-execution-detail-title\">\n <h3 className=\"w6w-execution-detail-name\">{execution.callableName}</h3>\n <div className=\"w6w-execution-detail-meta\">\n <StepStatusPill state={execution.status} />\n <span className=\"w6w-execution-detail-kind w6w-muted w6w-small\">\n {KIND_LABEL[execution.kind]}\n </span>\n </div>\n </div>\n {(onRerun || onOpenInEditor || onClose) && (\n <div className=\"w6w-execution-detail-actions\">\n {onRerun && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-execution-detail-rerun\"\n data-testid=\"execution-detail-rerun\"\n title=\"Run it again with the same input\"\n disabled={rerunning}\n onClick={onRerun}\n >\n <Icon name=\"sync\" size={14} /> {rerunning ? \"Re-running…\" : \"Re-run\"}\n </button>\n )}\n {onOpenInEditor && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-detail-open-editor\"\n onClick={onOpenInEditor}\n >\n Open in visual editor\n </button>\n )}\n {onClose && (\n <IconButton label=\"Close\" data-testid=\"execution-detail-close\" onClick={onClose}>\n ×\n </IconButton>\n )}\n </div>\n )}\n </div>\n\n <p className=\"w6w-execution-detail-id-line\">\n <code className=\"w6w-execution-detail-id\" data-testid=\"execution-detail-id\">\n {execution.id}\n </code>\n </p>\n\n {rerunOf && (\n <p className=\"w6w-execution-detail-rerun-of\" data-testid=\"execution-detail-rerun-of\">\n <span className=\"w6w-execution-rerun-tag\">Re-run</span>\n <span className=\"w6w-muted w6w-small\">of</span>\n {onOpenExecution ? (\n <button\n type=\"button\"\n className=\"w6w-execution-detail-rerun-of-link\"\n data-testid=\"execution-detail-rerun-of-link\"\n onClick={() => onOpenExecution(rerunOf)}\n >\n <code>{rerunOf}</code>\n </button>\n ) : (\n <code>{rerunOf}</code>\n )}\n </p>\n )}\n\n <dl className=\"w6w-execution-detail-timing\">\n <TimingItem label=\"Started\" value={formatExecutionTime(execution.startedAt)} />\n <TimingItem\n label=\"Finished\"\n value={execution.finishedAt ? formatExecutionTime(execution.finishedAt) : \"—\"}\n />\n <TimingItem label=\"Duration\" value={formatDurationMs(execution.durationMs)} />\n </dl>\n\n {execution.steps !== undefined && (\n <section\n className=\"w6w-execution-detail-section w6w-stack\"\n data-testid=\"execution-detail-steps\"\n >\n <strong className=\"w6w-small\">Nodes</strong>\n <ExecutionLogPanel steps={execution.steps} emptyLabel=\"No nodes ran.\" />\n </section>\n )}\n\n {execution.input !== undefined && (\n <JsonSection title=\"Input\" testid=\"execution-detail-input\" value={execution.input} />\n )}\n {execution.output !== undefined && (\n <JsonSection title=\"Output\" testid=\"execution-detail-output\" value={execution.output} />\n )}\n {execution.error != null && (\n <JsonSection title=\"Error\" testid=\"execution-detail-error\" value={execution.error} />\n )}\n </>\n );\n}\n\nfunction TimingItem({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"w6w-execution-detail-timing-item\">\n <dt>{label}</dt>\n <dd>{value}</dd>\n </div>\n );\n}\n\n/**\n * One payload as read-only, syntax-highlighted JSON — `CodeBlock`, the same\n * idiom `ExecutionLogPanel` renders a step's input/output through (see its own\n * doc comment for why `CodeBlock` and not `JsonEditor`/`<pre>`).\n */\nfunction JsonSection({ title, testid, value }: { title: string; testid: string; value: unknown }) {\n return (\n <section className=\"w6w-execution-detail-section w6w-stack\" data-testid={testid}>\n <strong className=\"w6w-small\">{title}</strong>\n <CodeBlock code={toJson(value)} language=\"json\" />\n </section>\n );\n}\n","/**\n * How the reliability board arranges itself — the decisions that are arithmetic\n * rather than markup, kept pure (no React, no DOM) so they test without a DOM\n * and so `@w6w/embed` can import them beside the components.\n *\n * **None of these decide a STATE.** Every state read below arrived already\n * decided by the server; nothing here compares a ratio, applies a threshold to\n * call data, or invents a fifth word. What these decide is where a row is PUT,\n * which is presentation.\n */\n\n/** The four words the server uses for a health verdict. */\nexport type ReliabilityViewState = \"ok\" | \"degraded\" | \"down\" | \"unknown\";\n\n/**\n * The row shape the reliability components render — owned by `@w6w/ui` so it\n * imports nothing from the SDK. The SDK's `ReliabilityService` assigns to it\n * structurally; the generic functions below keep the caller's richer row type.\n */\nexport interface ReliabilityServiceView {\n appId: string;\n displayName: string;\n /** Inline icon fields — the board never asks a catalog for them. */\n iconSrc?: string;\n iconSrcDark?: string;\n brandColor?: string;\n /** \"Did YOUR calls succeed\". */\n state: ReliabilityViewState;\n calls: number;\n errors: { e4xx: number; e429: number; eAuth: number; e5xx: number };\n p95Ms: number | null;\n ongoingOutageId: string | null;\n /** One entry per calendar day, oldest first, exactly as the server sent it. */\n uptime: readonly { day: string; state: ReliabilityViewState }[];\n /** \"What does the vendor say about itself\"; `null` when no public check exists. */\n vendorStatus: { state: ReliabilityViewState; message: string | null } | null;\n /** The server's tier for the row — read, never re-derived. */\n attention: \"now\" | \"recent\" | \"none\";\n}\n\n/** One point of the performance scatter — a service with both a call volume and a measured p95. */\nexport interface PerformancePoint {\n appId: string;\n displayName: string;\n calls: number;\n p95Ms: number;\n state: ReliabilityViewState;\n /** Total errors across all four kinds — drives the point's size, not its position. */\n errorCount: number;\n}\n\n/**\n * Every service with at least one timed call, as a (calls, p95) point — what\n * the performance chart plots. Excludes `p95Ms: null`: there is no Y position\n * for a service with nothing timed.\n */\nexport function performancePoints(services: readonly ReliabilityServiceView[]): PerformancePoint[] {\n const points: PerformancePoint[] = [];\n for (const s of services) {\n if (s.p95Ms === null) continue;\n points.push({\n appId: s.appId,\n displayName: s.displayName,\n calls: s.calls,\n p95Ms: s.p95Ms,\n state: s.state,\n errorCount: s.errors.e4xx + s.errors.e429 + s.errors.eAuth + s.errors.e5xx,\n });\n }\n return points;\n}\n\n/**\n * Does this service want the reader's attention? READS the tier the server\n * sent (`attention`), never re-derives it from `state` or `vendorStatus`: the\n * server's `boardRank` is the one implementation, and a second copy here would\n * drift. `now` and `recent` both count; they differ in tense only.\n */\nexport function needsAttention(service: Pick<ReliabilityServiceView, \"attention\">): boolean {\n return service.attention === \"now\" || service.attention === \"recent\";\n}\n\n/** The board in its three groups, each keeping the server's own ordering. */\nexport interface BoardPartition<T extends ReliabilityServiceView = ReliabilityServiceView> {\n /** Broken right now, on either signal. */\n now: T[];\n /** Clear now, but this window holds a failed stretch or an open advisory. */\n recent: T[];\n /** Everything else, in the server's recency order. */\n clear: T[];\n}\n\n/**\n * Group the board without reordering within any group. Bucketing is not\n * sorting: each group comes out in the order it arrived. An unrecognised\n * `attention` value falls to `clear` rather than throwing — a client can be\n * older than the server that answered it.\n */\nexport function partitionBoard<T extends ReliabilityServiceView>(\n services: readonly T[],\n): BoardPartition<T> {\n const groups: BoardPartition<T> = { now: [], recent: [], clear: [] };\n for (const s of services) {\n if (s.attention === \"now\") groups.now.push(s);\n else if (s.attention === \"recent\") groups.recent.push(s);\n else groups.clear.push(s);\n }\n return groups;\n}\n\n/**\n * The uptime strip's cells for one service — the server's own array, in the\n * order it arrived (oldest first). A passthrough on purpose: no sort, no\n * reverse, no gap filling. The strip has no date axis, so a reversed array is\n * visually plausible and would silently move an outage to the wrong end.\n */\nexport function uptimeDays(service: Pick<ReliabilityServiceView, \"uptime\">): {\n day: string;\n state: ReliabilityViewState;\n}[] {\n return service.uptime.map((entry) => ({ day: entry.day, state: entry.state }));\n}\n\n/** Compact mode shows at most this many needs-attention cards, `now` filling first. */\nexport const ATTENTION_DISPLAY_CAP = 3;\n/** Compact mode shows this many table rows unless the caller passes `limit`. */\nexport const RECENT_DISPLAY_CAP = 5;\n\n/** What the board shows and what a display cap hid. */\nexport interface BoardDisplay<T extends ReliabilityServiceView = ReliabilityServiceView> {\n /** TRUE total of attention rows (the whole input, not the capped slice). */\n attentionCount: number;\n shownNow: T[];\n shownRecent: T[];\n hiddenAttentionCount: number;\n /** Table rows in the server's order, every attention tier included. */\n shownTable: T[];\n hiddenTableCount: number;\n}\n\n/**\n * Apply the display caps to the complete board. Compact: ≤ 3 attention cards\n * (`now` first, `recent` tops up) and `limit ?? 5` table rows; otherwise\n * uncapped. Hidden counts are computed from the full input, so they are real.\n */\nexport function displayBoard<T extends ReliabilityServiceView>(\n services: readonly T[],\n opts: { compact?: boolean; limit?: number } = {},\n): BoardDisplay<T> {\n const compact = opts.compact ?? false;\n const { now, recent } = partitionBoard(services);\n const attentionCount = now.length + recent.length;\n const shownNow = compact ? now.slice(0, ATTENTION_DISPLAY_CAP) : now;\n const shownRecent = compact\n ? recent.slice(0, Math.max(0, ATTENTION_DISPLAY_CAP - shownNow.length))\n : recent;\n const shownTable = compact ? services.slice(0, opts.limit ?? RECENT_DISPLAY_CAP) : [...services];\n return {\n attentionCount,\n shownNow,\n shownRecent,\n hiddenAttentionCount: attentionCount - shownNow.length - shownRecent.length,\n shownTable,\n hiddenTableCount: services.length - shownTable.length,\n };\n}\n","import type { ReactElement, MouseEvent as ReactMouseEvent } from \"react\";\nimport { type ReliabilityServiceView, performancePoints } from \"../reliability-board-layout.ts\";\n\n/**\n * The performance chart — call volume × p95 latency, one point per API. One\n * axis never tells the whole story: a slow service nobody calls much matters\n * less than a slow service taking most of the traffic, so this is a real 2-axis\n * scatter, not a bar-per-app list.\n *\n * Ring colour carries exec status via the `--w6w-health-*` tokens (same as the\n * table's pills) and dot size carries the error count. Rows arrive with every\n * field they need; the chart makes no request.\n *\n * Navigation is the host's: with `getHref` each point is a real SVG `<a href>`;\n * a click calls `onOpen(appId, event)` and is never `preventDefault`ed here.\n * Neither given ⇒ points are not links.\n *\n * A fixed `viewBox` with a matching CSS `aspect-ratio` keeps points circular.\n * The y-axis runs INVERTED — 0ms at the top, the max at the bottom — so \"up\"\n * reads as \"better\" the same way \"right\" (more calls) does: the top-right\n * corner is fast AND heavily used.\n */\nconst WIDTH = 640;\nconst HEIGHT = 340;\nconst PAD = { top: 16, right: 24, bottom: 40, left: 56 };\n\nfunction niceMax(value: number): number {\n if (value <= 0) return 1;\n const magnitude = 10 ** Math.floor(Math.log10(value));\n const steps = [1, 2, 5, 10];\n for (const step of steps) {\n if (value <= step * magnitude) return step * magnitude;\n }\n return 10 * magnitude;\n}\n\nfunction ticks(max: number, count = 5): number[] {\n return Array.from({ length: count + 1 }, (_, i) => Math.round((max * i) / count));\n}\n\nexport interface ReliabilityChartProps<T extends ReliabilityServiceView = ReliabilityServiceView> {\n services: readonly T[];\n /** Real `<a href>` on each point when given. */\n getHref?: (appId: string) => string;\n /** Called on a point click; the host decides whether to `preventDefault`. */\n onOpen?: (appId: string, event: ReactMouseEvent<Element>) => void;\n}\n\nexport function ReliabilityChart<T extends ReliabilityServiceView>({\n services,\n getHref,\n onOpen,\n}: ReliabilityChartProps<T>): ReactElement {\n const points = performancePoints(services);\n\n if (points.length === 0) {\n return <p className=\"w6w-muted w6w-small\">No timed calls in this window yet.</p>;\n }\n\n const maxCalls = niceMax(Math.max(...points.map((p) => p.calls)));\n const maxP95 = niceMax(Math.max(...points.map((p) => p.p95Ms)));\n const maxErrors = Math.max(1, ...points.map((p) => p.errorCount));\n\n const plotW = WIDTH - PAD.left - PAD.right;\n const plotH = HEIGHT - PAD.top - PAD.bottom;\n const x = (calls: number) => PAD.left + (calls / maxCalls) * plotW;\n // Inverted on purpose — lower p95 (faster) sits HIGHER on the plot.\n const y = (p95: number) => PAD.top + (p95 / maxP95) * plotH;\n // 16px..30px icon diameter, scaled by error share.\n const iconSize = (errors: number) => 16 + (errors / maxErrors) * 14;\n\n const xTicks = ticks(maxCalls);\n const yTicks = ticks(maxP95);\n const yAxisTitleX = 18;\n const yAxisTitleY = PAD.top + plotH / 2;\n\n return (\n <div className=\"w6w-rel-scatter\">\n <svg\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n style={{ aspectRatio: `${WIDTH} / ${HEIGHT}` }}\n role=\"img\"\n aria-label=\"API performance: calls versus p95 latency, one point per API\"\n >\n <rect\n x={PAD.left}\n y={PAD.top}\n width={plotW}\n height={plotH}\n className=\"w6w-rel-scatter-plot-bg\"\n />\n\n {yTicks.map((t) => (\n <g key={`y-${t}`}>\n <line\n x1={PAD.left}\n x2={WIDTH - PAD.right}\n y1={y(t)}\n y2={y(t)}\n className=\"w6w-rel-scatter-grid\"\n />\n <text x={PAD.left - 8} y={y(t)} className=\"w6w-rel-scatter-axis-label\" textAnchor=\"end\">\n {t}\n </text>\n </g>\n ))}\n {xTicks.map((t) => (\n <text\n key={`x-${t}`}\n x={x(t)}\n y={HEIGHT - PAD.bottom + 18}\n className=\"w6w-rel-scatter-axis-label\"\n textAnchor=\"middle\"\n >\n {t}\n </text>\n ))}\n\n {/* Anchored on its own pivot so the rotation never leaves the viewBox. */}\n <text\n x={yAxisTitleX}\n y={yAxisTitleY}\n className=\"w6w-rel-scatter-axis-title\"\n textAnchor=\"middle\"\n transform={`rotate(-90, ${yAxisTitleX}, ${yAxisTitleY})`}\n >\n p95 (ms)\n </text>\n <text\n x={PAD.left + plotW / 2}\n y={HEIGHT - 4}\n className=\"w6w-rel-scatter-axis-title\"\n textAnchor=\"middle\"\n >\n calls in this window\n </text>\n\n {points.map((p) => {\n const size = iconSize(p.errorCount);\n const cx = x(p.calls);\n const cy = y(p.p95Ms);\n const dots = (\n <>\n <circle\n cx={cx}\n cy={cy}\n r={size / 2 + 2.5}\n className={`w6w-rel-scatter-ring w6w-rel-scatter-ring-${p.state}`}\n >\n <title>\n {p.displayName} — {p.calls} calls, {p.p95Ms} ms p95, {p.errorCount} errors\n </title>\n </circle>\n <circle\n cx={cx}\n cy={cy}\n r={size / 2}\n className={`w6w-rel-scatter-point w6w-rel-scatter-point-${p.state}`}\n />\n </>\n );\n if (getHref) {\n return (\n <a\n key={p.appId}\n href={getHref(p.appId)}\n className=\"w6w-rel-scatter-point-link\"\n onClick={onOpen ? (e) => onOpen(p.appId, e) : undefined}\n >\n {dots}\n </a>\n );\n }\n if (onOpen) {\n return (\n <g\n key={p.appId}\n // biome-ignore lint/a11y/useSemanticElements: an SVG group cannot be a <button>\n role=\"button\"\n tabIndex={0}\n className=\"w6w-rel-scatter-point-link\"\n onClick={(e) => onOpen(p.appId, e)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n (e.currentTarget as unknown as HTMLElement).dispatchEvent(\n new MouseEvent(\"click\", { bubbles: true }),\n );\n }\n }}\n >\n {dots}\n </g>\n );\n }\n return <g key={p.appId}>{dots}</g>;\n })}\n </svg>\n <p className=\"w6w-muted w6w-small w6w-rel-scatter-note\">\n Up is faster, right is more calls — top-right is the best outcome. Icon size is the error\n count in this window; ring colour is exec status.\n </p>\n </div>\n );\n}\n","import type { MouseEvent, ReactElement, ReactNode } from \"react\";\nimport {\n type ReliabilityServiceView,\n displayBoard,\n uptimeDays,\n} from \"../reliability-board-layout.ts\";\nimport { AppIcon } from \"./AppIcon.tsx\";\nimport { HealthStatusPill } from \"./HealthStatusPill.tsx\";\nimport { ReliabilityChart } from \"./ReliabilityChart.tsx\";\nimport { UptimeStrip } from \"./UptimeStrip.tsx\";\n\n/**\n * The reliability board's presentation: needs-attention cards, the\n * performance chart and the services table, drawn from rows passed in.\n * Router-free and request-free (no provider needed) — icons come from the\n * rows' own `iconSrc`/`iconSrcDark`/`brandColor`. Loading, error and\n * no-project states belong to whatever fetches the rows.\n *\n * Navigation, at every site (issue card, service cell, chart point): with\n * `getHref` a real anchor; a click calls `onOpen(appId, event)` and is never\n * `preventDefault`ed here; only `onOpen` ⇒ a button; neither ⇒ not a link.\n */\n\ntype Open = (appId: string, event: MouseEvent<Element>) => void;\n\nexport interface ReliabilityListWindow {\n from: string;\n to: string;\n days: number;\n}\n\nexport interface ReliabilityListProps<T extends ReliabilityServiceView = ReliabilityServiceView> {\n services: readonly T[];\n /** The window the rows cover; labels the heading. */\n window?: ReliabilityListWindow;\n /** Table column label (\"Last N days\"); defaults to `window?.days ?? 30`. */\n days?: number;\n /** Trim the display: ≤3 attention cards, `limit ?? 5` table rows, chart off. */\n compact?: boolean;\n /** Defaults to `!compact`. */\n showChart?: boolean;\n /** Compact table row cap (default 5). */\n limit?: number;\n getHref?: (appId: string) => string;\n onOpen?: Open;\n /** \"Show all services →\" / \"view all →\" render only when one of these is given. */\n showAllHref?: string;\n onShowAll?: (event: MouseEvent<Element>) => void;\n slots?: {\n /** Replaces the \"Service reliability\" title text. */\n header?: ReactNode;\n /** Rendered at the end of the heading row. */\n actions?: ReactNode;\n /** Replaces the \"No services yet\" message. */\n empty?: ReactNode;\n };\n}\n\n/** Short date for the window line (\"Jun 28 – Jul 27\"). */\nfunction formatDay(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleDateString(undefined, { month: \"short\", day: \"numeric\" });\n}\n\n/** The one anchor/button/plain wrapper every navigation site shares. */\nfunction Target({\n appId,\n className,\n title,\n getHref,\n onOpen,\n children,\n}: {\n appId: string;\n className: string;\n title?: string;\n getHref?: (appId: string) => string;\n onOpen?: Open;\n children: ReactNode;\n}) {\n if (getHref) {\n return (\n <a\n className={className}\n href={getHref(appId)}\n title={title}\n onClick={onOpen ? (e) => onOpen(appId, e) : undefined}\n >\n {children}\n </a>\n );\n }\n if (onOpen) {\n return (\n <button type=\"button\" className={className} title={title} onClick={(e) => onOpen(appId, e)}>\n {children}\n </button>\n );\n }\n return (\n <div className={className} title={title}>\n {children}\n </div>\n );\n}\n\n/** \"Did YOUR calls succeed\" — shared by the table cell and the issue card. */\nfunction ExecStatusSignal({ service }: { service: ReliabilityServiceView }) {\n return (\n <span className=\"w6w-rel-signal\">\n <HealthStatusPill state={service.state} />\n {service.ongoingOutageId && <span className=\"w6w-rel-tag\">outage open</span>}\n {service.calls === 0 && <span className=\"w6w-muted w6w-small\">no calls</span>}\n </span>\n );\n}\n\n/**\n * The API's own status, from the app's declared public health check. Kept a\n * SEPARATE signal from `ExecStatusSignal`: they answer different questions and\n * routinely disagree usefully. `null` ⇒ \"not published\", not an `unknown` pill.\n */\nfunction ApiStatusSignal({ vendor }: { vendor: ReliabilityServiceView[\"vendorStatus\"] }) {\n if (!vendor) return <span className=\"w6w-muted w6w-small\">not published</span>;\n // `unknown` is about US, not the API: we asked and could not tell.\n const unreadable = vendor.state === \"unknown\";\n return (\n <span className=\"w6w-rel-signal\" title={vendor.message ?? undefined}>\n <HealthStatusPill state={vendor.state} label={unreadable ? \"Unavailable\" : undefined} />\n {!unreadable && vendor.message && (\n <span className=\"w6w-rel-vendor-msg w6w-small\">{vendor.message}</span>\n )}\n </span>\n );\n}\n\ninterface NavProps {\n getHref?: (appId: string) => string;\n onOpen?: Open;\n}\n\nfunction IssueCard({ service, getHref, onOpen }: { service: ReliabilityServiceView } & NavProps) {\n return (\n <Target\n appId={service.appId}\n className=\"w6w-rel-issue-card\"\n title={`${service.displayName} — open service detail`}\n getHref={getHref}\n onOpen={onOpen}\n >\n <span className=\"w6w-rel-issue-head\">\n <AppIcon\n src={service.iconSrc}\n srcDark={service.iconSrcDark}\n brandColor={service.brandColor}\n name={service.displayName}\n size={24}\n />\n <span className=\"w6w-rel-issue-head-text\">\n <strong>{service.displayName}</strong>\n {service.attention === \"recent\" && (\n <span className=\"w6w-muted w6w-small\">trouble earlier in this window</span>\n )}\n </span>\n </span>\n <span className=\"w6w-rel-issue-signals\">\n <span className=\"w6w-rel-issue-signal\">\n <span className=\"w6w-muted w6w-small\">w6w exec</span>\n <ExecStatusSignal service={service} />\n </span>\n <span className=\"w6w-rel-issue-signal\">\n <span className=\"w6w-muted w6w-small\">API status</span>\n <ApiStatusSignal vendor={service.vendorStatus} />\n </span>\n </span>\n </Target>\n );\n}\n\nfunction ServiceTableRow({\n service,\n getHref,\n onOpen,\n}: { service: ReliabilityServiceView } & NavProps) {\n const noCalls = service.calls === 0;\n return (\n <tr\n className={`w6w-rel-tr${service.attention !== \"none\" ? \" w6w-rel-attention\" : \"\"}`}\n data-attention={service.attention === \"none\" ? undefined : service.attention}\n >\n <td className=\"w6w-rel-td-service\">\n <Target appId={service.appId} className=\"w6w-rel-open\" getHref={getHref} onOpen={onOpen}>\n <AppIcon\n src={service.iconSrc}\n srcDark={service.iconSrcDark}\n brandColor={service.brandColor}\n name={service.displayName}\n size={28}\n />\n <span className=\"w6w-rel-td-service-text\">\n <strong>{service.displayName}</strong>\n <code className=\"w6w-muted w6w-small\">{service.appId}</code>\n </span>\n </Target>\n </td>\n\n <td className=\"w6w-rel-td-status\">\n <span className=\"w6w-rel-status-row\">\n <span className=\"w6w-rel-status-label w6w-muted w6w-small\">Ops</span>\n <ExecStatusSignal service={service} />\n </span>\n <span className=\"w6w-rel-status-row\">\n <span className=\"w6w-rel-status-label w6w-muted w6w-small\">API</span>\n <ApiStatusSignal vendor={service.vendorStatus} />\n </span>\n </td>\n\n <td className=\"w6w-rel-td-uptime\">\n {noCalls ? (\n // A zero-call window is one identical hatched strip — the note says it better.\n <span className=\"w6w-rel-idle-note\">No calls in this window</span>\n ) : (\n <>\n {/* Oldest day first, exactly as the server sent it. */}\n <UptimeStrip\n days={uptimeDays(service)}\n ariaLabel={`${service.displayName}, ${service.uptime.length}-day status, oldest day first`}\n />\n <span className=\"w6w-muted w6w-small\">{service.calls} calls</span>\n </>\n )}\n </td>\n\n <td className=\"w6w-rel-td-p95\">{service.p95Ms === null ? \"—\" : `${service.p95Ms} ms`}</td>\n </tr>\n );\n}\n\nexport function ReliabilityList<T extends ReliabilityServiceView>({\n services,\n window: win,\n days,\n compact = false,\n showChart,\n limit,\n getHref,\n onOpen,\n showAllHref,\n onShowAll,\n slots,\n}: ReliabilityListProps<T>): ReactElement {\n const windowDays = days ?? win?.days ?? 30;\n // Reads `state` ONLY, on purpose: the card's copy says every service \"came\n // back ok\", a statement about YOUR CALLS that stays true while a vendor\n // reports an incident you have not hit. The grouping below reads `attention`.\n const allClear = services.length > 0 && services.every((s) => s.calls > 0 && s.state === \"ok\");\n const {\n attentionCount,\n shownNow,\n shownRecent,\n hiddenAttentionCount,\n shownTable,\n hiddenTableCount,\n } = displayBoard(services, { compact, limit });\n const shouldShowChart = showChart ?? !compact;\n const canShowAll = showAllHref !== undefined || onShowAll !== undefined;\n const showAllLink = (text: string): ReactNode => {\n const className = text.startsWith(\"Show\") ? \"w6w-muted w6w-small\" : undefined;\n if (showAllHref !== undefined) {\n return (\n <a href={showAllHref} className={className} onClick={onShowAll}>\n {text}\n </a>\n );\n }\n if (onShowAll) {\n return (\n <button\n type=\"button\"\n className={`w6w-rel-show-all${className ? ` ${className}` : \"\"}`}\n onClick={onShowAll}\n >\n {text}\n </button>\n );\n }\n return null;\n };\n\n return (\n <section className=\"w6w-rel-section\">\n <h3 className=\"w6w-rel-heading\">\n <span>\n {slots?.header ?? \"Service reliability\"}{\" \"}\n {win && (\n <span className=\"w6w-muted w6w-small\">\n {formatDay(win.from)} – {formatDay(win.to)} · {win.days} days\n </span>\n )}\n </span>\n {compact && showAllLink(\"Show all services →\")}\n {slots?.actions}\n </h3>\n\n <div className={compact ? \"w6w-rel-card\" : undefined}>\n <p className=\"w6w-muted w6w-small w6w-rel-intro\">\n Connected services across your account. Performance for the selected project.\n </p>\n\n {allClear && (\n <div className={compact ? \"w6w-rel-allclear\" : \"w6w-rel-card w6w-rel-allclear\"}>\n <h4>All clear</h4>\n <p>\n Every service you called in the last {windowDays} days came back{\" \"}\n <HealthStatusPill state=\"ok\" /> — no degraded stretches, no outages.\n </p>\n </div>\n )}\n\n {services.length === 0 &&\n (slots?.empty ?? (\n <div className={compact ? undefined : \"w6w-rel-card\"}>\n <p className=\"w6w-muted\">\n No services yet — connect an integration or use a service in this project.\n </p>\n </div>\n ))}\n\n {services.length > 0 && (\n <>\n {attentionCount > 0 && (\n <div className=\"w6w-rel-group\">\n <h4 className=\"w6w-rel-group-head\">\n Needs attention{\" \"}\n <span className=\"w6w-muted w6w-small\">\n {shownNow.length + shownRecent.length} of {attentionCount}\n </span>\n </h4>\n <div className=\"w6w-rel-issues\">\n {[...shownNow, ...shownRecent].map((s) => (\n <IssueCard key={s.appId} service={s} getHref={getHref} onOpen={onOpen} />\n ))}\n </div>\n {hiddenAttentionCount > 0 && (\n <p className=\"w6w-muted w6w-small w6w-rel-more-note\">\n {hiddenAttentionCount} more {hiddenAttentionCount === 1 ? \"needs\" : \"need\"}{\" \"}\n attention{canShowAll && <> — {showAllLink(\"view all →\")}</>}\n </p>\n )}\n </div>\n )}\n\n {shouldShowChart && (\n <div className=\"w6w-rel-group\">\n <h4 className=\"w6w-rel-group-head\">Performance across your APIs</h4>\n <ReliabilityChart services={services} getHref={getHref} onOpen={onOpen} />\n </div>\n )}\n\n {shownTable.length > 0 && (\n <div className=\"w6w-rel-group\">\n <h4 className=\"w6w-rel-group-head\">\n {compact ? \"Services\" : \"All services\"}{\" \"}\n <span className=\"w6w-muted w6w-small\">\n {compact ? `${shownTable.length} of ${services.length}` : services.length}\n </span>\n </h4>\n <div className=\"w6w-rel-table-wrap\">\n <table className=\"w6w-rel-table\">\n <thead>\n <tr>\n <th>Service</th>\n <th>Status</th>\n <th>Last {windowDays} days</th>\n <th>Latency</th>\n </tr>\n </thead>\n <tbody>\n {shownTable.map((s) => (\n <ServiceTableRow\n key={s.appId}\n service={s}\n getHref={getHref}\n onOpen={onOpen}\n />\n ))}\n </tbody>\n </table>\n </div>\n {hiddenTableCount > 0 && (\n <p className=\"w6w-muted w6w-small w6w-rel-more-note\">\n {hiddenTableCount} more{canShowAll && <> — {showAllLink(\"view all →\")}</>}\n </p>\n )}\n </div>\n )}\n </>\n )}\n </div>\n </section>\n );\n}\n","import type { MouseEvent, ReactNode } from \"react\";\n\nexport interface DataTableColumn<Row> {\n key: string;\n header: ReactNode;\n /** Omitted ⇒ the cell shows `String(row[key] ?? \"\")`. */\n render?: (row: Row) => ReactNode;\n width?: string;\n align?: \"left\" | \"right\" | \"center\";\n /** With `getRowHref`, wrap this column's cells in an anchor. Default true. */\n link?: boolean;\n}\n\nexport interface DataTableProps<Row> {\n columns: readonly DataTableColumn<Row>[];\n rows: readonly Row[];\n rowKey: (row: Row) => string;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onRowClick?: (row: Row, e: MouseEvent<Element>) => void;\n /** When set, every cell of a `link !== false` column wraps its content in `<a href>`. */\n getRowHref?: (row: Row) => string | undefined;\n /** Rendered in place of the body when there are no rows and not `loading`. */\n empty?: ReactNode;\n loading?: boolean;\n className?: string;\n testId?: string;\n rowTestId?: (row: Row) => string | undefined;\n}\n\nfunction cellValue<Row>(col: DataTableColumn<Row>, row: Row): ReactNode {\n if (col.render) return col.render(row);\n return String((row as Record<string, unknown>)[col.key] ?? \"\");\n}\n\nexport function DataTable<Row>(props: DataTableProps<Row>) {\n const { columns, rows, rowKey, onRowClick, getRowHref, empty, loading, className, testId } =\n props;\n if (rows.length === 0 && !loading && empty !== undefined && empty !== null) {\n return <>{empty}</>;\n }\n // The frame owns the ONE outer border + radius (T-3); the table and its cells\n // draw inner separators only, so no outer edge is painted twice.\n return (\n <div className=\"w6w-data-table-frame\">\n <table\n className={className ? `w6w-data-table ${className}` : \"w6w-data-table\"}\n data-testid={testId}\n aria-busy={loading ? true : undefined}\n >\n <thead>\n <tr>\n {columns.map((c) => (\n <th key={c.key} style={{ width: c.width, textAlign: c.align }} scope=\"col\">\n {c.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => {\n const href = getRowHref?.(row);\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: row click is a mouse convenience; keyboard users reach the row through its cell anchors (getRowHref) or the column's own controls.\n <tr\n key={rowKey(row)}\n data-testid={props.rowTestId?.(row)}\n className={onRowClick ? \"w6w-data-table-row-clickable\" : undefined}\n onClick={onRowClick ? (e) => onRowClick(row, e) : undefined}\n >\n {columns.map((c) => {\n const content = cellValue(c, row);\n return (\n <td key={c.key} style={{ textAlign: c.align }}>\n {href !== undefined && c.link !== false ? (\n <a className=\"w6w-data-table-link\" href={href}>\n {content}\n </a>\n ) : (\n content\n )}\n </td>\n );\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\nexport interface EmptyStateProps {\n title?: ReactNode;\n children?: ReactNode;\n action?: ReactNode;\n className?: string;\n testId?: string;\n}\n\nexport function EmptyState({ title, children, action, className, testId }: EmptyStateProps) {\n return (\n <div\n className={className ? `w6w-empty-state ${className}` : \"w6w-empty-state\"}\n data-testid={testId}\n >\n <div className=\"w6w-empty-state-inner\">\n {title !== undefined && title !== null && (\n <div className=\"w6w-empty-state-title\">{title}</div>\n )}\n {children !== undefined && children !== null && (\n <div className=\"w6w-empty-state-body\">{children}</div>\n )}\n {action !== undefined && action !== null && (\n <div className=\"w6w-empty-state-action\">{action}</div>\n )}\n </div>\n </div>\n );\n}\n","import { type MouseEvent, type ReactNode, useState } from \"react\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { EmptyState } from \"./EmptyState.tsx\";\n\n/** One row of a {@link CallableList}. The host decides `archived`; the list never learns a kind. */\nexport interface CallableListRow {\n id: string;\n title: ReactNode;\n description?: ReactNode;\n archived: boolean;\n /** Extra badges, rendered before the archived badge in the trailing slot. */\n badges?: ReactNode;\n /** Trailing content; sits inside the row's anchor when `getHref` is set, so keep it non-interactive. */\n trailing?: ReactNode;\n}\n\nexport interface CallableListProps {\n rows: readonly CallableListRow[];\n title: ReactNode;\n description?: ReactNode;\n /** Shown (inside an EmptyState) when no rows exist at all and not `loading`. */\n emptyCopy?: ReactNode;\n /** Label of the New button. Defaults to \"New\". */\n newLabel?: string;\n /** Tooltip (`title` attribute) on each openable row. */\n openRowTitle?: string;\n testIds?: { showArchived?: string; importOpen?: string; archivedBadge?: string };\n loading?: boolean;\n error?: string | null;\n /** The New button renders only when this is set. */\n onCreate?: () => void;\n /** New button is disabled and reads \"Creating…\" while true. */\n creating?: boolean;\n /** The Import button renders only when this is set. */\n onImport?: () => void;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onOpen?: (id: string, event: MouseEvent<Element>) => void;\n /** When set, each row is a real `<a href>`. */\n getHref?: (id: string) => string;\n /** Controlled \"Show archived\". Omit for an uncontrolled toggle that starts off. */\n showArchived?: boolean;\n onShowArchivedChange?: (next: boolean) => void;\n slots?: {\n /** Replaces the default title/description block (the Show-archived toggle stays). */\n header?: ReactNode;\n /** Rendered before Import/New. */\n actions?: ReactNode;\n /** Replaces `emptyCopy`. */\n empty?: ReactNode;\n };\n}\n\n/**\n * A presentational list of callables (Functions, Endpoints, Workflows): rows in, callbacks out.\n * Owns only the archived filter and its toggle; it knows no router, query, modal or kind.\n * Rows render through {@link DataTable}: a click handler with `onOpen`, anchors with `getHref`.\n * No visible rows renders an {@link EmptyState}; when only archived rows exist it offers \"Show archived\".\n */\nexport function CallableList({\n rows,\n title,\n description,\n emptyCopy,\n newLabel = \"New\",\n openRowTitle,\n testIds,\n loading,\n error,\n onCreate,\n creating,\n onImport,\n onOpen,\n getHref,\n showArchived: showArchivedProp,\n onShowArchivedChange,\n slots,\n}: CallableListProps) {\n const [showArchivedState, setShowArchivedState] = useState(false);\n const controlled = showArchivedProp !== undefined;\n const showArchived = controlled ? showArchivedProp : showArchivedState;\n const visible = showArchived ? rows : rows.filter((r) => !r.archived);\n const interactive = onOpen !== undefined || getHref !== undefined;\n const setShowArchived = (next: boolean) => {\n if (!controlled) setShowArchivedState(next);\n onShowArchivedChange?.(next);\n };\n const columns: DataTableColumn<CallableListRow>[] = [\n {\n key: \"main\",\n header: \"Name\",\n render: (row) => {\n const body = (\n <span className=\"w6w-callable-list-main\" title={interactive ? openRowTitle : undefined}>\n <span>{row.title}</span>\n {row.description != null && (\n <span className=\"w6w-muted w6w-small w6w-callable-list-row-desc\">\n {row.description}\n </span>\n )}\n </span>\n );\n // The click lands on the row (DataTable `onRowClick`); the button is the keyboard route in.\n return onOpen && !getHref ? (\n <button type=\"button\" className=\"w6w-callable-list-open\">\n {body}\n </button>\n ) : (\n body\n );\n },\n },\n {\n key: \"trail\",\n header: \"\",\n align: \"right\",\n render: (row) =>\n row.archived || row.badges != null || row.trailing != null ? (\n <span className=\"w6w-callable-list-trail\">\n {row.badges}\n {row.archived && (\n <span className=\"w6w-callable-list-badge\" data-testid={testIds?.archivedBadge}>\n archived\n </span>\n )}\n {row.trailing}\n </span>\n ) : null,\n },\n ];\n const archivedOnly = rows.length > 0 && visible.length === 0;\n\n return (\n <section className=\"w6w-callable-list\">\n <div className=\"w6w-callable-list-head\">\n <div className=\"w6w-callable-list-heading\">\n {slots?.header ?? (\n <>\n <h2 className=\"w6w-callable-list-title\">{title}</h2>\n {description != null && (\n <p className=\"w6w-muted w6w-small w6w-callable-list-description\">{description}</p>\n )}\n </>\n )}\n <label className=\"w6w-muted w6w-small w6w-callable-list-toggle\">\n <input\n type=\"checkbox\"\n checked={showArchived}\n data-testid={testIds?.showArchived}\n onChange={(e) => setShowArchived(e.target.checked)}\n />\n Show archived\n </label>\n </div>\n <div className=\"w6w-callable-list-actions\">\n {slots?.actions}\n {onImport && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid={testIds?.importOpen}\n onClick={onImport}\n >\n Import\n </button>\n )}\n {onCreate && (\n <button type=\"button\" className=\"w6w-btn\" disabled={creating} onClick={onCreate}>\n {creating ? \"Creating…\" : newLabel}\n </button>\n )}\n </div>\n </div>\n\n {error && <div className=\"w6w-error\">{error}</div>}\n\n <div className=\"w6w-callable-list-body\">\n {loading && <p className=\"w6w-muted\">Loading…</p>}\n {visible.length === 0 && !loading ? (\n archivedOnly ? (\n <EmptyState\n testId=\"w6w-callable-list-empty\"\n action={\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setShowArchived(true)}\n >\n Show archived\n </button>\n }\n >\n {rows.length === 1\n ? \"The only item is archived.\"\n : `All ${rows.length} items are archived.`}\n </EmptyState>\n ) : (\n <EmptyState testId=\"w6w-callable-list-empty\">{slots?.empty ?? emptyCopy}</EmptyState>\n )\n ) : (\n <DataTable\n columns={columns}\n rows={visible}\n rowKey={(r) => r.id}\n loading={loading}\n getRowHref={getHref ? (r) => getHref(r.id) : undefined}\n onRowClick={onOpen ? (r, event) => onOpen(r.id, event) : undefined}\n />\n )}\n </div>\n </section>\n );\n}\n","import type { MouseEvent, ReactNode } from \"react\";\nimport { type InlineAppMeta, resolveConnectionAppMeta } from \"../connection-app-meta.ts\";\nimport type { ConnectionSummary } from \"../types.ts\";\nimport { AppIcon } from \"./AppIcon.tsx\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\nimport { EditButton } from \"./EditButton.tsx\";\nimport { EmptyState } from \"./EmptyState.tsx\";\n\nexport interface ConnectionListProps {\n connections: readonly ConnectionSummary[];\n /**\n * App meta by id, used for rows whose own inline `app` is `undefined` (an older server).\n * Rows with an inline `app` object, or `null`, never consult it.\n */\n appsById?: ReadonlyMap<string, InlineAppMeta>;\n loading?: boolean;\n error?: string | null;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onOpen?: (id: string, event: MouseEvent<Element>) => void;\n /** When set, each openable row is a real `<a href>`. */\n getHref?: (id: string) => string;\n /**\n * Renders an Edit button per row. Pass it only when the host's adapter has `updateConnection`\n * (otherwise the modal it opens has nothing to save with).\n */\n onEdit?: (connection: ConnectionSummary) => void;\n /** Renders a Delete button per row. Confirmation and the delete call are the host's. */\n onDelete?: (connection: ConnectionSummary) => void;\n /** Disables every Delete button while a delete is in flight. */\n busy?: boolean;\n slots?: {\n /** Heading block above the rows. */\n header?: ReactNode;\n /** Trailing action(s) next to the header (e.g. an \"Add\" button). */\n actions?: ReactNode;\n /** Shown when there are no connections and the list is not `loading`. */\n empty?: ReactNode;\n };\n}\n\n/**\n * A presentational list of connections: rows in, callbacks out; it needs no provider. Rows render\n * through {@link DataTable} (name/app, status, and an Edit/Delete column that is never a link).\n *\n * A `builtIn` row (the server's synthetic \"no credential\" entry) is a plain non-interactive item:\n * no link, no `onOpen`, no Edit, no Delete, because the server 404s get/test/delete on its id.\n * Detection is `row.builtIn === true`, never an id prefix.\n */\nexport function ConnectionList({\n connections,\n appsById,\n loading,\n error,\n onOpen,\n getHref,\n onEdit,\n onDelete,\n busy,\n slots,\n}: ConnectionListProps) {\n const byId = appsById ?? new Map<string, InlineAppMeta>();\n const hasActions = onEdit !== undefined || onDelete !== undefined;\n const columns: DataTableColumn<ConnectionSummary>[] = [\n {\n key: \"name\",\n header: \"Name\",\n render: (c) => {\n const app = resolveConnectionAppMeta(c, byId);\n const name = c.displayName || c.id;\n return (\n <span className=\"w6w-connection-cell-name\">\n <AppIcon\n src={app?.iconSvg}\n srcDark={app?.iconSvgDark}\n brandColor={app?.brandColor}\n name={app?.displayName ?? c.appId}\n />\n <strong className=\"w6w-connection-name\" title={name}>\n {name}\n </strong>{\" \"}\n <span className=\"w6w-muted\">{app?.displayName ?? c.appId}</span>\n </span>\n );\n },\n },\n {\n key: \"status\",\n header: \"Status\",\n render: (c) => (\n <>\n auth <code>{c.authKey}</code> ·{\" \"}\n <span\n className={`w6w-connection-tag${c.state === \"connected\" ? \"\" : \" w6w-connection-tag-warn\"}`}\n >\n {c.state}\n </span>\n {c.lastTestOk === false && (\n <span\n className=\"w6w-connection-tag w6w-connection-tag-danger\"\n title=\"Last test failed — update or re-test.\"\n >\n invalid\n </span>\n )}\n </>\n ),\n },\n ];\n if (hasActions) {\n columns.push({\n key: \"actions\",\n header: \"\",\n align: \"right\",\n link: false,\n render: (c) =>\n c.builtIn === true ? null : (\n // Clicks here must not reach the row's onOpen.\n // biome-ignore lint/a11y/useKeyWithClickEvents: propagation guard only; the buttons inside are the controls.\n <div className=\"w6w-connection-row-actions\" onClick={(e) => e.stopPropagation()}>\n {onEdit && (\n <EditButton\n label=\"Edit\"\n onClick={() => onEdit(c)}\n data-testid={`connection-edit-${c.id}`}\n />\n )}\n {onDelete && (\n <DeleteButton\n label=\"Delete\"\n onClick={() => onDelete(c)}\n disabled={busy}\n data-testid={`connection-delete-${c.id}`}\n />\n )}\n </div>\n ),\n });\n }\n return (\n <section className=\"w6w-connection-list\">\n {(slots?.header != null || slots?.actions != null) && (\n <div className=\"w6w-connection-list-head\">\n <div className=\"w6w-connection-list-heading\">{slots?.header}</div>\n <div className=\"w6w-connection-list-actions\">{slots?.actions}</div>\n </div>\n )}\n {error && <div className=\"w6w-error\">{error}</div>}\n {loading && <p className=\"w6w-muted\">Loading…</p>}\n {connections.length === 0 && !loading ? (\n <EmptyState testId=\"w6w-connection-list-empty\">\n {slots?.empty ?? \"No connections yet.\"}\n </EmptyState>\n ) : (\n <DataTable\n columns={columns}\n rows={connections}\n rowKey={(c) => c.id}\n loading={loading}\n getRowHref={getHref ? (c) => (c.builtIn === true ? undefined : getHref(c.id)) : undefined}\n onRowClick={\n onOpen\n ? (c, event) => (c.builtIn === true ? undefined : onOpen(c.id, event))\n : undefined\n }\n />\n )}\n </section>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { AuthFieldsForm, parseJsonFields } from \"./components/AuthFieldsForm.tsx\";\nimport { bindingFieldsFor, buildBinding } from \"./components/CredentialPicker.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport type {\n AuthDef,\n AuthField,\n ConnectionBinding,\n ConnectionSummary,\n CredentialTestResult,\n ThemeMode,\n} from \"./types.ts\";\nimport { useEnterSubmit } from \"./use-enter-submit.ts\";\n\nexport interface EditConnectionModalProps {\n /** The row being edited. `builtIn` rows have nothing to edit: the modal shows a notice only. */\n connection: Pick<\n ConnectionSummary,\n \"id\" | \"appId\" | \"authKey\" | \"displayName\" | \"builtIn\" | \"credentialId\" | \"lastTestOk\"\n >;\n onClose: () => void;\n /** Fired after all changes are saved. The typed credential is cleared before this runs. */\n onSaved: (updated: ConnectionSummary) => void;\n /** Reserved for icon variants, like the other modals. */\n theme?: ThemeMode;\n}\n\n/**\n * Edit an existing connection: rename it and/or replace some of its credential fields. Runs on\n * the {@link useW6WApi} adapter alone. The server never returns the stored secret, so credential\n * fields start empty and blank means \"keep what is stored\" — only the fields the user filled are\n * sent, and the server merges them over the stored credential. Switching to a key/token auth\n * method replaces the full credential while preserving the connection ID. OAuth re-authorization\n * is not part of this modal.\n *\n * A connection that uses a stored credential (`connection.credentialId`), when the host supplies\n * `api.rotateCredential`, saves a full credential replacement through that adapter method.\n * Save also applies any name/binding changes. Other connections sharing the credential switch\n * to the replacement too.\n *\n * Needs `api.updateConnection`. Without it (or for a `builtIn` row) there is no Save button, a\n * one-line notice shows instead, and nothing is called. Hosts should not offer Edit in that case.\n */\nexport function EditConnectionModal({ connection, onClose, onSaved }: EditConnectionModalProps) {\n const api = useW6WApi();\n const update = api.updateConnection;\n const builtIn = connection.builtIn === true;\n const editable = !builtIn && typeof update === \"function\";\n\n const [displayName, setDisplayName] = useState(connection.displayName ?? \"\");\n const [authKey, setAuthKey] = useState(connection.authKey);\n const [credential, setCredential] = useState<Record<string, unknown>>({});\n const [auths, setAuths] = useState<AuthDef[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [pending, setPending] = useState(false);\n const [bindingVals, setBindingVals] = useState<Record<string, unknown>>({});\n const [connectionCount, setConnectionCount] = useState<number | null>(null);\n const [credentialContract, setCredentialContract] = useState<string | null>(null);\n const [health, setHealth] = useState<CredentialTestResult | null>(null);\n\n // The app's declared auth methods drive which credential fields to show.\n useEffect(() => {\n if (!editable) return;\n let canceled = false;\n setAuths(null);\n api\n .getAppAuth(connection.appId)\n .then((a) => !canceled && setAuths(a))\n .catch((e) => !canceled && setError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, editable, connection.appId]);\n\n const authDef = auths?.find((a) => a.key === authKey);\n const authChanged = authKey !== connection.authKey;\n const authChoices =\n auths?.filter(\n (a) =>\n a.key === connection.authKey ||\n (a.available !== false &&\n !a.autoSatisfied &&\n [\"apiKey\", \"bearer\", \"basic\", \"custom\"].includes(a.type)),\n ) ?? [];\n const isOAuth = authDef?.type === \"oauth2\";\n const fields: AuthField[] = isOAuth ? [] : (authDef?.fields ?? []);\n const credentialId = connection.credentialId;\n const storedCredential =\n !authChanged &&\n !!credentialId &&\n typeof api.rotateCredential === \"function\" &&\n (credentialContract !== null\n ? !credentialContract.startsWith(\"legacy:\")\n : authDef?.type === \"serviceAccount\") &&\n !isOAuth;\n const bindingFields =\n storedCredential && authDef?.serviceAccount ? bindingFieldsFor(authDef.serviceAccount) : [];\n\n // Impact of replacing a credential: how many connections share the stored credential.\n useEffect(() => {\n if (\n !editable ||\n authChanged ||\n isOAuth ||\n !credentialId ||\n typeof api.getCredential !== \"function\"\n )\n return;\n let canceled = false;\n api\n .getCredential(credentialId)\n .then((c) => {\n if (canceled) return;\n setConnectionCount(c.connectionCount);\n setCredentialContract(c.contract);\n })\n .catch(() => {});\n return () => {\n canceled = true;\n };\n }, [api, editable, authChanged, isOAuth, credentialId]);\n\n /** `null` = nothing to update. Only a changed name and non-blank credential fields are sent. */\n function buildBody(): {\n authKey?: string;\n displayName?: string;\n binding?: ConnectionBinding;\n credential?: Record<string, unknown>;\n } | null {\n if (storedCredential) {\n // Rename/binding only: the credential is never part of this body.\n const body: { displayName?: string; binding?: ConnectionBinding } = {};\n if (displayName !== (connection.displayName ?? \"\")) body.displayName = displayName;\n const binding = buildBinding(bindingFields, bindingVals);\n if (binding) body.binding = binding;\n return body.displayName === undefined && body.binding === undefined ? null : body;\n }\n const filled: Record<string, unknown> = {};\n for (const f of fields) {\n const v = credential[f.key];\n if (v !== undefined && v !== \"\") filled[f.key] = v;\n }\n const body: { authKey?: string; displayName?: string; credential?: Record<string, unknown> } =\n {};\n if (authChanged) {\n body.authKey = authKey;\n body.credential = filled;\n }\n if (displayName !== (connection.displayName ?? \"\")) body.displayName = displayName;\n if (Object.keys(filled).length > 0) body.credential = filled;\n return body.displayName === undefined && body.credential === undefined ? null : body;\n }\n\n async function save() {\n if (!editable || !update || pending) return;\n setError(null);\n const body = buildBody();\n const filled = Object.fromEntries(\n fields\n .filter((f) => credential[f.key] !== undefined && credential[f.key] !== \"\")\n .map((f) => [f.key, credential[f.key]]),\n );\n const hasCredential = Object.keys(filled).length > 0;\n if (!body && !hasCredential) {\n setError(\"Nothing to update — change the name or a credential or binding field.\");\n return;\n }\n if (authChanged || (storedCredential && hasCredential)) {\n const missing = fields.filter((f) => f.required && !(f.key in filled));\n if (missing.length > 0) {\n setError(`Enter the full new credential: ${missing.map((f) => f.label).join(\", \")}.`);\n return;\n }\n }\n const parsed = parseJsonFields(fields, filled);\n if (\"error\" in parsed) {\n setError(parsed.error);\n return;\n }\n setPending(true);\n let credentialSaved = false;\n try {\n if (storedCredential && hasCredential && credentialId && api.rotateCredential) {\n await api.rotateCredential(credentialId, { source: parsed.values });\n credentialSaved = true;\n setCredential({});\n setHealth(null);\n } else if (body?.credential) {\n body.credential = parsed.values;\n }\n // Replacing a stored credential leaves the connection row unchanged.\n const updated = body ? await update.call(api, connection.id, body) : connection;\n // Drop every typed secret before handing control back to the host.\n setCredential({});\n onSaved(updated);\n } catch (e) {\n // The rejection's message only — never the values the user typed.\n setError(\n credentialSaved\n ? `The credential was saved, but the other changes failed. Click Save to retry them. ${(e as Error).message}`\n : (e as Error).message,\n );\n } finally {\n setPending(false);\n }\n }\n\n async function checkHealth() {\n if (!credentialId || !api.testCredential) return;\n setError(null);\n try {\n setHealth(await api.testCredential(credentialId));\n } catch (e) {\n setError((e as Error).message);\n }\n }\n\n const enterSubmit = useEnterSubmit(save, { enabled: editable && !pending });\n\n return (\n <Modal title=\"Edit connection\" onClose={onClose}>\n <div className=\"w6w-stepconfig\">\n <div className=\"w6w-modal-body\">\n <div className=\"w6w-stack\">\n {builtIn && (\n <p className=\"w6w-muted w6w-small\">\n This connection is built in — it has no stored credential to edit.\n </p>\n )}\n {!builtIn && !editable && (\n <p className=\"w6w-muted w6w-small\">Editing connections is not available here.</p>\n )}\n {editable && (\n <>\n <label className=\"w6w-field\">\n <span>Display name</span>\n <input\n type=\"text\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n placeholder=\"Connection name\"\n maxLength={80}\n name=\"w6w-connection-label\"\n autoComplete=\"off\"\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n data-bwignore=\"true\"\n data-form-type=\"other\"\n {...enterSubmit}\n />\n </label>\n\n {authChoices.some((a) => a.key !== connection.authKey) && (\n <label className=\"w6w-field\">\n <span>Authentication method</span>\n <select\n name=\"w6w-connection-auth\"\n value={authKey}\n disabled={pending}\n onChange={(e) => {\n setAuthKey(e.target.value);\n setCredential({});\n setBindingVals({});\n setHealth(null);\n setError(null);\n }}\n >\n {!authChoices.some((a) => a.key === connection.authKey) && (\n <option value={connection.authKey}>{connection.authKey}</option>\n )}\n {authChoices.map((a) => (\n <option key={a.key} value={a.key}>\n {a.displayName ?? a.key}\n </option>\n ))}\n </select>\n </label>\n )}\n {authChanged && (\n <p className=\"w6w-muted w6w-small\">\n Enter the new credential and click Save. This connection stays linked to your\n existing workflows.\n </p>\n )}\n\n {auths === null && !error && (\n <p className=\"w6w-muted w6w-small\">Loading auth fields…</p>\n )}\n\n {isOAuth && (\n <p className=\"w6w-muted w6w-small\">\n {authChoices.some((a) => a.key !== connection.authKey)\n ? \"This connection uses OAuth. Choose another authentication method above to use a key or token.\"\n : \"This is an OAuth connection. You can rename it here; its credential is renewed by re-authorizing it.\"}\n </p>\n )}\n\n {storedCredential && bindingFields.length > 0 && (\n <>\n <p className=\"w6w-muted w6w-small\">\n Leave a binding field blank to keep it unchanged.\n </p>\n <AuthFieldsForm\n mode=\"edit\"\n fields={bindingFields}\n values={bindingVals}\n onChange={setBindingVals}\n enterSubmitProps={enterSubmit}\n />\n </>\n )}\n\n {storedCredential && (\n <div className=\"w6w-stack\" data-w6w=\"credential-section\">\n {typeof api.testCredential === \"function\" && (\n <div>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={checkHealth}\n >\n Test credential\n </button>\n {health && (\n <p className=\"w6w-small\" data-w6w=\"credential-health\">\n Credential health: {health.ok ? \"ok\" : (health.code ?? \"failed\")}\n </p>\n )}\n </div>\n )}\n <p className=\"w6w-small\" data-w6w=\"app-access\">\n App access:{\" \"}\n {connection.lastTestOk === true\n ? \"passed\"\n : connection.lastTestOk === false\n ? \"failed\"\n : \"never tested\"}\n </p>\n {fields.length > 0 && (\n <>\n <p className=\"w6w-muted w6w-small\">\n Leave the credential blank to keep it unchanged. To replace it, enter the\n full new credential and click Save.\n {connectionCount !== null &&\n connectionCount > 1 &&\n ` This credential is used by ${connectionCount} connections; saving a new credential updates all of them.`}\n </p>\n <AuthFieldsForm\n mode=\"edit\"\n fields={fields}\n values={credential}\n onChange={setCredential}\n enterSubmitProps={enterSubmit}\n />\n </>\n )}\n </div>\n )}\n\n {!storedCredential && fields.length > 0 && (\n <>\n {!authChanged && (\n <p className=\"w6w-muted w6w-small\">\n Leave a field blank to keep it unchanged. Filled fields replace the stored\n credential.\n </p>\n )}\n <AuthFieldsForm\n mode=\"edit\"\n fields={fields}\n values={credential}\n onChange={setCredential}\n enterSubmitProps={enterSubmit}\n />\n </>\n )}\n </>\n )}\n\n {error && <div className=\"w6w-result w6w-error\">{error}</div>}\n </div>\n </div>\n <div className=\"w6w-modal-actions\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n {editable && (\n <button type=\"button\" className=\"w6w-btn\" disabled={pending} onClick={save}>\n {pending ? \"Saving…\" : \"Save\"}\n </button>\n )}\n </div>\n </div>\n </Modal>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { AppIcon } from \"./components/AppIcon.tsx\";\nimport { CopyableText } from \"./components/CopyableText.tsx\";\nimport type { ConnectionSummary } from \"./types.ts\";\n\nexport interface ConnectionHeaderProps {\n conn: ConnectionSummary;\n /** The connection's app display meta (inline `app`, or the by-id record). */\n app:\n | { displayName?: string; iconSvg?: string; iconSvgDark?: string; brandColor?: string }\n | undefined;\n /** Actions slot, right-aligned (e.g. a Test or Edit button, or a back link). */\n children?: ReactNode;\n}\n\n/**\n * Connection identity strip: app icon, display name, copyable id, app id, auth key and state tag\n * (plus `invalid` after a failed test). Presentational; the actions live in `children`.\n */\nexport function ConnectionHeader({ conn, app, children }: ConnectionHeaderProps) {\n return (\n <div className=\"w6w-connection-header\" data-testid=\"connection-header\">\n <AppIcon\n src={app?.iconSvg}\n srcDark={app?.iconSvgDark}\n brandColor={app?.brandColor}\n name={app?.displayName ?? conn.appId}\n size={56}\n />\n <div className=\"w6w-connection-header-main\">\n <h2 className=\"w6w-connection-header-title\">{conn.displayName || conn.id}</h2>\n <p className=\"w6w-muted w6w-small w6w-connection-header-meta\">\n <CopyableText value={conn.id} className=\"w6w-connection-id-copy\" /> · App{\" \"}\n <code>{conn.appId}</code> · Auth <code>{conn.authKey}</code> ·{\" \"}\n <span\n className={`w6w-connection-tag${conn.state === \"connected\" ? \"\" : \" w6w-connection-tag-warn\"}`}\n >\n {conn.state}\n </span>\n {conn.lastTestOk === false && (\n <span\n className=\"w6w-connection-tag w6w-connection-tag-danger\"\n title=\"Last test failed — update or re-test.\"\n >\n invalid\n </span>\n )}\n </p>\n </div>\n {children && <div className=\"w6w-connection-header-actions\">{children}</div>}\n </div>\n );\n}\n","// BudgetMeter — a one-line usage-vs-limit meter for model budgets.\n//\n// Purely presentational: the host owns the numbers and decides what \"the\n// budget\" is (tokens, requests, currency). `format` is the host's hook for\n// rendering those numbers in its own unit; without it the raw values are\n// printed.\n//\n// `role=\"meter\"` (not `progressbar`) is the ARIA role for a measurement within\n// a known range, and the accessible name is the `label` prop. The bar is drawn\n// from two segments — `used` and, when non-zero, `reserved` — because a\n// reserved-but-not-yet-spent amount is a distinct quantity from spend and must\n// stay legible next to it. At or past the limit the root carries\n// `w6w-budget-meter-over`, which is the only hook styles use to switch the bar\n// to the danger colour.\n\nconst defaultFormat = (n: number): string => String(n);\n\n/** Clamp a 0..100 percentage and keep it to a stable number of decimals so the\n * inline `width` style does not wobble between renders. */\nfunction pct(value: number): number {\n const clamped = Math.min(100, Math.max(0, value));\n return Number(clamped.toFixed(4));\n}\n\nexport interface BudgetMeterProps {\n /** Accessible name and the visible caption. */\n label: string;\n /** Amount already consumed. */\n used: number;\n /** Upper bound `used` is measured against. */\n limit: number;\n /** Amount held back but not yet spent. The segment renders only when > 0. */\n reserved?: number;\n /** Formats every number the meter prints (visible text and aria-valuetext). */\n format?: (n: number) => string;\n className?: string;\n testId?: string;\n}\n\nexport function BudgetMeter({\n label,\n used,\n limit,\n reserved = 0,\n format,\n className,\n testId,\n}: BudgetMeterProps) {\n const fmt = format ?? defaultFormat;\n const hasReserved = Number.isFinite(reserved) && reserved > 0;\n const usedPct = limit > 0 ? pct((used / limit) * 100) : 100;\n // A reservation can never push the bar past a full track, so it only fills\n // what `used` leaves over.\n const reservedPct =\n hasReserved && limit > 0 ? pct(Math.min(100 - usedPct, (reserved / limit) * 100)) : 0;\n const over = used >= limit;\n const valueText = `${fmt(used)} / ${fmt(limit)}`;\n\n const classes = [\"w6w-budget-meter\"];\n if (over) classes.push(\"w6w-budget-meter-over\");\n if (className) classes.push(className);\n\n return (\n <div\n role=\"meter\"\n className={classes.join(\" \")}\n aria-label={label}\n aria-valuemin={0}\n aria-valuenow={used}\n aria-valuemax={limit}\n aria-valuetext={valueText}\n data-testid={testId}\n >\n <div className=\"w6w-budget-meter-head\">\n <span className=\"w6w-budget-meter-label\">{label}</span>\n <span className=\"w6w-budget-meter-value\">{valueText}</span>\n </div>\n <div className=\"w6w-budget-meter-track\">\n <div className=\"w6w-budget-meter-used\" style={{ width: `${usedPct}%` }} />\n {hasReserved && (\n <div className=\"w6w-budget-meter-reserved\" style={{ width: `${reservedPct}%` }} />\n )}\n </div>\n </div>\n );\n}\n","/**\n * The pure, data-free vocabulary of a Data store (F-2, lifted from Studio's\n * `lib/data-stores-view`, `data-cells`, `data-grid` and `data-store-errors`).\n *\n * One import point for every consumer (Studio, `@w6w/embed`, the components in\n * this package): the wire types, the closed kind/scalar vocabularies, the\n * cell text codec, the row-draft/write helpers and the error locator. Paths,\n * query builders and cache keys deliberately stay in Studio.\n *\n * Pure and dependency-free on purpose: no React, no SDK, no `fetch`, only\n * relative imports, so `node --test` loads it with nothing but type-stripping.\n */\n\n/** Display label per store kind (shared by every list and picker). */\nexport const DATA_STORE_KIND_LABEL = {\n kv: \"Key-value\",\n doc: \"Document\",\n table: \"Table\",\n} as const;\n\n// ── Wire vocabulary ──────────────────────────────────────────────────────────\n\n/**\n * The three store shapes. `kv` holds one value per key, `doc` holds a JSON\n * document per key, `table` holds rows whose columns are declared in the\n * store's schema.\n */\nexport type DataStoreKind = \"kv\" | \"doc\" | \"table\";\n\n/**\n * The server's scalar vocabulary (S-1). A value of this type is validated\n * server-side and stored as the string the caller sent — never coerced.\n */\nexport type ScalarType = \"string\" | \"number\" | \"integer\" | \"boolean\" | \"date\" | \"datetime\";\n\n/** One declared table column (S-2). `default` is the column's JSON default, verbatim. */\nexport interface TableColumn {\n name: string;\n type: ScalarType;\n required: boolean;\n default?: unknown;\n}\n\n/** A `kv` store's schema (S-2): one scalar type for every value. */\nexport interface KvSchema {\n valueType: ScalarType;\n}\n\n/** A `table` store's schema (S-2); `key` names the column whose cell is the row's key. */\nexport interface TableSchema {\n columns: TableColumn[];\n key?: string;\n}\n\n/** A store as the wire carries it (S-3). Timestamps are ISO-8601 strings. */\nexport interface DataStore {\n id: string;\n kind: DataStoreKind;\n name: string;\n description: string;\n project: string;\n schema: Record<string, unknown>;\n entryCount: number;\n sizeBytes: number;\n createdBy: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/** One entry as the wire carries it (S-3). `expiresAt` is `null` when the entry never expires. */\nexport interface Entry {\n key: string;\n value: unknown;\n version: number;\n sizeBytes: number;\n expiresAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** `GET /data-stores` — one page of stores plus the cursor for the next one. */\nexport interface DataStorePage {\n items: DataStore[];\n nextCursor?: string;\n}\n\n/** `GET /data-stores/:id/entries` — one page of entries (a table query never carries a cursor). */\nexport interface EntryPage {\n items: Entry[];\n nextCursor?: string;\n}\n\n/** `POST /data-stores/:id/import` — how many CSV rows the host upserted/appended. */\nexport interface ImportResult {\n imported: number;\n}\n\n/** `POST /data-stores` body. `schema` is the S-2 shape for the chosen `kind`. */\nexport interface DataStoreCreateInput {\n kind: DataStoreKind;\n name: string;\n description?: string;\n schema?: Record<string, unknown>;\n}\n\n/** `PATCH /data-stores/:id` body — every field optional, none of them the kind. */\nexport interface DataStorePatch {\n name?: string;\n description?: string;\n schema?: Record<string, unknown>;\n}\n\n/** The closed set of store kinds, in the order the create dialog offers them. */\nexport const DATA_STORE_KINDS = [\"kv\", \"doc\", \"table\"] as const;\n\n/** The closed set of scalar cell types, in the order the columns editor offers them. */\nexport const SCALAR_TYPES = [\"string\", \"number\", \"integer\", \"boolean\", \"date\", \"datetime\"] as const;\n\n/** R-7: a CSV upload is at most 5 MB (5 242 880 bytes). The client checks before sending. */\nexport const CSV_MAX_BYTES = 5_242_880;\n\n/**\n * A `kv` store's declared value type, defaulting to `\"string\"` — S-2's own\n * default, and the only safe reading of a schema the client did not write\n * (a store created before the field existed, or one whose schema is garbage).\n */\nexport function kvValueTypeOf(store: DataStore): ScalarType {\n const declared = store.schema?.valueType;\n return typeof declared === \"string\" && (SCALAR_TYPES as readonly string[]).includes(declared)\n ? (declared as ScalarType)\n : \"string\";\n}\n\n/**\n * A `table` store's schema, or `null` when the store is not a table or its\n * schema has no column array. `null` — not an empty column list — so the grid\n * can tell \"not a table\" from \"a table with nothing declared\".\n */\nexport function tableSchemaOf(store: DataStore): TableSchema | null {\n if (store.kind !== \"table\") return null;\n const columns = store.schema?.columns;\n if (!Array.isArray(columns)) return null;\n const key = store.schema?.key;\n return typeof key === \"string\"\n ? { columns: columns as TableColumn[], key }\n : { columns: columns as TableColumn[] };\n}\n\n/**\n * The filename to save an export under: the host's own `filename=\"…\"` from the\n * `Content-Disposition` header when it sent one, otherwise `<store name>.csv`.\n * A header without that parameter (`attachment` alone, or `null` when a\n * proxy stripped it) falls back rather than producing a nameless file.\n */\nexport function csvFilenameOf(contentDisposition: string | null, storeName: string): string {\n const quoted = contentDisposition?.match(/filename=\"([^\"]*)\"/);\n const name = quoted?.[1];\n return name !== undefined && name !== \"\" ? name : `${storeName}.csv`;\n}\n\n// ── Cell codec ──────────────────────────────────────────────────────────────\n\n/** Why a cell's text could not become a value. */\nexport type CellProblem =\n | \"required\"\n | \"not_a_number\"\n | \"not_an_integer\"\n | \"not_a_boolean\"\n | \"not_a_date\"\n | \"not_a_datetime\";\n\n/** The one sentence rendered beside the offending cell, per problem. */\nexport const CELL_PROBLEM_COPY: Record<CellProblem, string> = {\n required: \"Required.\",\n not_a_number: \"Enter a number.\",\n not_an_integer: \"Enter a whole number.\",\n not_a_boolean: \"Enter true or false.\",\n not_a_date: \"Enter a date as YYYY-MM-DD.\",\n not_a_datetime: \"Enter a date-time like 2026-01-31T09:30:00Z.\",\n};\n\n/** The JSON number grammar, without the forms JSON itself would not round-trip (`01`, `+1`, `.5`, `1.`). */\nconst NUMBER_TEXT = /^-?(0|[1-9]\\d*)(\\.\\d+)?([eE][+-]?\\d+)?$/;\n\n/** A whole number: no fraction, no exponent. */\nconst INTEGER_TEXT = /^-?(0|[1-9]\\d*)$/;\n\n/** `YYYY-MM-DD` — the calendar check is {@linkcode isRealDate}. */\nconst DATE_TEXT = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** RFC 3339 with an offset; the field ranges and the calendar are checked separately. */\nconst DATETIME_TEXT = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/;\n\n/** Days in `month` (1–12) of `year`, Gregorian leap rule. */\nfunction daysInMonth(year: number, month: number): number {\n if (month === 2) {\n const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n return leap ? 29 : 28;\n }\n return [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];\n}\n\n/** `YYYY-MM-DD` split into numbers, or `null` when it is not a real calendar day. */\nfunction readDate(text: string): { year: number; month: number; day: number } | null {\n if (!DATE_TEXT.test(text)) return null;\n const year = Number(text.slice(0, 4));\n const month = Number(text.slice(5, 7));\n const day = Number(text.slice(8, 10));\n if (month < 1 || month > 12) return null;\n if (day < 1 || day > daysInMonth(year, month)) return null;\n return { year, month, day };\n}\n\n/** The failure half of {@linkcode parseCell}'s answer, carrying the copy the cell renders. */\nfunction refuse(problem: CellProblem) {\n return { ok: false as const, problem, message: CELL_PROBLEM_COPY[problem] };\n}\n\n/**\n * Turn the text an operator typed into the value the wire takes, for a column\n * of `type`.\n *\n * `required` is applied to the EMPTY cell only (R-7): every other rule is the\n * server's own, so a cell this returns `ok` for is a cell the server accepts.\n * `string` is the one type that keeps the text as typed — trimming it would\n * silently edit the operator's value.\n */\nexport function parseCell(\n type: ScalarType,\n text: string,\n required: boolean,\n):\n | { ok: true; value: string | number | boolean | undefined }\n | { ok: false; problem: CellProblem; message: string } {\n const trimmed = text.trim();\n if (trimmed === \"\") {\n return required ? refuse(\"required\") : { ok: true, value: undefined };\n }\n switch (type) {\n case \"string\":\n return { ok: true, value: text };\n case \"number\": {\n if (!NUMBER_TEXT.test(trimmed)) return refuse(\"not_a_number\");\n const value = Number(trimmed);\n return Number.isFinite(value) ? { ok: true, value } : refuse(\"not_a_number\");\n }\n case \"integer\": {\n if (!INTEGER_TEXT.test(trimmed)) return refuse(\"not_an_integer\");\n const value = Number(trimmed);\n return Number.isSafeInteger(value) ? { ok: true, value } : refuse(\"not_an_integer\");\n }\n case \"boolean\": {\n if (trimmed === \"true\") return { ok: true, value: true };\n if (trimmed === \"false\") return { ok: true, value: false };\n return refuse(\"not_a_boolean\");\n }\n case \"date\":\n return readDate(trimmed) === null ? refuse(\"not_a_date\") : { ok: true, value: trimmed };\n case \"datetime\":\n return isDateTime(trimmed) ? { ok: true, value: trimmed } : refuse(\"not_a_datetime\");\n }\n}\n\n/** RFC 3339 text with a real calendar date, real clock fields and a well-formed offset. */\nfunction isDateTime(text: string): boolean {\n if (!DATETIME_TEXT.test(text)) return false;\n if (readDate(text.slice(0, 10)) === null) return false;\n const hour = Number(text.slice(11, 13));\n const minute = Number(text.slice(14, 16));\n const second = Number(text.slice(17, 19));\n if (hour > 23 || minute > 59 || second > 59) return false;\n const rest = text.slice(19);\n const zone = rest.match(/(Z|([+-])(\\d{2}):(\\d{2}))$/);\n if (zone === null || zone[1] === \"Z\") return true;\n return Number(zone[3]) <= 23 && Number(zone[4]) <= 59;\n}\n\n/**\n * The text to put in a cell for an already-typed value.\n *\n * `undefined`/`null` render as the empty cell (never `\"undefined\"` or `\"null\"`);\n * a string value for a string-ish column is shown as itself; a finite number\n * and a boolean render as their JSON literals; anything else (an object cell,\n * a `null` inside a document) falls back to its JSON text so the cell shows\n * what the server holds rather than `[object Object]`.\n */\nexport function serializeCell(type: ScalarType, value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (type === \"string\" || type === \"date\" || type === \"datetime\") {\n if (typeof value === \"string\") return value;\n }\n if (\n (type === \"number\" || type === \"integer\") &&\n typeof value === \"number\" &&\n Number.isFinite(value)\n ) {\n return String(value);\n }\n if (type === \"boolean\" && typeof value === \"boolean\") return value ? \"true\" : \"false\";\n const json = JSON.stringify(value);\n return json === undefined ? \"\" : json;\n}\n\n/**\n * Is an already-typed JSON value of `type`? The same rules {@linkcode parseCell}\n * applies to text, applied to a value that came back from the server — the grid\n * uses it to mark a row the server would refuse before the operator presses\n * Save. `required` plays no part here: an absent value is the caller's problem\n * to decide about, not this predicate's.\n */\nexport function isCellValue(type: ScalarType, value: unknown): boolean {\n switch (type) {\n case \"string\":\n return typeof value === \"string\";\n case \"number\":\n return typeof value === \"number\" && Number.isFinite(value);\n case \"integer\":\n return Number.isSafeInteger(value);\n case \"boolean\":\n return typeof value === \"boolean\";\n case \"date\":\n return typeof value === \"string\" && readDate(value) !== null;\n case \"datetime\":\n return typeof value === \"string\" && isDateTime(value);\n }\n}\n\n// ── Error locator ───────────────────────────────────────────────────────────\n\n/** What is shown when the server said nothing a human can read. */\nexport const DATA_STORE_ERROR_FALLBACK = \"The request failed.\";\n\n/** `rawRequest`'s `status: 0` — the request never reached the server. */\nexport const DATA_STORE_NETWORK_ERROR = \"Could not reach the server.\";\n\n/** A failure, flattened into the fields the page needs and nothing else. */\nexport interface DataStoreErrorLocator {\n /** Always present: the server's own sentence, or one of the two copy constants above. */\n message: string;\n /** The host's machine-readable code (`invalid_value`, `invalid_cursor`, …). */\n code?: string;\n /** The HTTP status; `0` is the transport-failure convention. */\n status?: number;\n /** The request-body field the host blamed. */\n field?: string;\n /** The 0-based CSV data row the host blamed (header excluded). */\n row?: number;\n /** The table column the host blamed. */\n column?: string;\n}\n\n/** A non-empty string, or `undefined`. */\nfunction textOf(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** A 0-based row index, or `undefined` — a negative or fractional row is not a row. */\nfunction rowOf(value: unknown): number | undefined {\n return Number.isInteger(value) && (value as number) >= 0 ? (value as number) : undefined;\n}\n\n/**\n * Read `{ error: { code, message, field, row, column } }` out of whatever the\n * caller has, adding `status` from `status` when that is a number.\n *\n * `body` is a value of unknown shape (a parsed JSON body, or the `.raw` of an\n * `ApiError`); the envelope is nested under `error`, and an unshaped body\n * contributes nothing rather than a guess.\n */\nfunction locatorFromEnvelope(\n body: unknown,\n fallbackMessages: unknown[],\n status: unknown,\n): DataStoreErrorLocator {\n const locator: DataStoreErrorLocator = { message: DATA_STORE_ERROR_FALLBACK };\n if (typeof status === \"number\") locator.status = status;\n const envelope =\n body !== null && typeof body === \"object\" ? (body as { error?: unknown }).error : undefined;\n if (envelope !== null && typeof envelope === \"object\") {\n const error = envelope as {\n code?: unknown;\n message?: unknown;\n field?: unknown;\n row?: unknown;\n column?: unknown;\n };\n const code = textOf(error.code);\n if (code !== undefined) locator.code = code;\n const field = textOf(error.field);\n if (field !== undefined) locator.field = field;\n const column = textOf(error.column);\n if (column !== undefined) locator.column = column;\n const row = rowOf(error.row);\n if (row !== undefined) locator.row = row;\n const message = textOf(error.message);\n if (message !== undefined) locator.message = message;\n }\n if (locator.message === DATA_STORE_ERROR_FALLBACK) {\n for (const candidate of fallbackMessages) {\n const message = textOf(candidate);\n if (message !== undefined) {\n locator.message = message;\n break;\n }\n }\n }\n return locator;\n}\n\n/**\n * Locate a thrown JSON-call failure: an `ApiError` (whose parsed body lives on\n * `.raw`), a plain `Error`, or anything else at all.\n *\n * The message falls back in that order — the envelope's `message`, the error's\n * own `message`, then {@linkcode DATA_STORE_ERROR_FALLBACK} — so an unfamiliar\n * throw still produces a sentence rather than an empty panel.\n */\nexport function locateDataStoreError(e: unknown): DataStoreErrorLocator {\n try {\n const shaped =\n e !== null && typeof e === \"object\"\n ? (e as { raw?: unknown; status?: unknown; message?: unknown })\n : undefined;\n const raw = shaped?.raw;\n const ownMessage = shaped?.message;\n return locatorFromEnvelope(raw, [ownMessage], shaped?.status);\n } catch {\n return { message: DATA_STORE_ERROR_FALLBACK };\n }\n}\n\n/**\n * Locate a CSV-call failure from P-RAW's `{status, text}` — the body is still\n * unparsed text because that transport does not know the content type.\n *\n * `status: 0` means the request never produced a response, and gets the\n * transport sentence rather than an attempt to parse an empty body. Otherwise\n * the body is parsed iff it is JSON: an HTML error page from a proxy is\n * `{status, message: fallback}`, not a crash.\n */\nexport function locateRawResponseError(res: {\n status: number;\n text: string;\n}): DataStoreErrorLocator {\n try {\n if (res.status === 0) {\n return {\n status: 0,\n code: \"network_error\",\n message: DATA_STORE_NETWORK_ERROR,\n };\n }\n let body: unknown;\n try {\n body = JSON.parse(res.text);\n } catch {\n return { status: res.status, message: DATA_STORE_ERROR_FALLBACK };\n }\n return locatorFromEnvelope(body, [], res.status);\n } catch {\n return { message: DATA_STORE_ERROR_FALLBACK };\n }\n}\n\n/** Where the message is rendered: under one table cell, under one form field, or over the whole form. */\nexport function errorPlacement(\n loc: DataStoreErrorLocator,\n):\n | { kind: \"cell\"; column: string; row?: number }\n | { kind: \"field\"; field: string }\n | { kind: \"form\" } {\n const column = textOf(loc.column);\n if (column !== undefined) {\n const row = rowOf(loc.row);\n return row === undefined ? { kind: \"cell\", column } : { kind: \"cell\", column, row };\n }\n const field = textOf(loc.field);\n if (field !== undefined) return { kind: \"field\", field };\n return { kind: \"form\" };\n}\n\n/**\n * The operator's 1-based line number in the CSV they uploaded, from the host's\n * 0-based data-row index: the header row is line 1, so data row 0 is line 2.\n */\nexport function csvLineOf(row: number): number {\n return row + 2;\n}\n\n// ── Row drafts and writes ───────────────────────────────────────────────────\n\n/**\n * The draft id of a row that does not exist yet: a NUL-prefixed sentinel, which\n * R-5 forbids a real key from ever being (no control characters in a key), so\n * `id === NEW_ROW_ID` and \"this row has no server-side key\" are the same fact.\n */\nexport const NEW_ROW_ID = \"\\u0000new\";\n\n/** Rendered beside a row whose `ifVersion` was stale — never as the server's sentence alone. */\nexport const VERSION_CONFLICT_COPY = \"Changed by someone else since you loaded it.\";\n\n/** A `doc` store holds a JSON object or array; anything else is not a document. */\nexport const DOC_VALUE_COPY = \"Enter a JSON object or array.\";\n\n/** R-7's client-side ceiling copy — the check runs before anything is sent. */\nexport const CSV_TOO_LARGE_COPY = \"The file is larger than 5 MB.\";\n\n/**\n * One row's editable state: the id it is saved under (`entry.key`, or\n * {@linkcode NEW_ROW_ID}), the version the save guards with (`null` for a new\n * row) and the cell TEXT per declared column (never a parsed value — the text\n * is what the operator is editing, and re-serialising it on every keystroke\n * would fight their cursor).\n */\nexport interface RowDraft {\n id: string;\n version: number | null;\n cells: Record<string, string>;\n}\n\n/**\n * An entry's value read as a table row: the object the server stored, or `{}`\n * for anything that is not a plain object (a `null`, an array, a scalar from a\n * column set that has since changed).\n */\nexport function rowValueOf(entry: Entry): Record<string, unknown> {\n const value = entry.value;\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\n/** The draft an entry starts as: its key, its version, and each declared column's text. */\nexport function draftFromEntry(entry: Entry, columns: readonly TableColumn[]): RowDraft {\n const row = rowValueOf(entry);\n const cells: Record<string, string> = {};\n for (const column of columns) cells[column.name] = serializeCell(column.type, row[column.name]);\n return { id: entry.key, version: entry.version, cells };\n}\n\n/**\n * The draft a brand-new row starts as: {@linkcode NEW_ROW_ID}, no version, and\n * each column seeded from its declared `default` (absent default = empty cell).\n */\nexport function newRowDraft(columns: readonly TableColumn[]): RowDraft {\n const cells: Record<string, string> = {};\n for (const column of columns) {\n cells[column.name] =\n column.default === undefined ? \"\" : serializeCell(column.type, column.default);\n }\n return { id: NEW_ROW_ID, version: null, cells };\n}\n\n/**\n * Which declared columns the operator actually changed, in DECLARED order.\n *\n * Declared order (not object order) so the answer is stable across browsers and\n * the row's Save button can decide \"dirty\" with one empty-array check. An\n * untouched draft is `[]`.\n */\nexport function dirtyColumns(\n draft: RowDraft,\n base: RowDraft,\n columns: readonly TableColumn[],\n): string[] {\n const dirty: string[] = [];\n for (const column of columns) {\n if ((draft.cells[column.name] ?? \"\") !== (base.cells[column.name] ?? \"\")) {\n dirty.push(column.name);\n }\n }\n return dirty;\n}\n\n/**\n * The row body a Save sends, or the per-cell refusals that stop it.\n *\n * Every DECLARED column is parsed through {@linkcode parseCell} with its own\n * `required` flag: an absent value omits the key entirely (R-7's empty-cell\n * rule, so the host's default applies), a `string` cell keeps its text verbatim\n * and every other type is the JSON value the server expects — never the typed\n * text. Failures are keyed by column name so the caller renders them under the\n * offending cell.\n */\nexport function buildRowValue(\n draft: RowDraft,\n columns: readonly TableColumn[],\n): { ok: true; value: Record<string, unknown> } | { ok: false; errors: Record<string, string> } {\n const value: Record<string, unknown> = {};\n const errors: Record<string, string> = {};\n for (const column of columns) {\n const parsed = parseCell(column.type, draft.cells[column.name] ?? \"\", column.required);\n if (parsed.ok) {\n if (parsed.value !== undefined) value[column.name] = parsed.value;\n } else {\n errors[column.name] = parsed.message;\n }\n }\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value };\n}\n\n/**\n * The `ttlSeconds` a save must resend so it does not CLEAR an existing expiry\n * (S-1: a PUT without `ttlSeconds` sets `expires_at = NULL`).\n *\n * `undefined` for an entry that never expires, for an unparseable timestamp and\n * for one already in the past — in all three cases sending nothing is correct\n * (and a non-positive TTL is not a TTL the host accepts). Rounded UP, so a save\n * one millisecond before the deadline does not shorten the entry's life.\n */\nexport function remainingTtlSeconds(expiresAt: string | null, nowMs: number): number | undefined {\n if (expiresAt === null) return undefined;\n const ms = Date.parse(expiresAt);\n if (!Number.isFinite(ms)) return undefined;\n const seconds = Math.ceil((ms - nowMs) / 1000);\n return seconds > 0 ? seconds : undefined;\n}\n\n/**\n * Which request a draft implies: an INSERT (`POST entries`, no `ifVersion`) for\n * a row that does not exist yet, otherwise a PUT under the row's key guarded by\n * the version the operator loaded.\n *\n * `ttlSeconds` is present ONLY when the caller has one: it reaches the wire as\n * a defining key, and an explicit `undefined` would be indistinguishable from\n * \"the caller measured nothing\".\n */\nexport function rowWriteOf(\n draft: RowDraft,\n value: Record<string, unknown>,\n ttlSeconds: number | undefined,\n):\n | { kind: \"insert\"; value: Record<string, unknown>; ttlSeconds?: number }\n | {\n kind: \"put\";\n key: string;\n value: Record<string, unknown>;\n ifVersion: number;\n ttlSeconds?: number;\n } {\n if (draft.id === NEW_ROW_ID) {\n return ttlSeconds === undefined\n ? { kind: \"insert\", value }\n : { kind: \"insert\", value, ttlSeconds };\n }\n const write = {\n kind: \"put\" as const,\n key: draft.id,\n value,\n ifVersion: draft.version ?? 0,\n };\n return ttlSeconds === undefined ? write : { ...write, ttlSeconds };\n}\n\n/**\n * The cell errors a refusal places, or `null` when it belongs somewhere else\n * (the form, a request-body field, a column this table does not declare).\n *\n * `null` is load-bearing: the grid renders `grid-error` exactly when this\n * returns `null`, so \"the message shows in one slot\" is a property of the\n * answer rather than of the caller's care.\n */\nexport function cellErrorsOf(\n loc: DataStoreErrorLocator,\n columns: readonly TableColumn[],\n): Record<string, string> | null {\n const placement = errorPlacement(loc);\n if (placement.kind !== \"cell\") return null;\n if (!columns.some((column) => column.name === placement.column)) return null;\n return { [placement.column]: loc.message };\n}\n\n/**\n * Is this failure the optimistic-concurrency refusal — and nothing else?\n *\n * `409` alone is not enough: `entry_exists` and `store_exists` share the status\n * and neither is fixed by reloading, so both halves of the locator must agree.\n */\nexport function isVersionConflict(loc: DataStoreErrorLocator): boolean {\n return loc.status === 409 && loc.code === \"version_conflict\";\n}\n\n/**\n * A `doc` store's value from the editor's text: any JSON object or array.\n *\n * A scalar is refused rather than wrapped — the store's own `doc` shape is an\n * object/array (S-2), and the host would refuse `42` anyway; failing here means\n * the operator sees why without a round trip. `null` parses but is not a\n * document, so it is refused with the same sentence.\n */\nexport function parseDocText(\n text: string,\n): { ok: true; value: object } | { ok: false; message: string } {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return { ok: false, message: DOC_VALUE_COPY };\n }\n if (parsed === null || typeof parsed !== \"object\") {\n return { ok: false, message: DOC_VALUE_COPY };\n }\n return { ok: true, value: parsed };\n}\n\n/**\n * A `kv` store's value from the editor's text.\n *\n * `string` is the one type whose text IS the value, empty string included (an\n * empty `string` entry is a real value, not an absent one), so it never passes\n * through {@linkcode parseCell} — which reads an empty cell as absent. Every\n * other type is parsed exactly as a table cell would be, `required` on, because\n * a kv entry always has a value.\n */\nexport function kvValueOf(\n type: ScalarType,\n text: string,\n): { ok: true; value: unknown } | { ok: false; message: string } {\n if (type === \"string\") return { ok: true, value: text };\n const parsed = parseCell(type, text, true);\n return parsed.ok ? { ok: true, value: parsed.value } : { ok: false, message: parsed.message };\n}\n\n/**\n * What a CSV import's `RawResponse` says to the operator.\n *\n * The host is the only parser (R-7): a `200` reports how many rows it took, and\n * a refusal is located rather than interpreted — a `row` becomes the operator's\n * own 1-based line (`csvLineOf`), the `column` is named when the host named one,\n * and everything else is the host's sentence verbatim.\n */\nexport function csvImportMessage(res: { status: number; text: string }): {\n ok: boolean;\n message: string;\n} {\n if (res.status === 200) {\n let imported = 0;\n try {\n const body = JSON.parse(res.text) as { imported?: unknown };\n if (typeof body.imported === \"number\" && Number.isFinite(body.imported)) {\n imported = body.imported;\n }\n } catch {\n imported = 0;\n }\n return {\n ok: true,\n message: `Imported ${imported} row${imported === 1 ? \"\" : \"s\"}.`,\n };\n }\n const loc = locateRawResponseError(res);\n if (loc.row === undefined) return { ok: false, message: loc.message };\n const where = loc.column\n ? `Line ${csvLineOf(loc.row)}, column ${loc.column}`\n : `Line ${csvLineOf(loc.row)}`;\n return { ok: false, message: `${where}: ${loc.message}` };\n}\n","import type { MouseEvent, ReactNode } from \"react\";\nimport { DATA_STORE_KIND_LABEL, type DataStore } from \"../data-stores/data-store-view.ts\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\nimport { EditButton } from \"./EditButton.tsx\";\nimport { EmptyState } from \"./EmptyState.tsx\";\nimport { formatBytes } from \"./server-resources-format.ts\";\n\nexport interface DataStoreListProps {\n stores: readonly DataStore[];\n loading?: boolean;\n error?: string | null;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onOpen?: (id: string, event: MouseEvent<Element>) => void;\n /** When set, each row is a real `<a href>`. */\n getHref?: (id: string) => string;\n /** Renders an Edit button per row. */\n onEdit?: (store: DataStore) => void;\n /** Renders an Archive button per row. Confirmation and the archive call are the host's. */\n onArchive?: (store: DataStore) => void;\n /** Disables every Archive button while an archive is in flight. */\n busy?: boolean;\n /** Size formatter; defaults to the package's `formatBytes` (`2.0 KiB`). */\n formatSize?: (bytes: number) => string;\n slots?: {\n /** Heading block above the rows. */\n header?: ReactNode;\n /** Trailing action(s) next to the header (e.g. a \"New store\" button). */\n actions?: ReactNode;\n /** Shown when there are no stores and the list is not `loading`. */\n empty?: ReactNode;\n };\n}\n\n/**\n * A presentational list of Data stores: rows in, callbacks out; it needs no provider. Rows render\n * through {@link DataTable} (name, kind, entry count, size, last update, and an Edit/Archive column\n * that is never a link).\n */\nexport function DataStoreList({\n stores,\n loading,\n error,\n onOpen,\n getHref,\n onEdit,\n onArchive,\n busy,\n formatSize,\n slots,\n}: DataStoreListProps) {\n const size = formatSize ?? formatBytes;\n const hasActions = onEdit !== undefined || onArchive !== undefined;\n const columns: DataTableColumn<DataStore>[] = [\n { key: \"name\", header: \"Name\", render: (s) => <strong>{s.name}</strong> },\n { key: \"kind\", header: \"Kind\", render: (s) => DATA_STORE_KIND_LABEL[s.kind] },\n { key: \"entries\", header: \"Entries\", align: \"right\", render: (s) => String(s.entryCount) },\n { key: \"size\", header: \"Size\", align: \"right\", render: (s) => size(s.sizeBytes) },\n {\n key: \"updated\",\n header: \"Updated\",\n render: (s) => new Date(s.updatedAt).toLocaleString(),\n },\n ];\n if (hasActions) {\n columns.push({\n key: \"actions\",\n header: \"\",\n align: \"right\",\n link: false,\n render: (s) => (\n // Clicks here must not reach the row's onOpen.\n // biome-ignore lint/a11y/useKeyWithClickEvents: propagation guard only; the buttons inside are the controls.\n <div className=\"w6w-data-row-actions\" onClick={(e) => e.stopPropagation()}>\n {onEdit && (\n <EditButton\n label=\"Edit\"\n onClick={() => onEdit(s)}\n data-testid={`data-store-edit-${s.id}`}\n />\n )}\n {onArchive && (\n <DeleteButton\n label=\"Archive\"\n onClick={() => onArchive(s)}\n disabled={busy}\n data-testid={`data-store-archive-${s.id}`}\n />\n )}\n </div>\n ),\n });\n }\n return (\n <section className=\"w6w-data-store-list\">\n {(slots?.header != null || slots?.actions != null) && (\n <div className=\"w6w-data-store-list-head\">\n <div className=\"w6w-data-store-list-heading\">{slots?.header}</div>\n <div className=\"w6w-data-store-list-actions\">{slots?.actions}</div>\n </div>\n )}\n {error && <div className=\"w6w-error\">{error}</div>}\n {loading && <p className=\"w6w-muted\">Loading…</p>}\n {stores.length === 0 && !loading ? (\n <EmptyState testId=\"w6w-data-store-list-empty\">\n {slots?.empty ?? \"No data stores yet.\"}\n </EmptyState>\n ) : (\n <DataTable\n columns={columns}\n rows={stores}\n rowKey={(s) => s.id}\n loading={loading}\n getRowHref={getHref ? (s) => getHref(s.id) : undefined}\n onRowClick={onOpen ? (s, event) => onOpen(s.id, event) : undefined}\n />\n )}\n </section>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport {\n SCALAR_TYPES,\n type ScalarType,\n type TableColumn,\n parseCell,\n serializeCell,\n} from \"../data-stores/data-store-view.ts\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\n\n/**\n * The `table` kind's column list: a controlled row editor (rows + `onChange(next)`; the column\n * list itself is never copied).\n *\n * The **key column** select is the one piece of the schema a row cannot decide for itself: only a\n * column that is `required` and typed `string` or `integer` may be a row's key, so the select\n * offers only those rows. A column renamed, retyped or un-required out of that set resets the\n * selection to `\"\"` (\"generated keys\") rather than holding a key the server would reject.\n *\n * `columnErrors` is keyed by column NAME (what the host's error envelope names in\n * `error.column`), so a 400 lands under the row that caused it.\n *\n * Each row also takes a **default**, typed as text and parsed with the column's type: empty or\n * refused text leaves the column with no `default` key at all, a valid one stores the typed value\n * (`7`, `true`), never the text.\n */\nexport interface ColumnsEditorProps {\n columns: TableColumn[];\n onChange: (next: TableColumn[]) => void;\n /** The selected key column's name, or `\"\"` for \"generated keys\". */\n keyColumn: string;\n onKeyColumnChange: (k: string) => void;\n /** One message per column name, from the server's `error.column`. */\n columnErrors: Record<string, string>;\n}\n\n/** The key column's eligibility rule. */\nfunction eligibleAsKey(c: TableColumn): boolean {\n return c.name !== \"\" && c.required === true && (c.type === \"string\" || c.type === \"integer\");\n}\n\n/** `column` with its default replaced by the parse of `text`; no `default` key unless it parsed. */\nfunction withDefault(column: TableColumn, text: string): { column: TableColumn; error?: string } {\n const { default: _old, ...rest } = column;\n const parsed = parseCell(column.type, text, false);\n if (!parsed.ok) return { column: rest, error: parsed.message };\n if (parsed.value === undefined) return { column: rest };\n return { column: { ...rest, default: parsed.value } };\n}\n\ninterface DefaultDraft {\n text: string;\n error?: string;\n}\n\nexport function ColumnsEditor(props: ColumnsEditorProps) {\n const { columns, onChange, keyColumn, onKeyColumnChange, columnErrors } = props;\n // The text typed into each row's default box, by row position. A row with no draft shows the\n // serialization of the column's own default.\n const [drafts, setDrafts] = useState<Record<number, DefaultDraft>>({});\n\n const eligible = columns.filter(eligibleAsKey);\n const eligibleKey = eligible.some((c) => c.name === keyColumn) ? keyColumn : \"\";\n\n // The selection cannot survive its column leaving the eligible set.\n useEffect(() => {\n if (keyColumn !== \"\" && eligibleKey === \"\") onKeyColumnChange(\"\");\n }, [keyColumn, eligibleKey, onKeyColumnChange]);\n\n function addColumn() {\n onChange([...columns, { name: \"\", type: \"string\", required: false }]);\n }\n function updateColumn(i: number, next: Partial<TableColumn>) {\n onChange(columns.map((c, idx) => (idx === i ? { ...c, ...next } : c)));\n }\n function setDefault(i: number, type: ScalarType, text: string, extra?: Partial<TableColumn>) {\n const base = { ...columns[i], ...extra, type } as TableColumn;\n const { column, error } = withDefault(base, text);\n setDrafts((d) => ({ ...d, [i]: error === undefined ? { text } : { text, error } }));\n onChange(columns.map((c, idx) => (idx === i ? column : c)));\n }\n function removeColumn(i: number) {\n setDrafts((d) => {\n const next: Record<number, DefaultDraft> = {};\n for (const [k, v] of Object.entries(d)) {\n const n = Number(k);\n if (n < i) next[n] = v;\n else if (n > i) next[n - 1] = v;\n }\n return next;\n });\n onChange(columns.filter((_, idx) => idx !== i));\n }\n\n return (\n <div className=\"w6w-data-columns\">\n <div className=\"w6w-data-columns-head\">\n <h3>Columns</h3>\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={addColumn}>\n + Add column\n </button>\n </div>\n <p className=\"w6w-muted w6w-small\">\n Each column has a name, a scalar type, whether it must be set, and an optional default.\n </p>\n {columns.length === 0 && <p className=\"w6w-muted w6w-small\">No columns yet.</p>}\n <ul className=\"w6w-data-columns-list\" data-testid=\"data-columns\">\n {columns.map((c, i) => {\n const draft = drafts[i];\n const text = draft?.text ?? serializeCell(c.type, c.default);\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and reorderable\n <li key={i} className=\"w6w-data-columns-row\">\n <input\n type=\"text\"\n value={c.name}\n placeholder=\"name\"\n aria-label=\"Column name\"\n onChange={(e) => updateColumn(i, { name: e.target.value })}\n />\n <select\n value={c.type}\n aria-label=\"Column type\"\n onChange={(e) => setDefault(i, e.target.value as ScalarType, text)}\n >\n {SCALAR_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <label className=\"w6w-data-columns-required\">\n <input\n type=\"checkbox\"\n checked={c.required}\n aria-label=\"Required\"\n onChange={(e) => updateColumn(i, { required: e.target.checked })}\n />\n <span className=\"w6w-muted w6w-small\">required</span>\n </label>\n <input\n type=\"text\"\n value={text}\n placeholder=\"default\"\n aria-label=\"Column default\"\n onChange={(e) => setDefault(i, c.type, e.target.value)}\n />\n <DeleteButton\n label={`Remove column ${c.name || i + 1}`}\n onClick={() => removeColumn(i)}\n />\n {draft?.error !== undefined && (\n <div\n className=\"w6w-result w6w-error w6w-data-columns-error\"\n data-testid={`data-store-column-default-error-${i}`}\n >\n {draft.error}\n </div>\n )}\n {c.name !== \"\" && columnErrors[c.name] !== undefined && (\n <div\n className=\"w6w-result w6w-error w6w-data-columns-error\"\n data-testid={`data-store-column-error-${c.name}`}\n >\n {columnErrors[c.name]}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n <label className=\"w6w-field\">\n <span>Key column</span>\n <select value={eligibleKey} onChange={(e) => onKeyColumnChange(e.target.value)}>\n <option value=\"\">(none — rows get generated keys)</option>\n {eligible.map((c) => (\n <option key={c.name} value={c.name}>\n {c.name}\n </option>\n ))}\n </select>\n <span className=\"w6w-hint\">\n Only a required, string or integer column can name a row's key.\n </span>\n </label>\n </div>\n );\n}\n","import type { ChangeEvent } from \"react\";\nimport { CSV_MAX_BYTES, CSV_TOO_LARGE_COPY } from \"../data-stores/data-store-view.ts\";\n\nexport interface CsvPanelProps {\n /** What the panel is telling the operator, and whether it failed. `null` renders nothing. */\n result: { ok: boolean; message: string } | null;\n /** Disables Export while a request is in flight. */\n busy?: boolean;\n /** A file within {@link CSV_MAX_BYTES}. Reading and sending it are the host's. */\n onImport: (file: File) => void;\n /** A file the panel refused before handing it over (too large). */\n onRefuse: (message: string) => void;\n onExport: () => void;\n}\n\n/**\n * CSV import and export for one table store: one file input, one Export button, one result line.\n * Props-only. The panel owns the size check (a file over {@link CSV_MAX_BYTES} is refused here and\n * never reaches `onImport`); it never parses the CSV, because the host is the authority on line\n * and column.\n */\nexport function CsvPanel({ result, busy, onImport, onRefuse, onExport }: CsvPanelProps) {\n function onFile(e: ChangeEvent<HTMLInputElement>) {\n const input = e.target;\n const file = input.files?.[0];\n if (file === undefined) return;\n // Reset the input's own value so choosing the SAME file again re-fires `change`.\n input.value = \"\";\n if (file.size > CSV_MAX_BYTES) {\n onRefuse(CSV_TOO_LARGE_COPY);\n return;\n }\n onImport(file);\n }\n\n return (\n <div className=\"w6w-data-csv-panel\" data-testid=\"csv-panel\">\n <div className=\"w6w-data-csv-panel-actions\">\n <input\n type=\"file\"\n accept=\".csv,text/csv\"\n data-testid=\"csv-file\"\n aria-label=\"Import CSV\"\n onChange={onFile}\n />\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"csv-export\"\n disabled={busy}\n onClick={onExport}\n >\n Export CSV\n </button>\n </div>\n {result !== null && (\n <div className={result.ok ? \"w6w-result\" : \"w6w-result w6w-error\"} data-testid=\"csv-result\">\n {result.message}\n </div>\n )}\n </div>\n );\n}\n","import { type FormEvent, type ReactNode, useState } from \"react\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\n\n/** One row of a kv/doc store's entry list, as the host has already prepared it. */\nexport interface DataEntryListRow {\n key: string;\n version: number;\n /** The short text shown in the Value column. */\n preview: string;\n}\n\nexport interface DataEntryListProps {\n rows: readonly DataEntryListRow[];\n /** Shown instead of the table when there are no rows and the list is not `loading`. */\n empty?: ReactNode;\n /** When there are no rows, shows the loading text instead of `empty`. */\n loading?: boolean;\n /** Initial text of the key-prefix box. */\n searchValue?: string;\n /** Renders \"Load more\" when true. */\n hasMore?: boolean;\n /** Fired when a row is opened by mouse or its key button by keyboard. */\n onOpen: (key: string) => void;\n /** Fired with the prefix text when the search form is SUBMITTED (never per keystroke). */\n onSearch: (text: string) => void;\n /** Fired by the \"New entry\" button. */\n onNew: () => void;\n /** Fired by \"Load more\". */\n onLoadMore: () => void;\n}\n\n/**\n * A presentational list of a kv/doc store's entries: view-model rows in, callbacks out. It owns\n * only the text of the search box; the query, the editor and the delete confirmation are the\n * host's. Rows render through {@link DataTable}.\n */\nexport function DataEntryList({\n rows,\n empty,\n loading,\n searchValue,\n hasMore,\n onOpen,\n onSearch,\n onNew,\n onLoadMore,\n}: DataEntryListProps) {\n const [prefix, setPrefix] = useState(searchValue ?? \"\");\n const submit = (e: FormEvent) => {\n e.preventDefault();\n onSearch(prefix);\n };\n const columns: DataTableColumn<DataEntryListRow>[] = [\n {\n key: \"key\",\n header: \"Key\",\n width: \"38%\",\n render: (row) => (\n <button\n type=\"button\"\n className=\"w6w-data-entry-key\"\n title={row.key}\n data-testid=\"entry-key\"\n onClick={(event) => {\n event.stopPropagation();\n onOpen(row.key);\n }}\n >\n {row.key}\n </button>\n ),\n },\n {\n key: \"value\",\n header: \"Value\",\n render: (row) => (\n <span className=\"w6w-muted w6w-small w6w-data-entry-preview\">{row.preview}</span>\n ),\n },\n ];\n return (\n <div>\n <form className=\"w6w-data-entries-toolbar\" data-testid=\"entry-search\" onSubmit={submit}>\n <input\n type=\"search\"\n data-testid=\"entry-prefix\"\n value={prefix}\n placeholder=\"Key prefix\"\n aria-label=\"Key prefix\"\n onChange={(e) => setPrefix(e.target.value)}\n />\n <button className=\"w6w-btn w6w-btn-ghost\" type=\"submit\">\n Search\n </button>\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entry-new\"\n onClick={onNew}\n >\n New entry\n </button>\n </form>\n\n <DataTable\n className=\"w6w-data-entry-list\"\n onRowClick={(row) => onOpen(row.key)}\n columns={columns}\n rows={rows}\n rowKey={(row) => row.key}\n empty={\n // A div, not a <p>: `empty` is any node and callers often pass a <p>.\n <div className=\"w6w-muted w6w-small\">\n {loading ? \"Loading…\" : (empty ?? \"No entries match this key prefix.\")}\n </div>\n }\n />\n\n {hasMore && (\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entries-load-more\"\n onClick={onLoadMore}\n >\n Load more\n </button>\n )}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { JsonEditor } from \"../JsonEditor.tsx\";\nimport { VERSION_CONFLICT_COPY, parseDocText } from \"../data-stores/data-store-view.ts\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\nimport { Modal } from \"./Modal.tsx\";\n\nexport interface DataEntryEditorProps {\n /** `kv` edits one input; `doc` edits JSON in a {@link JsonEditor}. */\n kind: \"kv\" | \"doc\";\n /** True for a not-yet-created entry: opens directly in edit mode with a key input. */\n isNew: boolean;\n /** The entry's key (existing mode heading). */\n entryKey?: string;\n /** The new entry's key (controlled). */\n newKey?: string;\n /** Concurrency token supplied by the host; never presented as document history. */\n version?: number | null;\n /** Existing mode: ISO expiry, shown when set. */\n expiresAt?: string | null;\n /** The value text (controlled). */\n text: string;\n /** A host-supplied value/save error. */\n error?: string | null;\n /** True after a stale `ifVersion`: shows the conflict copy and Reload, and disables Save. */\n conflict?: boolean;\n /** True while a save is in flight: disables Save. */\n saving?: boolean;\n /** Fired per edit of the value, with the new text. */\n onTextChange: (text: string) => void;\n /** Fired per edit of the new-entry key, with the new text. */\n onKeyChange: (key: string) => void;\n /** Opens the host's delete confirmation for an existing entry. */\n onDelete?: () => void;\n onSave: () => void;\n onCancel: () => void;\n /** Fired by the conflict prompt's Reload. */\n onReload: () => void;\n}\n\n/**\n * Existing entries open for viewing, then Edit enables changes inside the same modal.\n * New entries start in edit mode. Drafts, `ifVersion` and mutations live in the host.\n * Document validity is derived from the controlled text, including initial values and reloads.\n */\nexport function DataEntryEditor({\n kind,\n isNew,\n entryKey,\n newKey,\n expiresAt,\n text,\n error,\n conflict,\n saving,\n onTextChange,\n onKeyChange,\n onDelete,\n onSave,\n onCancel,\n onReload,\n}: DataEntryEditorProps) {\n const [editing, setEditing] = useState(isNew);\n const [showValidation, setShowValidation] = useState(false);\n const closeButton = useRef<HTMLButtonElement>(null);\n useEffect(() => {\n if (!isNew) closeButton.current?.focus();\n }, [isNew]);\n const noun = kind === \"doc\" ? \"document\" : \"entry\";\n const parsedDocument = kind === \"doc\" ? parseDocText(text) : undefined;\n const invalidDocument = parsedDocument !== undefined && !parsedDocument.ok;\n const valueError =\n error ||\n (showValidation && parsedDocument && !parsedDocument.ok ? parsedDocument.message : null);\n const body = (\n <>\n {isNew ? (\n <label className=\"w6w-field\">\n <span>Key</span>\n <input\n data-testid=\"entry-new-key\"\n value={newKey ?? \"\"}\n placeholder=\"Key\"\n aria-label=\"Key\"\n onChange={(e) => onKeyChange(e.target.value)}\n />\n </label>\n ) : expiresAt ? (\n <p className=\"w6w-muted w6w-small\">Expires {expiresAt}</p>\n ) : null}\n\n {kind === \"doc\" ? (\n <JsonEditor\n value={text}\n readOnly={!editing}\n onChange={(next) => {\n setShowValidation(false);\n onTextChange(next);\n }}\n onFocus={() => setShowValidation(false)}\n onBlur={() => setShowValidation(true)}\n showDiagnostics={showValidation}\n minHeight=\"min(50vh, 400px)\"\n maxHeight=\"60vh\"\n />\n ) : (\n <input\n data-testid=\"entry-value\"\n value={text}\n aria-label=\"Value\"\n readOnly={!editing}\n onChange={(e) => onTextChange(e.target.value)}\n />\n )}\n\n {valueError && (\n <div className=\"w6w-field-error\" role=\"alert\" data-testid=\"entry-value-error\">\n {valueError}\n </div>\n )}\n {conflict && (\n <div className=\"w6w-error\" data-testid=\"entry-conflict\">\n {VERSION_CONFLICT_COPY}{\" \"}\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entry-reload\"\n onClick={onReload}\n >\n Reload\n </button>\n </div>\n )}\n </>\n );\n return (\n <Modal\n title={\n isNew ? `New ${noun}` : editing ? `Edit ${noun}` : kind === \"doc\" ? \"Document\" : \"Entry\"\n }\n subtitle={isNew ? undefined : entryKey}\n size={kind === \"doc\" ? \"wide\" : \"default\"}\n onClose={saving ? () => {} : onCancel}\n >\n <div className=\"w6w-modal-body\" data-testid=\"entry-editor\">\n {body}\n </div>\n <div className=\"w6w-modal-actions\">\n {!isNew && onDelete && (\n <DeleteButton\n label=\"Delete entry\"\n className=\"w6w-data-entry-delete\"\n disabled={saving}\n onClick={onDelete}\n />\n )}\n <button\n ref={closeButton}\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n disabled={saving}\n onClick={onCancel}\n >\n {editing ? \"Cancel\" : \"Close\"}\n </button>\n {editing ? (\n <button\n className=\"w6w-btn\"\n type=\"button\"\n data-testid=\"entry-save\"\n disabled={\n Boolean(conflict) || Boolean(saving) || invalidDocument || (isNew && !newKey?.trim())\n }\n onClick={onSave}\n >\n Save\n </button>\n ) : (\n <button\n className=\"w6w-btn\"\n type=\"button\"\n disabled={saving}\n onClick={() => setEditing(true)}\n >\n Edit\n </button>\n )}\n </div>\n </Modal>\n );\n}\n","import { type FormEvent, type ReactNode, useState } from \"react\";\nimport { type TableColumn, VERSION_CONFLICT_COPY } from \"../data-stores/data-store-view.ts\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\n\n/** One grid row as the host has prepared it. `id` is the entry key; the new row is `isNew`. */\nexport interface DataTableGridRow {\n id: string;\n /** True for the unsaved row: its key cell is editable and its `data-row` is `\"new\"`. */\n isNew?: boolean;\n /** Draft cell text by column name. */\n cells: Record<string, string>;\n /** The version the row was loaded at; `null` for a new row. */\n version: number | null;\n /** True when the draft differs from the loaded entry. */\n dirty: boolean;\n /** True after a stale `ifVersion`: shows the conflict copy and Reload, and disables Save. */\n conflict?: boolean;\n /** Per-cell error messages by column name, shown under their own cell. */\n cellErrors?: Record<string, string>;\n}\n\nexport interface DataTableGridProps {\n columns: readonly TableColumn[];\n /** The column whose cell is the row key (read-only on an existing row). */\n keyColumn: string;\n rows: readonly DataTableGridRow[];\n /** A grid-level (not cell) error. */\n error?: string | null;\n loading?: boolean;\n empty?: ReactNode;\n /** Initial text of the key-prefix box. */\n searchValue?: string;\n hasMore?: boolean;\n onCellChange: (rowId: string, column: string, text: string) => void;\n onSave: (rowId: string) => void;\n /** Fired immediately; confirmation is the host's. */\n onDelete: (rowId: string) => void;\n onReload: (rowId: string) => void;\n onAddRow: () => void;\n onLoadMore: () => void;\n /** Fired with the prefix text when the search form is SUBMITTED (never per keystroke). */\n onSearch: (text: string) => void;\n}\n\nconst rowAttr = (row: DataTableGridRow) => (row.isNew ? \"new\" : row.id);\n\n/**\n * A presentational editable grid for a table store: row view-models in, callbacks out. Drafts,\n * dirty tracking, version handling and the delete confirmation are the host's. Rows render through\n * {@link DataTable}.\n */\nexport function DataTableGrid({\n columns,\n keyColumn,\n rows,\n error,\n loading,\n empty,\n searchValue,\n hasMore,\n onCellChange,\n onSave,\n onDelete,\n onReload,\n onAddRow,\n onLoadMore,\n onSearch,\n}: DataTableGridProps) {\n const [prefix, setPrefix] = useState(searchValue ?? \"\");\n const submit = (e: FormEvent) => {\n e.preventDefault();\n onSearch(prefix);\n };\n const tableColumns: DataTableColumn<DataTableGridRow>[] = [\n ...columns.map((column) => ({\n key: column.name,\n header: (\n <>\n {column.name} <span className=\"w6w-muted w6w-small\">{column.type}</span>\n </>\n ),\n render: (row: DataTableGridRow) => {\n const message = row.cellErrors?.[column.name];\n return (\n <div className=\"w6w-data-cell\">\n <input\n data-row={rowAttr(row)}\n data-column={column.name}\n value={row.cells[column.name] ?? \"\"}\n readOnly={column.name === keyColumn && !row.isNew}\n aria-label={`${column.name} (${column.type})`}\n onChange={(e) => onCellChange(row.id, column.name, e.target.value)}\n />\n {message !== undefined && (\n <div\n className=\"w6w-data-cell-error\"\n data-row={rowAttr(row)}\n data-column={column.name}\n >\n {message}\n </div>\n )}\n </div>\n );\n },\n })),\n {\n key: \"actions\",\n header: \"\",\n render: (row: DataTableGridRow) => (\n <div className=\"w6w-data-row-actions\">\n <span className=\"w6w-muted w6w-small\">\n {row.version === null ? \"\" : `v${row.version}`}\n </span>\n <button\n className=\"w6w-btn\"\n type=\"button\"\n data-row={rowAttr(row)}\n data-testid=\"row-save\"\n disabled={(!row.isNew && !row.dirty) || Boolean(row.conflict)}\n onClick={() => onSave(row.id)}\n >\n Save\n </button>\n <DeleteButton label=\"Delete entry\" onClick={() => onDelete(row.id)} />\n {row.conflict && (\n <div className=\"w6w-error\" data-row={rowAttr(row)} data-testid=\"row-conflict\">\n {VERSION_CONFLICT_COPY}{\" \"}\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"row-reload\"\n onClick={() => onReload(row.id)}\n >\n Reload\n </button>\n </div>\n )}\n </div>\n ),\n },\n ];\n return (\n <div>\n {error != null && error !== \"\" && (\n <div className=\"w6w-error\" data-testid=\"grid-error\">\n {error}\n </div>\n )}\n\n <form className=\"w6w-data-entries-toolbar\" data-testid=\"entry-search\" onSubmit={submit}>\n <input\n type=\"search\"\n data-testid=\"entry-prefix\"\n value={prefix}\n placeholder=\"Key prefix\"\n aria-label=\"Key prefix\"\n onChange={(e) => setPrefix(e.target.value)}\n />\n <button className=\"w6w-btn w6w-btn-ghost\" type=\"submit\">\n Search\n </button>\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"grid-add-row\"\n onClick={onAddRow}\n >\n Add row\n </button>\n </form>\n\n <div className=\"w6w-data-grid-scroll\" data-testid=\"data-grid-scroll\">\n <DataTable\n columns={tableColumns}\n rows={rows}\n rowKey={(row) => row.id}\n empty={\n // A div, not a <p>: `empty` is any node and callers often pass a <p>.\n <div className=\"w6w-muted w6w-small\">\n {loading ? \"Loading…\" : (empty ?? \"No rows match this key prefix.\")}\n </div>\n }\n />\n </div>\n\n {hasMore && (\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entries-load-more\"\n onClick={onLoadMore}\n >\n Load more\n </button>\n )}\n </div>\n );\n}\n"],"names":["ApiError","status","code","message","body","__publicField","createW6WApi","opts","baseUrl","doFetch","getToken","rawReq","path","init","headers","token","res","e","text","data","err","req","walk","apps","cursor","qs","r","ids","unique","i","id","appId","filter","q","authKey","actionKey","params","connectionId","patch","connId","workflowId","stepId","nodeId","input","inputs","ListItem","title","subtitle","icon","trailing","active","onClick","href","ariaLabel","jsxs","Fragment","jsx","className","relativeTime","iso","then","secs","mins","hours","days","defaultParamsFor","action","out","p","extractProviderMessage","msg","brace","j","m","_b","_a","_c","prefix","isInvokeApiError","describeInvokeError","detail","haystack","apiCallsOf","source","useOverrideJsonField","setText","useState","value","setValue","invalid","setInvalid","next","trimmed","parsed","ActionTestForm","actions","seedValues","onSavedTestsChanged","seedTestId","onDirtyChange","onTestSaved","onDeleted","embedded","api","useW6WApi","sortedActions","useMemo","list","a","b","pickedKey","setPickedKey","selectedAction","running","setRunning","error","setError","result","setResult","apiCalls","setApiCalls","ovBody","ovQuery","ovHeaders","ovTarget","setOvTarget","ovMatch","setOvMatch","overridesInvalid","currentOverrides","viewMode","setViewMode","jsonText","setJsonText","jsonInvalid","setJsonInvalid","modalOpen","setModalOpen","selectedKey","initialValues","valuesByAction","setValuesByAction","editingTestId","setEditingTestId","baseline","setBaseline","fresh","lastSeedTestId","setLastSeedTestId","lastSeed","setLastSeed","structurallyChanged","seeded","values","setValues","dirty","useEffect","enterJsonView","runWith","outcome","overrides","refreshSavedTests","refreshRunHistory","run","savedTests","setSavedTests","savedTestsError","setSavedTestsError","savedTestsNonce","setSavedTestsNonce","nameModalOpen","setNameModalOpen","pendingName","setPendingName","confirmDeleteOpen","setConfirmDeleteOpen","n","canceled","railTests","t","runHistory","setRunHistory","runHistoryNonce","setRunHistoryNonce","load","railRunHistory","openSaveModal","handleSaveClick","submitSaveTest","saved","name","loadSavedTest","loaded","deleteCurrentTest","deletedId","paramsRegion","v","ParamsForm","JsonEditor","valid","overridesRegion","savedTestsRail","deletingTestName","Combobox","errorBox","resultBlock","ResultViewer","paramsAndResult","ApiCallsPanel","actionBar","Modal","ConfirmModal","YamlEditor","props","theme","useEffectiveTheme","copied","copy","useCopyToClipboard","extensions","yaml","EditorView","EDITOR_THEME_SPEC","handleChange","CodeMirror","CheckGlyph","CopyGlyph","MARKER","cropText","chars","crop","head","tail","CopyableText","label","copiedMs","cropped","classes","Copyable","DEFAULT_LABELS","HealthStatusPill","state","STATE_LABELS","UptimeStrip","entry","UNKNOWN","BYTE_UNITS","formatBytes","unit","formatPercent","f","cpuLoadFraction","s","divisor","memoryUsedFraction","memoryTotal","memoryAvailable","clamp","lo","hi","sparklinePoints","width","height","max","points","x","y","SPARK_WIDTH","SPARK_HEIGHT","Sparkline","formatLoad","fractionMax","MetricRow","readings","samples","last","cpuValues","memoryValues","rssValues","ServerResourcesCard","intervalMs","ServerResourcesCardSmall","ServerResourcesRail","onExpand","ServerResourcesBadge","cpu","mem","MIN_BAR_WIDTH_PCT","DAY_MS","placeIncidentBar","window","bar","nowMs","start","startMs","endMs","windowStartMs","windowEndMs","spanMs","clippedStart","clippedEnd","clampedStartMs","clampedEndMs","leftPct","rawWidthPct","widthPct","NO_FEED_LABEL","QUIET_LABEL","barTitle","parts","HistoryTimeline","win","incidents","vendorEmptyLabel","cellWidthPct","emptyLabel","placement","clipClass","InfoTip","children","open","setOpen","useId","IconButton","o","EditButton","disabled","rest","RepoSyncIndicator","branch","shortSha","lastSyncLabel","onSyncNow","syncing","ref","useRef","onDown","onKey","Icon","StepStatusPill","MS_PER_SECOND","MS_PER_MINUTE","formatDurationMs","ms","formatExecutionTime","date","KIND_LABEL","TRIGGER_LABEL","triggerText","item","ExecutionList","items","selectedId","onSelect","showCallable","loading","hasPrev","hasNext","onPrev","onNext","onRerun","rerunningId","pager","describeNode","node","builtin","internalNodeDef","chronologicalSteps","steps","time","step","ExecutionLogPanel","onDismiss","runError","stepErrors","recorded","errors","ExecutionLogErrorBlock","index","inRun","isOffPath","offPath","footer","ExecutionLogOffPath","ExecutionLogRow","SKIP_REASON_LABELS","header","StepTiming","loop","ExecutionLogIterations","hasStateBlock","ExecutionLogState","ExecutionLogConditions","ExecutionLogJson","CodeBlock","iterations","total","failedCount","it","firstFailed","defaultIndex","bodyIds","labels","failedId","ExecutionLogBodyStep","initial","selected","setSelected","record","startedAt","finishedAt","elapsed","formatElapsed","totalSeconds","minutes","seconds","isRecord","conditionTrace","rows","groups","own","route","trace","g","conditionCombinatorLabel","row","conditionOperatorLabel","operandText","STATE_WARNING_LABELS","stateWarningLabel","hasWrites","after","STATE_VALUE_MAX","stateValueText","writes","w","EMPTY","STATUS_OPTIONS","KIND_OPTIONS","ExecutionFilters","onChange","showKind","searchPlaceholder","clearable","option","ExecutionStats","stats","cards","formatSuccessRate","card","rate","toJson","ExecutionDetail","execution","errorMessage","onClose","onOpenInEditor","onBack","rerunning","onOpenExecution","Body","rerunOf","TimingItem","JsonSection","testid","performancePoints","services","needsAttention","service","partitionBoard","uptimeDays","ATTENTION_DISPLAY_CAP","RECENT_DISPLAY_CAP","displayBoard","compact","now","recent","attentionCount","shownNow","shownRecent","shownTable","WIDTH","HEIGHT","PAD","niceMax","magnitude","ticks","count","_","ReliabilityChart","getHref","onOpen","maxCalls","maxP95","maxErrors","plotW","plotH","calls","p95","iconSize","xTicks","yTicks","yAxisTitleX","yAxisTitleY","size","cx","cy","dots","formatDay","d","Target","ExecStatusSignal","ApiStatusSignal","vendor","unreadable","IssueCard","AppIcon","ServiceTableRow","noCalls","ReliabilityList","showChart","limit","showAllHref","onShowAll","slots","windowDays","allClear","hiddenAttentionCount","hiddenTableCount","shouldShowChart","canShowAll","showAllLink","cellValue","col","DataTable","columns","rowKey","onRowClick","getRowHref","empty","testId","c","content","EmptyState","CallableList","description","emptyCopy","newLabel","openRowTitle","testIds","onCreate","creating","onImport","showArchivedProp","onShowArchivedChange","showArchivedState","setShowArchivedState","controlled","showArchived","visible","interactive","setShowArchived","archivedOnly","event","ConnectionList","connections","appsById","onEdit","onDelete","busy","byId","hasActions","app","resolveConnectionAppMeta","DeleteButton","EditConnectionModal","connection","onSaved","update","builtIn","editable","displayName","setDisplayName","setAuthKey","credential","setCredential","auths","setAuths","pending","setPending","bindingVals","setBindingVals","connectionCount","setConnectionCount","credentialContract","setCredentialContract","health","setHealth","authDef","authChanged","authChoices","isOAuth","fields","credentialId","storedCredential","bindingFields","bindingFieldsFor","buildBody","binding","buildBinding","filled","save","hasCredential","missing","parseJsonFields","credentialSaved","updated","checkHealth","enterSubmit","useEnterSubmit","AuthFieldsForm","ConnectionHeader","conn","defaultFormat","pct","clamped","BudgetMeter","used","reserved","format","fmt","hasReserved","usedPct","reservedPct","over","valueText","DATA_STORE_KIND_LABEL","DATA_STORE_KINDS","SCALAR_TYPES","CSV_MAX_BYTES","kvValueTypeOf","store","declared","tableSchemaOf","key","csvFilenameOf","contentDisposition","storeName","quoted","CELL_PROBLEM_COPY","NUMBER_TEXT","INTEGER_TEXT","DATE_TEXT","DATETIME_TEXT","daysInMonth","year","month","readDate","day","refuse","problem","parseCell","type","required","isDateTime","hour","minute","second","zone","serializeCell","json","isCellValue","DATA_STORE_ERROR_FALLBACK","DATA_STORE_NETWORK_ERROR","textOf","rowOf","locatorFromEnvelope","fallbackMessages","locator","envelope","field","column","candidate","locateDataStoreError","shaped","raw","ownMessage","locateRawResponseError","errorPlacement","loc","csvLineOf","NEW_ROW_ID","VERSION_CONFLICT_COPY","DOC_VALUE_COPY","CSV_TOO_LARGE_COPY","rowValueOf","draftFromEntry","cells","newRowDraft","dirtyColumns","draft","base","buildRowValue","remainingTtlSeconds","expiresAt","rowWriteOf","ttlSeconds","write","cellErrorsOf","isVersionConflict","parseDocText","kvValueOf","csvImportMessage","imported","DataStoreList","stores","onArchive","formatSize","eligibleAsKey","withDefault","_old","ColumnsEditor","keyColumn","onKeyColumnChange","columnErrors","drafts","setDrafts","eligible","eligibleKey","addColumn","updateColumn","idx","setDefault","extra","removeColumn","k","CsvPanel","onRefuse","onExport","onFile","file","DataEntryList","searchValue","hasMore","onSearch","onNew","onLoadMore","setPrefix","submit","DataEntryEditor","kind","isNew","entryKey","newKey","conflict","saving","onTextChange","onKeyChange","onSave","onCancel","onReload","editing","setEditing","showValidation","setShowValidation","closeButton","noun","parsedDocument","invalidDocument","valueError","rowAttr","DataTableGrid","onCellChange","onAddRow","tableColumns"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/createW6WApi.ts","../src/components/ListItem.tsx","../src/ActionTestForm.tsx","../src/YamlEditor.tsx","../src/components/CopyableText.tsx","../src/components/HealthStatusPill.tsx","../src/components/UptimeStrip.tsx","../src/components/server-resources-format.ts","../src/components/ServerResources.tsx","../src/components/history-scale.ts","../src/components/HistoryTimeline.tsx","../src/components/InfoTip.tsx","../src/components/EditButton.tsx","../src/components/RepoSyncIndicator.tsx","../src/components/StepStatusPill.tsx","../src/components/execution-format.ts","../src/components/ExecutionList.tsx","../src/components/ExecutionLogPanel.tsx","../src/components/ExecutionFilters.tsx","../src/components/ExecutionStats.tsx","../src/components/ExecutionDetail.tsx","../src/reliability-board-layout.ts","../src/components/ReliabilityChart.tsx","../src/components/ReliabilityList.tsx","../src/components/DataTable.tsx","../src/components/EmptyState.tsx","../src/components/CallableList.tsx","../src/components/ConnectionList.tsx","../src/EditConnectionModal.tsx","../src/ConnectionHeader.tsx","../src/components/BudgetMeter.tsx","../src/data-stores/data-store-view.ts","../src/components/DataStoreList.tsx","../src/components/ColumnsEditor.tsx","../src/components/CsvPanel.tsx","../src/components/DataEntryList.tsx","../src/components/DataEntryEditor.tsx","../src/components/DataTableGrid.tsx"],"sourcesContent":["/**\n * Default fetch-based W6WApi client. Convenience for partners without their\n * own HTTP client — studio wires react-query around its own implementation\n * and doesn't use this. Every method calls the w6w server directly and\n * throws `ApiError` on non-OK responses so callers can surface the message.\n */\nimport type { NodeSample } from \"./node-samples.ts\";\nimport type { StepMeta, StepTest, TestRunSummary, W6WApi } from \"./provider.tsx\";\nimport type { NodeTestInput } from \"./test-inputs.ts\";\nimport type {\n ActionDef,\n ApiCallRecord,\n AppSummary,\n AuthDef,\n ConnectionSummary,\n CredentialDependents,\n CredentialSummary,\n CredentialTestResult,\n FunctionDetail,\n FunctionSummary,\n SavedTest,\n WorkflowDetail,\n WorkflowSummary,\n} from \"./types.ts\";\n\nexport interface CreateW6WApiOptions {\n /** Absolute URL or path prefix — e.g. `\"https://w6w.example.com\"` or `\"/api\"`. */\n baseUrl: string;\n /**\n * Bearer token to send. Accepts a string (static) or a supplier function so\n * a JWT that rotates on refresh is fetched fresh on every request. The\n * supplier may be sync or return a `Promise` — either way it is awaited\n * once per request. It receives an optional `{ forceRefresh? }` ctx arg\n * (unused by this client today, but part of the shape so a caller's\n * supplier can share one implementation with `@w6w/sdk`'s `TokenProvider`).\n */\n token?:\n | string\n | ((ctx?: { forceRefresh?: boolean }) =>\n | string\n | null\n | undefined\n | Promise<string | null | undefined>);\n /** Optional fetch replacement — handy for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nexport class ApiError extends Error {\n status: number;\n code: string;\n /**\n * The parsed error response body, when the server sent one. Carries the\n * fields that ride alongside an error — e.g. an invoke's `logs` and\n * `apiCalls` — which the message alone would drop.\n */\n body?: unknown;\n\n constructor(status: number, code: string, message: string, body?: unknown) {\n super(message);\n this.name = \"ApiError\";\n this.status = status;\n this.code = code;\n this.body = body;\n }\n}\n\n/** Build a fetch-based W6WApi client bound to a base URL + token supplier. */\nexport function createW6WApi(opts: CreateW6WApiOptions): W6WApi {\n const baseUrl = opts.baseUrl.replace(/\\/$/, \"\");\n const doFetch = opts.fetch ?? globalThis.fetch;\n const getToken = async () => (typeof opts.token === \"function\" ? await opts.token() : opts.token);\n\n // The shared fetch core: auth header, JSON parse, and the one error-shaping\n // idiom every member uses. Exposes the response's own status code (`req<T>`\n // below discards it) — `runWorkflow` is the one caller that needs it, to\n // derive `terminal` from `200` vs the server's own `202` wait-timeout arm.\n async function rawReq(\n path: string,\n init?: RequestInit,\n ): Promise<{ status: number; data: unknown }> {\n const headers = new Headers(init?.headers);\n const token = await getToken();\n if (token) headers.set(\"authorization\", `Bearer ${token}`);\n if (init?.body && !headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n\n let res: Response;\n try {\n res = await doFetch(`${baseUrl}${path}`, { ...init, headers });\n } catch (e) {\n // A failed fetch throws a bare `TypeError: Failed to fetch` — wrap it with\n // the target so callers can tell the server is down vs. a real API error.\n throw new ApiError(\n 0,\n \"network_error\",\n `Could not reach the w6w server (${init?.method ?? \"GET\"} ${baseUrl}${path}). ` +\n `It may be down or unreachable. (${(e as Error).message})`,\n );\n }\n const text = await res.text();\n let data: unknown = null;\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n if (!res.ok) {\n throw new ApiError(\n res.status,\n \"bad_response\",\n `Server returned a non-JSON ${res.status} response: ${text.slice(0, 200)}`,\n );\n }\n }\n }\n if (!res.ok) {\n const err = ((data as { error?: { code?: string; message?: string } } | null)?.error ??\n {}) as { code?: string; message?: string };\n throw new ApiError(res.status, err.code ?? \"error\", err.message ?? res.statusText, data);\n }\n return { status: res.status, data };\n }\n\n async function req<T>(path: string, init?: RequestInit): Promise<T> {\n const { data } = await rawReq(path, init);\n return data as T;\n }\n\n return {\n // A bare GET only returns the server's default page (50) — every consumer\n // of this client treats the result as the complete catalog, so walk one\n // server snapshot by `nextCursor` (opaque; the cursor encodes the\n // snapshot, so `snapshot`/`offset` are never sent). No page cap: the walk\n // ends when the cursor is absent or fails to advance. If the snapshot\n // expired mid-walk (410 `snapshot_expired` / 404 `unknown_snapshot`, alike\n // to a token holder), drop what was gathered and restart once.\n listApps: async () => {\n const walk = async (): Promise<AppSummary[]> => {\n const apps: AppSummary[] = [];\n let cursor: string | undefined;\n for (;;) {\n const qs = new URLSearchParams({ limit: \"200\" });\n if (cursor) qs.set(\"cursor\", cursor);\n const r = await req<{ apps: AppSummary[]; nextCursor?: string }>(`/apps?${qs}`);\n apps.push(...r.apps);\n if (!r.nextCursor || r.nextCursor === cursor) return apps;\n cursor = r.nextCursor;\n }\n };\n try {\n return await walk();\n } catch (e) {\n if (\n e instanceof ApiError &&\n (e.code === \"snapshot_expired\" || e.code === \"unknown_snapshot\")\n ) {\n return await walk();\n }\n throw e;\n }\n },\n\n // Bounded lookup: dedupe; `[]` sends nothing; chunks of <= 100 (the server's\n // `MAX_IDS_PER_QUERY`), each `GET /apps?ids=a,b` with no limit/cursor.\n listAppsByIds: async (ids) => {\n const unique = Array.from(new Set(ids));\n const apps: AppSummary[] = [];\n for (let i = 0; i < unique.length; i += 100) {\n const chunk = unique.slice(i, i + 100);\n const qs = chunk.map(encodeURIComponent).join(\",\");\n const r = await req<{ apps: AppSummary[] }>(`/apps?ids=${qs}`);\n apps.push(...r.apps);\n }\n return apps;\n },\n\n getAppAuth: async (id: string) => {\n const r = await req<{ auths: AuthDef[] }>(`/apps/${encodeURIComponent(id)}/auths`);\n return r.auths ?? [];\n },\n\n createConnection: (appId, body) =>\n req<{ connection: ConnectionSummary }>(`/apps/${encodeURIComponent(appId)}/connections`, {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then((r) => r.connection),\n\n updateConnection: (id, body) =>\n req<{ connection: ConnectionSummary }>(`/connections/${encodeURIComponent(id)}`, {\n method: \"PATCH\",\n body: JSON.stringify(body),\n }).then((r) => r.connection),\n\n listCredentials: (filter) => {\n const qs = new URLSearchParams();\n if (filter?.contract !== undefined) qs.set(\"contract\", filter.contract);\n if (filter?.appId !== undefined) qs.set(\"appId\", filter.appId);\n if (filter?.authKey !== undefined) qs.set(\"authKey\", filter.authKey);\n const q = qs.toString();\n return req<{ credentials: CredentialSummary[] }>(`/credentials${q ? `?${q}` : \"\"}`).then(\n (r) => r.credentials ?? [],\n );\n },\n\n createCredential: (body) =>\n req<{ credential: CredentialSummary }>(\"/credentials\", {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then((r) => r.credential),\n\n getCredential: (id) =>\n req<{ credential: CredentialSummary }>(`/credentials/${encodeURIComponent(id)}`).then(\n (r) => r.credential,\n ),\n\n rotateCredential: (id, body) =>\n req<{ credential: CredentialSummary }>(`/credentials/${encodeURIComponent(id)}/rotate`, {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then((r) => r.credential),\n\n setCredentialStatus: (id, status) =>\n req<{ credential: CredentialSummary }>(\n `/credentials/${encodeURIComponent(id)}/${status === \"disabled\" ? \"disable\" : \"enable\"}`,\n { method: \"POST\" },\n ).then((r) => r.credential),\n\n testCredential: (id) =>\n req<CredentialTestResult>(`/credentials/${encodeURIComponent(id)}/test`, { method: \"POST\" }),\n\n credentialDependents: (id) =>\n req<{ dependents: CredentialDependents }>(\n `/credentials/${encodeURIComponent(id)}/dependents`,\n ).then((r) => r.dependents),\n\n deleteCredential: async (id) => {\n await req<unknown>(`/credentials/${encodeURIComponent(id)}`, { method: \"DELETE\" });\n },\n\n startAppOAuthFlow: (appId, authKey, body) =>\n req<{ authorizationUrl: string }>(\n `/apps/${encodeURIComponent(appId)}/oauth-config/${encodeURIComponent(authKey)}/authorize-url`,\n { method: \"POST\", body: JSON.stringify(body) },\n ),\n\n getAppActions: (appId) =>\n req<{ actions: ActionDef[] }>(`/apps/${encodeURIComponent(appId)}`).then(\n (r) => r.actions ?? [],\n ),\n\n listConnectionsForApp: (appId) =>\n req<{ connections: ConnectionSummary[] }>(\n `/apps/${encodeURIComponent(appId)}/connections`,\n ).then((r) => r.connections ?? []),\n\n listConnections: () =>\n req<{ connections: ConnectionSummary[] }>(\"/connections\").then((r) => r.connections ?? []),\n\n invokeAction: (appId, actionKey, params, opts = {}) =>\n req<{\n value: unknown;\n logs?: string[];\n apiCalls?: ApiCallRecord[];\n meta?: StepMeta;\n }>(\n `/apps/${encodeURIComponent(appId)}/actions/${encodeURIComponent(actionKey)}/invoke`,\n // This body is built KEY BY KEY, not by spreading `opts` — so every new\n // option has to be named here or it is silently dropped before the wire\n // (the caller compiles, the UI looks right, the field never leaves the\n // page). `project` scopes document-expression resolution to the\n // workflow's selected project; `state` is the start state upstream step\n // outputs are seeded from, so `{{ steps.<id>.output.<f> }}` resolves.\n // Undefined keys are dropped by JSON.stringify, so an absent project or\n // state leaves the request byte-identical to one that never had them.\n {\n method: \"POST\",\n body: JSON.stringify({\n params,\n connectionId: opts.connectionId,\n project: opts.project,\n state: opts.state,\n workflowId: opts.workflowId,\n }),\n },\n ),\n\n listSavedTests: (connectionId) =>\n req<{ savedTests: SavedTest[] }>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests`,\n ).then((r) => r.savedTests ?? []),\n\n createSavedTest: (connectionId, body) =>\n req<{ savedTest: SavedTest }>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests`,\n { method: \"POST\", body: JSON.stringify(body) },\n ).then((r) => r.savedTest),\n\n updateSavedTest: (connectionId, id, patch) =>\n req<{ savedTest: SavedTest }>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests/${encodeURIComponent(id)}`,\n { method: \"PATCH\", body: JSON.stringify(patch) },\n ).then((r) => r.savedTest),\n\n deleteSavedTest: (connectionId, id) =>\n req<void>(\n `/connections/${encodeURIComponent(connectionId)}/saved-tests/${encodeURIComponent(id)}`,\n { method: \"DELETE\" },\n ).then(() => undefined),\n\n recordTestRun: (connId, body) =>\n req<{ run: unknown }>(`/connections/${encodeURIComponent(connId)}/test-runs`, {\n method: \"POST\",\n body: JSON.stringify(body),\n }).then(() => undefined),\n\n listTestRuns: (connectionId) =>\n req<{ runs: TestRunSummary[] }>(\n `/connections/${encodeURIComponent(connectionId)}/test-runs`,\n ).then((r) => r.runs ?? []),\n\n saveStepTest: (workflowId, stepId, body) =>\n req<{ stepTest: StepTest }>(\n `/workflows/${encodeURIComponent(workflowId)}/steps/${encodeURIComponent(stepId)}/tests`,\n { method: \"POST\", body: JSON.stringify(body) },\n ).then((r) => r.stepTest),\n\n listStepTests: (workflowId, stepId) =>\n req<{ stepTests: StepTest[] }>(\n `/workflows/${encodeURIComponent(workflowId)}/steps/${encodeURIComponent(stepId)}/tests`,\n ).then((r) => r.stepTests ?? []),\n\n loadNodeSamples: (workflowId) =>\n req<{ nodeSamples?: NodeSample[] }>(\n `/workflows/${encodeURIComponent(workflowId)}/node-samples`,\n ).then((r) => r.nodeSamples ?? []),\n\n loadTestInputs: (workflowId) =>\n req<{ testInputs?: NodeTestInput[] }>(\n `/workflows/${encodeURIComponent(workflowId)}/test-inputs`,\n ).then((r) => r.testInputs ?? []),\n\n saveTestInput: (workflowId, nodeId, input) =>\n req<{ ok: boolean }>(\n `/workflows/${encodeURIComponent(workflowId)}/nodes/${encodeURIComponent(nodeId)}/test-input`,\n { method: \"PUT\", body: JSON.stringify({ input }) },\n ).then(() => undefined),\n\n recordStepTestRun: (workflowId, stepId, body) =>\n req<{ run: unknown }>(\n `/workflows/${encodeURIComponent(workflowId)}/steps/${encodeURIComponent(stepId)}/test-runs`,\n { method: \"POST\", body: JSON.stringify(body) },\n ).then(() => undefined),\n\n listFunctions: () =>\n req<{ functions: FunctionSummary[] }>(\"/functions\").then((r) => r.functions ?? []),\n\n getFunction: (id) =>\n req<{ function: Omit<FunctionDetail, \"valid\">; valid: boolean }>(\n `/functions/${encodeURIComponent(id)}`,\n ).then((r) => ({ ...r.function, valid: r.valid })),\n\n // The real synchronous route (`/functions/:id/invoke`) — deliberately NOT\n // `POST /run`, which would give the test stage a different code path than\n // the `@w6w/call` node it's standing in for. Returns the raw output,\n // pinned against the committed `studio/src/repos/functions.ts` signature.\n invokeFunction: (id, inputs) =>\n req<{ output?: unknown }>(`/functions/${encodeURIComponent(id)}/invoke`, {\n method: \"POST\",\n body: JSON.stringify({ inputs }),\n }).then((r) => r.output),\n\n listWorkflows: () =>\n req<{ workflows: WorkflowSummary[] }>(\"/workflows\").then((r) => r.workflows ?? []),\n\n getWorkflow: (id) =>\n req<{ workflow: WorkflowDetail }>(`/workflows/${encodeURIComponent(id)}`).then(\n (r) => r.workflow,\n ),\n\n // `rawReq`, not `req<T>` — the ONE caller that needs the response's own\n // status code: `200` (the run reached a terminal state inside the wait\n // window) vs `202` (the server's own wait-timeout, still running). Both\n // are 2xx successes; `rawReq` already throws on a non-2xx.\n runWorkflow: (id, opts = {}) =>\n rawReq(`/workflows/${encodeURIComponent(id)}/run?wait=true`, {\n method: \"POST\",\n body: JSON.stringify({ variables: opts.variables, input: opts.input, entry: opts.entry }),\n }).then(({ status, data }) => {\n const body = (data ?? {}) as {\n runId: string;\n status: string;\n output?: unknown;\n error?: unknown;\n };\n return { ...body, terminal: status === 200 };\n }),\n };\n}\n","import type { MouseEvent, ReactNode } from \"react\";\n\nexport interface ListItemProps {\n /** Primary label — prominent, single-line with ellipsis overflow. */\n title: ReactNode;\n /** Secondary label under the title — muted, small, truncates. */\n subtitle?: ReactNode;\n /** Leading slot (e.g. an `<AppIcon />` or status glyph). */\n icon?: ReactNode;\n /**\n * Trailing slot pushed to the right (e.g. a badge or chevron). With `href` it sits INSIDE the\n * anchor, so it must stay non-interactive (no buttons or links).\n */\n trailing?: ReactNode;\n /** Highlights the row as selected/current. Reflected as `aria-pressed` when clickable. */\n active?: boolean;\n /**\n * When provided, the row renders as a focusable, keyboard-activatable button — or, with `href`,\n * still fires on a click of the anchor. Receives the click event; ListItem never calls\n * `preventDefault`, so the host decides whether the browser navigates.\n */\n onClick?: (event: MouseEvent<HTMLElement>) => void;\n /** When provided, the row renders as a real `<a href>` (middle-click, copy link, new tab). */\n href?: string;\n /** Accessible label for the clickable row (falls back to the `title` DOM text). */\n ariaLabel?: string;\n}\n\n/**\n * A clean, reusable list row: leading icon · title over subtitle · trailing slot.\n *\n * Mirrors the look/behaviour of the saved-test button rows it replaces. When\n * `onClick` is given it renders a `<button type=\"button\">` (focusable, Enter/Space\n * activatable) with `aria-pressed={active}`; with `href` an `<a href>` (the click still reaches\n * `onClick`); otherwise a plain, non-interactive row.\n */\nexport function ListItem({\n title,\n subtitle,\n icon,\n trailing,\n active = false,\n onClick,\n href,\n ariaLabel,\n}: ListItemProps) {\n const body = (\n <>\n {icon != null && <span className=\"w6w-list-item-icon\">{icon}</span>}\n <span className=\"w6w-list-item-body\">\n <span className=\"w6w-list-item-title\">{title}</span>\n {subtitle != null && <span className=\"w6w-list-item-subtitle\">{subtitle}</span>}\n </span>\n {trailing != null && <span className=\"w6w-list-item-trailing\">{trailing}</span>}\n </>\n );\n\n const className = `w6w-list-item${active ? \" active\" : \"\"}`;\n\n if (href !== undefined) {\n return (\n <a\n className={className}\n href={href}\n aria-current={active ? \"true\" : undefined}\n aria-label={ariaLabel}\n onClick={onClick}\n >\n {body}\n </a>\n );\n }\n\n if (onClick) {\n return (\n <button\n type=\"button\"\n className={className}\n aria-pressed={active}\n aria-label={ariaLabel}\n onClick={onClick}\n >\n {body}\n </button>\n );\n }\n\n return (\n <div className={className} aria-label={ariaLabel}>\n {body}\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { JsonEditor } from \"./JsonEditor.tsx\";\nimport { ParamsForm } from \"./ParamsForm.tsx\";\nimport { ApiCallsPanel } from \"./components/ApiCallsPanel.tsx\";\nimport { Combobox } from \"./components/Combobox.tsx\";\nimport { ConfirmModal } from \"./components/ConfirmModal.tsx\";\nimport { ListItem } from \"./components/ListItem.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport { ResultViewer } from \"./components/ResultViewer.tsx\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport type { RequestOverrides, TestRunSummary } from \"./provider.tsx\";\nimport type { ActionDef, ApiCallRecord, SavedTest, ThemeMode } from \"./types.ts\";\n\nexport interface ActionTestFormProps {\n /** App the action belongs to. */\n appId: string;\n /** The app's actions — the caller already has them from the app detail. */\n actions: ActionDef[];\n /** Fixed connection to run against; its credential is resolved server-side. */\n connectionId?: string;\n /**\n * Pre-selected action (controlled). When provided the built-in action\n * `<select>` is hidden — the caller is already driving the selection.\n */\n action?: ActionDef | null;\n /** Theme hint, accepted for parity with other ui-lib components. */\n theme?: ThemeMode;\n /**\n * Studio-integration seam: when provided (and its reference changes) the\n * current action's params are seeded from a shallow copy of this object, so a\n * host page can \"open\" a saved test pre-filled. The stored object is never\n * mutated; a subsequent user edit is free to diverge. Optional — existing\n * consumers keep compiling.\n */\n seedValues?: Record<string, unknown> | null;\n /**\n * Studio-integration seam: fired after a successful saved-test create/delete\n * so the host page can invalidate its own `[\"saved-tests\", connId]` query.\n * The modal rail still refreshes its own list independently. Optional.\n */\n onSavedTestsChanged?: () => void;\n /**\n * Studio-integration seam (URL-driven host): the id of the saved test being\n * edited, from a studio deep link (`…/test/:testId`). When it changes to a\n * non-null id it is adopted as the current `editingTestId` — so the bottom Save\n * PATCHes that row and the Delete button shows; when null the tester is a\n * fresh/unsaved test. Optional — existing consumers keep compiling.\n */\n seedTestId?: string | null;\n /**\n * Studio-integration seam: fired whenever the current `values` diverge from\n * (or return to) the seeded baseline. This is the unsaved-changes signal the\n * studio host gates modal-close on (its ConfirmModal prompt). Optional.\n */\n onDirtyChange?: (dirty: boolean) => void;\n /**\n * Studio-integration seam: fired after a successful save (POST create or PATCH\n * update) with the resulting `SavedTest`, so the host can sync the URL\n * (`…/test/:id`) and clear its own dirty state. Optional.\n */\n onTestSaved?: (test: SavedTest) => void;\n /**\n * Studio-integration seam: fired after a successful delete of the saved test\n * currently being edited, with the deleted id, so the host can navigate away\n * from a now-dead `…/test/:id` URL. Optional — existing consumers keep compiling.\n */\n onDeleted?: (testId: string) => void;\n /**\n * Host-embedded mode. When `true` the caller already renders this widget inside\n * its own modal (studio's `ConnectionTesterModal`), so the widget suppresses its\n * OWN `<Modal>` + pop-out (⤢) toggle and instead fills the host container as a\n * full-height flex column: the params + saved-tests region scrolls and the\n * action bar is pinned to the bottom. Default `false` — non-embedded (inline /\n * own pop-out) usages are unchanged.\n */\n embedded?: boolean;\n}\n\n/**\n * Minimal relative-time label (\"just now\", \"5m ago\", \"3h ago\", \"2d ago\", or a\n * date for anything older) from an ISO timestamp. Kept inline — no formatter is\n * imported here — and only used for the saved-tests rail subtitle.\n */\nfunction relativeTime(iso: string): string {\n const then = Date.parse(iso);\n if (Number.isNaN(then)) return \"\";\n const secs = Math.max(0, Math.round((Date.now() - then) / 1000));\n if (secs < 45) return \"just now\";\n const mins = Math.round(secs / 60);\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.round(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.round(hours / 24);\n if (days < 7) return `${days}d ago`;\n return new Date(then).toLocaleDateString();\n}\n\n/** Pull default values out of declared params so the form starts populated. */\nfunction defaultParamsFor(action: ActionDef | null | undefined): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const p of action?.params ?? []) {\n if (p.key && p.default !== undefined) out[p.key] = p.default;\n }\n return out;\n}\n\n/** A rendered action error: a plain-language headline, an optional fix hint, and the raw provider detail. */\ninterface InvokeError {\n headline: string;\n hint?: string;\n detail?: string;\n}\n\n/**\n * Pull the provider's own human-readable message out of a raw error string. App\n * actions often throw like `SendGrid list index returned 403: {\"errors\":[{\"message\":\"…\"}]}`\n * — parse the trailing JSON and surface just the human message, keeping the\n * `\"<App> … returned <status>\"` prefix.\n */\nfunction extractProviderMessage(msg: string): string {\n const brace = msg.indexOf(\"{\");\n if (brace >= 0) {\n try {\n const j = JSON.parse(msg.slice(brace)) as {\n errors?: { message?: string }[];\n error?: { message?: string } | string;\n message?: string;\n };\n const m =\n j?.errors?.[0]?.message ??\n (typeof j?.error === \"object\" ? j.error?.message : j?.error) ??\n j?.message;\n if (typeof m === \"string\" && m.trim()) {\n const prefix = msg.slice(0, brace).replace(/[:\\s]+$/, \"\");\n return prefix ? `${prefix}: ${m.trim()}` : m.trim();\n }\n } catch {\n // Not JSON — fall through and return the message as-is.\n }\n }\n return msg;\n}\n\n/**\n * A failed-invoke error shape, matched by field rather than class identity —\n * ui's own `ApiError` and `@w6w/sdk`'s are two different classes across the\n * package boundary, and `status`+`code` is what both actually carry.\n * Considered mirroring `packages/wrappers/cli/src/exit.ts:60-63`'s `name ===\n * \"ApiError\"` fallback; not adopted — that solves module DUPLICATION of one\n * class, while ui's problem is cross-package IDENTITY, which `status`+`code`\n * already settles.\n */\nfunction isInvokeApiError(\n e: unknown,\n): e is { status: number; code: string; message?: string; body?: unknown; raw?: unknown } {\n return (\n typeof e === \"object\" &&\n e !== null &&\n typeof (e as { status: unknown }).status === \"number\" &&\n typeof (e as { code: unknown }).code === \"string\"\n );\n}\n\n/**\n * Turn a thrown invoke error into a user-facing message. A permission/credential\n * failure at the underlying provider (HTTP 401/403, or the message mentions\n * scopes/forbidden/unauthorized) is stated plainly with what to fix, so the user\n * isn't left staring at a raw upstream JSON blob.\n */\nfunction describeInvokeError(e: unknown): InvokeError {\n if (!isInvokeApiError(e)) {\n return { headline: (e as Error)?.message ?? \"The action failed to run.\" };\n }\n const detail = extractProviderMessage(e.message ?? \"\");\n const haystack = `${e.status} ${e.code} ${e.message ?? \"\"}`.toLowerCase();\n const isPermission =\n e.status === 401 ||\n e.status === 403 ||\n /\\b(401|403)\\b|forbidden|unauthorized|not authorized|permission|scope|access denied|invalid api key|invalid credential/.test(\n haystack,\n );\n if (isPermission) {\n return {\n headline:\n \"Permission denied by the provider — this is a credential/scope problem, not a w6w error.\",\n hint:\n \"The connection's API key is missing the permissions this action needs. Fix it at the \" +\n \"provider — e.g. SendGrid → Settings → API Keys → give the key the required scopes (or Full \" +\n \"Access), or create a new key — then update this connection's credential and try again.\",\n detail,\n };\n }\n return { headline: \"The action returned an error.\", detail };\n}\n\n/**\n * The captured outbound calls the server attached to a failed invoke — ui's\n * own `ApiError` carries them on `body`, `@w6w/sdk`'s on `raw`; read `body ??\n * raw` so either shape's calls surface.\n */\nfunction apiCallsOf(e: unknown): ApiCallRecord[] {\n const source = isInvokeApiError(e)\n ? ((e.body ?? e.raw) as { apiCalls?: ApiCallRecord[] } | null)\n : null;\n return source?.apiCalls ?? [];\n}\n\n/**\n * One Overrides sub-editor's local state (`body`/`query`/`headers`): raw text\n * (the widget's source of truth), the last value that parsed as a plain JSON\n * object, and whether the CURRENT text is invalid. Empty/whitespace text is\n * always valid and means \"not set\" — never blocks Run — matching the\n * requirement that clearing a field returns to \"no override\", not an error.\n *\n * Deliberately re-parses on every keystroke here rather than wiring\n * `JsonEditor`'s own `onValidChange`/`onValidityChange`: that pair reports an\n * emptied field as `{valid: false, error: \"Empty\"}`, which would wrongly keep\n * Run refusing the moment a touched field is cleared back out.\n */\nfunction useOverrideJsonField() {\n const [text, setText] = useState(\"\");\n const [value, setValue] = useState<Record<string, unknown> | undefined>(undefined);\n const [invalid, setInvalid] = useState(false);\n const onChange = (next: string) => {\n setText(next);\n const trimmed = next.trim();\n if (trimmed === \"\") {\n setInvalid(false);\n return;\n }\n try {\n const parsed = JSON.parse(trimmed);\n if (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n setValue(parsed as Record<string, unknown>);\n setInvalid(false);\n } else {\n setInvalid(true);\n }\n } catch {\n setInvalid(true);\n }\n };\n return { text, value, invalid, onChange } as const;\n}\n\n/**\n * Schema-driven form to test/run a single action against a connection. Renders\n * the action's declared params through {@link ParamsForm} (the same primitive\n * the step builder uses) instead of a raw JSON textarea, invokes the action via\n * `useW6WApi().invokeAction`, and shows the returned value or error.\n *\n * The selected action is either controlled by the caller (`action` prop) or\n * chosen from a built-in `<select>` over `actions`. Param values reset whenever\n * the selected action changes.\n */\nexport function ActionTestForm({\n appId,\n actions,\n connectionId,\n action,\n seedValues,\n onSavedTestsChanged,\n seedTestId,\n onDirtyChange,\n onTestSaved,\n onDeleted,\n embedded = false,\n}: ActionTestFormProps) {\n const api = useW6WApi();\n\n // Actions sorted for the built-in picker (only used when uncontrolled).\n const sortedActions = useMemo(() => {\n const list = [...actions];\n list.sort((a, b) => (a.title || a.key).localeCompare(b.title || b.key));\n return list;\n }, [actions]);\n\n // Internal selection, used only when the caller doesn't control `action`.\n const [pickedKey, setPickedKey] = useState<string>(action?.key ?? \"\");\n const selectedAction: ActionDef | null =\n action ?? actions.find((a) => a.key === pickedKey) ?? null;\n\n const [running, setRunning] = useState(false);\n const [error, setError] = useState<InvokeError | null>(null);\n const [result, setResult] = useState<unknown>(undefined);\n // The outbound HTTP calls the last run made (redacted request + response).\n // Populated on success AND failure — a wrong payload is usually only visible\n // on the wire, not in the value.\n const [apiCalls, setApiCalls] = useState<ApiCallRecord[]>([]);\n\n // Overrides region (T2.1.1): a RequestOverrides envelope submitted as a\n // fourth field alongside params — architecturally NOT a Param (it never\n // enters `resolveParams`), so it is a SIBLING region to `paramsRegion`\n // rather than a slot inside `ParamsForm`'s \"Additional parameters\"\n // disclosure. See `.claude/docs/overrides.md`.\n const ovBody = useOverrideJsonField();\n const ovQuery = useOverrideJsonField();\n const ovHeaders = useOverrideJsonField();\n const [ovTarget, setOvTarget] = useState<\"\" | \"first\" | \"first-write\" | \"all\">(\"\");\n const [ovMatch, setOvMatch] = useState(\"\");\n // Any sub-editor currently holding invalid JSON blocks the run outright —\n // never send a half-parsed envelope.\n const overridesInvalid = ovBody.invalid || ovQuery.invalid || ovHeaders.invalid;\n // Built fresh from current state on every call — an untouched (or cleared)\n // control leaves every field empty, so this returns `undefined` and the run\n // sends no `overrides` key at all: byte-identical to a request from before\n // this control existed.\n const currentOverrides = (): RequestOverrides | undefined => {\n const out: RequestOverrides = {};\n if (ovBody.text.trim() !== \"\" && ovBody.value !== undefined) out.body = ovBody.value;\n if (ovQuery.text.trim() !== \"\" && ovQuery.value !== undefined) {\n out.query = ovQuery.value as Record<string, string | number | boolean | null>;\n }\n if (ovHeaders.text.trim() !== \"\" && ovHeaders.value !== undefined) {\n out.headers = ovHeaders.value as Record<string, string>;\n }\n if (ovTarget) out.target = ovTarget;\n if (ovMatch.trim() !== \"\") out.match = ovMatch.trim();\n return Object.keys(out).length > 0 ? out : undefined;\n };\n\n // Params view: the schema-driven form, or the whole `values` object as raw JSON.\n const [viewMode, setViewMode] = useState<\"form\" | \"json\">(\"form\");\n const [jsonText, setJsonText] = useState(\"\");\n const [jsonInvalid, setJsonInvalid] = useState(false);\n\n // Pop-out: when open, the params region moves into a larger `Modal` canvas.\n // It is the SAME region bound to the SAME `values`/`setValues`, just relocated,\n // so edits stay in sync with the inline view.\n const [modalOpen, setModalOpen] = useState(false);\n\n // Param values, re-seeded from defaults whenever the selected action changes.\n // On a FRESH MOUNT with `seedValues` present (e.g. a deep-linked saved test),\n // seed from a shallow copy of it rather than defaults — otherwise the seed guard\n // below never fires on first render (`lastSeed` inits to the same ref) and the\n // seeded values are dropped.\n const selectedKey = selectedAction?.key ?? null;\n const initialValues = seedValues ? { ...seedValues } : defaultParamsFor(selectedAction);\n const [valuesByAction, setValuesByAction] = useState<{\n key: string | null;\n values: Record<string, unknown>;\n }>(() => ({\n key: selectedKey,\n values: initialValues,\n }));\n\n // The id of the saved test currently being edited, or `null` for an unsaved\n // test. Drives the PATCH-vs-POST decision in `submitSaveTest`: a set id updates\n // that row in place, `null` creates a new named row. Seeded from `seedTestId`\n // so a studio deep link (`…/test/:testId`) mounts already in edit mode.\n const [editingTestId, setEditingTestId] = useState<string | null>(seedTestId ?? null);\n\n // Dirty baseline: the values as last seeded/loaded/saved. `values` is compared\n // against this to derive the host-facing `dirty` signal (`onDirtyChange`). Reset\n // wherever a fresh set of values is adopted (action change, seed, load, save).\n const [baseline, setBaseline] = useState<Record<string, unknown>>(initialValues);\n\n if (valuesByAction.key !== selectedKey) {\n // Selection changed (controlled or via the picker, without a remount) — reset the\n // form values AND clear any stale result/error carried over from the previously\n // selected action (a 403 from `list-get` must not linger while `mail-send` shows).\n // Editing id: a genuine action-switch starts a fresh unsaved test (→ null), BUT a\n // deep-link whose action arrives AFTER mount is NOT an action-switch — the selected\n // action IS the seeded test's action. A truthy `seedTestId` therefore wins here, so\n // the late null→key transition keeps `editingTestId === seedTestId` (Save PATCHes,\n // Delete shows) instead of clobbering it to null and POSTing a duplicate row.\n const fresh = defaultParamsFor(selectedAction);\n setValuesByAction({ key: selectedKey, values: fresh });\n setBaseline(fresh);\n setEditingTestId(seedTestId ?? null);\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n }\n\n // Studio seam: adopt a deep-linked saved-test id. When `seedTestId` changes to a\n // non-null id, make it the current editing id (bottom Save PATCHes, Delete\n // shows); a change to null returns the tester to a fresh/unsaved test.\n const [lastSeedTestId, setLastSeedTestId] = useState<string | null | undefined>(seedTestId);\n if (seedTestId !== lastSeedTestId) {\n setLastSeedTestId(seedTestId);\n setEditingTestId(seedTestId ?? null);\n }\n\n // Studio seam: when a new `seedValues` reference arrives (e.g. \"open a saved\n // test\"), seed the current action's params from a SHALLOW COPY of it. Applied\n // as a render-phase guard like the action-change reseed above; the passed\n // object is never mutated and later edits are free to diverge.\n const [lastSeed, setLastSeed] = useState<Record<string, unknown> | null | undefined>(seedValues);\n if (seedValues !== lastSeed) {\n // Content-aware, not reference-keyed: a `[\"saved-tests\"]` invalidation (fired by\n // onTestSaved/onSavedTestsChanged after a Save) hands back a fresh OBJECT with the\n // SAME content — that must NOT reseed the draft or clear the on-screen Run\n // result/error. Reseed only when the incoming values differ STRUCTURALLY from the\n // last applied seed. `lastSeed` advances to the new ref regardless, so we don't\n // re-compare the same pair every render.\n const structurallyChanged =\n JSON.stringify(seedValues ?? null) !== JSON.stringify(lastSeed ?? null);\n setLastSeed(seedValues);\n if (seedValues && structurallyChanged) {\n const seeded = { ...seedValues };\n setValuesByAction({ key: selectedKey, values: seeded });\n setBaseline(seeded);\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n }\n }\n\n const values = valuesByAction.values;\n const setValues = (next: Record<string, unknown>) =>\n setValuesByAction({ key: selectedKey, values: next });\n\n // Host-facing dirty signal: do the current values diverge from the seeded\n // baseline? Compared by structural JSON so a load→edit→revert cycle clears it.\n const dirty = useMemo(\n () => JSON.stringify(values) !== JSON.stringify(baseline),\n [values, baseline],\n );\n // biome-ignore lint/correctness/useExhaustiveDependencies: fire only when `dirty` flips, not on every `onDirtyChange` identity change.\n useEffect(() => {\n onDirtyChange?.(dirty);\n }, [dirty]);\n\n // Entering the JSON view seeds the editor from the current values; edits that\n // parse to a plain object round-trip straight back into `values`.\n const enterJsonView = () => {\n setJsonText(JSON.stringify(values, null, 2));\n setJsonInvalid(false);\n setViewMode(\"json\");\n };\n\n // The single invoke path — used by \"Run action\" and by re-running a saved test.\n const runWith = async (params: Record<string, unknown>) => {\n if (!selectedAction) return;\n // An invalid Overrides sub-editor refuses the run outright — the Run\n // button is also disabled for this, but guard here too so a saved-test\n // re-run (which bypasses the button) can't slip a half-parsed envelope\n // through either.\n if (overridesInvalid) return;\n const actionKey = selectedAction.key;\n setRunning(true);\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n let outcome: { ok: boolean; summary: string; result?: unknown };\n const overrides = currentOverrides();\n try {\n const r = await api.invokeAction(appId, actionKey, params, {\n connectionId,\n ...(overrides ? { overrides } : {}),\n });\n setResult(r.value);\n setApiCalls(r.apiCalls ?? []);\n outcome = { ok: true, summary: \"OK\", result: r.value };\n } catch (e) {\n const err = describeInvokeError(e);\n setError(err);\n // The server returns the captured calls on the error body too — the\n // request that failed is the thing worth looking at.\n setApiCalls(apiCallsOf(e));\n outcome = { ok: false, summary: err.headline };\n } finally {\n setRunning(false);\n }\n // Log every run (success or failure) against the connection, and update the\n // saved test's last-run when this run came from an editing session. Best\n // effort — a logging failure must not mask the run's own result.\n if (connectionId) {\n try {\n await api.recordTestRun(connectionId, {\n savedTestId: editingTestId ?? null,\n actionKey,\n ok: outcome.ok,\n summary: outcome.summary.slice(0, 200),\n result: outcome.result,\n });\n refreshSavedTests();\n refreshRunHistory();\n onSavedTestsChanged?.();\n } catch {\n // Ignore — the run itself already surfaced via result/error.\n }\n }\n };\n const run = () => runWith(values);\n\n // Saved tests for this connection. `nonce` re-triggers the fetch after a\n // create/delete so the rail reflects the change without a full remount.\n const [savedTests, setSavedTests] = useState<SavedTest[] | null>(null);\n const [savedTestsError, setSavedTestsError] = useState<string | null>(null);\n const [savedTestsNonce, setSavedTestsNonce] = useState(0);\n // Name-a-saved-test dialog (in-app Modal — never the browser's prompt()).\n const [nameModalOpen, setNameModalOpen] = useState(false);\n const [pendingName, setPendingName] = useState(\"\");\n // Delete-confirm dialog (in-app ConfirmModal — never the browser's confirm()).\n const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);\n const refreshSavedTests = () => setSavedTestsNonce((n) => n + 1);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `savedTestsNonce` is a deliberate re-fetch trigger, not read inside the effect.\n useEffect(() => {\n if (!connectionId) {\n setSavedTests(null);\n return;\n }\n let canceled = false;\n setSavedTestsError(null);\n api\n .listSavedTests(connectionId)\n .then((list) => !canceled && setSavedTests(list))\n .catch((e) => !canceled && setSavedTestsError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, connectionId, savedTestsNonce]);\n\n // Only this action's saved tests belong on the rail.\n const railTests = selectedKey\n ? (savedTests ?? []).filter((t) => t.actionKey === selectedKey)\n : [];\n\n // Connection run history from the unified `run_log` ledger (F-1). Complements\n // the per-saved-test `lastRun*` badge with the full recent-run list. Fetched\n // via the OPTIONAL `api.listTestRuns` — a consumer that doesn't implement it\n // (studio, until T2.2.2) simply shows no history. `runHistoryNonce` re-triggers\n // the fetch after a run is recorded so the list stays current.\n const [runHistory, setRunHistory] = useState<TestRunSummary[] | null>(null);\n const [runHistoryNonce, setRunHistoryNonce] = useState(0);\n const refreshRunHistory = () => setRunHistoryNonce((n) => n + 1);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `runHistoryNonce` is a deliberate re-fetch trigger, not read inside the effect.\n useEffect(() => {\n const load = api.listTestRuns;\n if (!connectionId || !load) {\n setRunHistory(null);\n return;\n }\n let canceled = false;\n load(connectionId)\n .then((list) => !canceled && setRunHistory(list))\n // Best-effort: a history load failure must never break the tester.\n .catch(() => !canceled && setRunHistory(null));\n return () => {\n canceled = true;\n };\n }, [api, connectionId, runHistoryNonce]);\n\n // History rows for the current action (mirrors the saved-tests rail filter),\n // most-recent first — the server orders newest-first but we don't rely on it.\n const railRunHistory = selectedKey\n ? (runHistory ?? [])\n .filter((r) => r.actionKey === selectedKey)\n .slice()\n .sort((a, b) => Date.parse(b.occurredAt) - Date.parse(a.occurredAt))\n : [];\n\n // Open the in-app name dialog to save the current params as a NEW named test.\n const openSaveModal = () => {\n if (!connectionId || !selectedAction) return;\n setPendingName(\"\");\n setSavedTestsError(null);\n setNameModalOpen(true);\n };\n // Bottom Save affordance. When a saved test is loaded for editing\n // (`editingTestId` set) the save is a silent PATCH — no throwaway name dialog\n // (FU-1). With no editing id, open the name dialog to create a new named row.\n const handleSaveClick = () => {\n if (!connectionId || !selectedAction) return;\n if (editingTestId) {\n void submitSaveTest();\n } else {\n openSaveModal();\n }\n };\n // Persist the current params. When a saved test is loaded for editing\n // (`editingTestId` set), PATCH that row in place — updating only `values` keeps\n // its name and sidesteps the 409 duplicate-name guard a re-POST would trip.\n // With no editing id, create a new named row from the dialog and remember its\n // id so the next save updates in place rather than spawning a second row.\n const submitSaveTest = async () => {\n if (!connectionId || !selectedAction) return;\n try {\n let saved: SavedTest;\n if (editingTestId) {\n saved = await api.updateSavedTest(connectionId, editingTestId, { values });\n } else {\n const name = pendingName.trim();\n if (!name) return;\n saved = await api.createSavedTest(connectionId, {\n actionKey: selectedAction.key,\n name,\n values,\n });\n setEditingTestId(saved.id);\n }\n // The just-saved values are the new clean baseline (dirty → false).\n setBaseline({ ...values });\n setNameModalOpen(false);\n setPendingName(\"\");\n refreshSavedTests();\n onSavedTestsChanged?.();\n onTestSaved?.(saved);\n } catch (e) {\n setSavedTestsError((e as Error).message);\n }\n };\n\n // Load a saved test's values into the form (shallow copy — never mutate the\n // stored row). Clicking a saved test's name loads it for editing: values +\n // editing id are adopted and the load becomes the new clean baseline.\n const loadSavedTest = (t: SavedTest) => {\n const loaded = { ...t.values };\n setValuesByAction({ key: selectedKey, values: loaded });\n setBaseline(loaded);\n // Remember which row is being edited so a subsequent save PATCHes it in place.\n setEditingTestId(t.id);\n setViewMode(\"form\");\n setError(null);\n setResult(undefined);\n setApiCalls([]);\n };\n // Delete the saved test currently being edited (Delete only shows with an\n // editing id set). Clears the editing id so the form drops to unsaved state.\n const deleteCurrentTest = async () => {\n if (!connectionId || !editingTestId) return;\n const deletedId = editingTestId;\n try {\n await api.deleteSavedTest(connectionId, deletedId);\n setEditingTestId(null);\n refreshSavedTests();\n onSavedTestsChanged?.();\n // Host hook: let the URL-driven host (studio's ConnectionTesterModal) navigate\n // away from the now-dead `…/test/:deletedId` deep link.\n onDeleted?.(deletedId);\n } catch (e) {\n setSavedTestsError((e as Error).message);\n }\n };\n\n // The params region: the form↔JSON toggle plus the ParamsForm/JsonEditor block.\n // Rendered in exactly one place at a time — inline when the pop-out is closed,\n // inside the `Modal` when it's open — so there's a single instance bound to the\n // single `values`/`setValues` state (no copy-on-open, edits stay in sync).\n const paramsRegion = (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-1-5)\" }}>\n <div\n className=\"w6w-field-labelrow\"\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}\n >\n <span className=\"w6w-muted w6w-small\">Parameters</span>\n <div style={{ display: \"flex\", gap: \"var(--w6w-sp-1)\" }}>\n <button\n type=\"button\"\n className={`w6w-btn w6w-btn-sm w6w-btn-ghost${viewMode === \"form\" ? \" active\" : \"\"}`}\n aria-pressed={viewMode === \"form\"}\n onClick={() => setViewMode(\"form\")}\n >\n Form\n </button>\n <button\n type=\"button\"\n className={`w6w-btn w6w-btn-sm w6w-btn-ghost${viewMode === \"json\" ? \" active\" : \"\"}`}\n aria-pressed={viewMode === \"json\"}\n onClick={enterJsonView}\n >\n JSON\n </button>\n {/* Pop-out toggle — suppressed in embedded mode: the host already\n provides full-screen modal chrome, so a modal-in-modal ⤢ is redundant. */}\n {!embedded && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-sm w6w-btn-ghost\"\n aria-pressed={modalOpen}\n title={\n modalOpen ? \"Collapse the params editor\" : \"Open the params editor in a larger view\"\n }\n aria-label={\n modalOpen ? \"Collapse the params editor\" : \"Open the params editor in a larger view\"\n }\n onClick={() => setModalOpen((v) => !v)}\n >\n {modalOpen ? \"⤡\" : \"⤢\"}\n </button>\n )}\n </div>\n </div>\n\n {viewMode === \"form\" ? (\n <ParamsForm\n params={selectedAction?.params ?? []}\n values={values}\n onChange={setValues}\n dynamic={\n selectedAction ? { appId, actionKey: selectedAction.key, connectionId } : undefined\n }\n />\n ) : (\n <>\n <JsonEditor\n value={jsonText}\n onChange={setJsonText}\n minHeight={modalOpen ? \"50vh\" : \"200px\"}\n aria-label=\"Params JSON\"\n onValidChange={(parsed) => {\n // Only a JSON object maps onto the params `values` record; ignore a\n // bare array/scalar so `values` stays a plain key→value object.\n if (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n setValues(parsed as Record<string, unknown>);\n }\n }}\n onValidityChange={({ valid }) => setJsonInvalid(!valid)}\n />\n {jsonInvalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </>\n )}\n </div>\n );\n\n // The Overrides region: a sibling to `paramsRegion`, never nested inside it\n // (and never inside `ParamsForm`'s own \"Additional parameters\" disclosure —\n // `overrides` is not a Param). Collapsed by default via `<details>`, reusing\n // the same `.w6w-section` disclosure `SectionField` renders for a\n // `section: \"collapsible\"` param, since this is the identical visual shape\n // (titled, collapsed-by-default disclosure) applied to a hand-built control\n // instead of a schema-driven one.\n const overridesRegion = (\n <details className=\"w6w-section\" data-testid=\"overrides-region\">\n <summary className=\"w6w-section-summary\">\n <span className=\"w6w-section-title\">Overrides</span>\n <span className=\"w6w-section-subtitle\">\n Reach a vendor field this action's own params don't declare\n </span>\n </summary>\n <div className=\"w6w-stack w6w-section-body\" style={{ gap: \"var(--w6w-sp-2)\" }}>\n <div className=\"w6w-field\">\n <span>Body</span>\n <JsonEditor\n value={ovBody.text}\n onChange={ovBody.onChange}\n minHeight=\"80px\"\n aria-label=\"Overrides body (JSON)\"\n />\n {ovBody.invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </div>\n <div className=\"w6w-field\">\n <span>Query</span>\n <JsonEditor\n value={ovQuery.text}\n onChange={ovQuery.onChange}\n minHeight=\"80px\"\n aria-label=\"Overrides query (JSON)\"\n />\n {ovQuery.invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </div>\n <div className=\"w6w-field\">\n <span>Headers</span>\n <JsonEditor\n value={ovHeaders.text}\n onChange={ovHeaders.onChange}\n minHeight=\"80px\"\n aria-label=\"Overrides headers (JSON)\"\n />\n {ovHeaders.invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </div>\n <label className=\"w6w-field\">\n <span>Target</span>\n <select\n aria-label=\"Overrides target\"\n value={ovTarget}\n onChange={(e) => setOvTarget(e.target.value as typeof ovTarget)}\n >\n <option value=\"\">— default (first) —</option>\n <option value=\"first\">first</option>\n <option value=\"first-write\">first-write</option>\n <option value=\"all\">all</option>\n </select>\n </label>\n <label className=\"w6w-field\">\n <span>Match</span>\n <input\n type=\"text\"\n aria-label=\"Overrides match\"\n value={ovMatch}\n placeholder=\"Restrict to requests whose URL contains…\"\n onChange={(e) => setOvMatch(e.target.value)}\n />\n </label>\n <span className=\"w6w-hint\">\n Merged onto the outbound request at the wire, never into the params above — name a field\n the way the vendor's own API documents it.\n </span>\n </div>\n </details>\n );\n\n // The saved-tests rail — the right pane of the pop-out. Only meaningful when a\n // connection is fixed; hidden entirely otherwise (guarded on `connectionId`).\n const savedTestsRail = connectionId ? (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-1-5)\" }}>\n <div\n className=\"w6w-field-labelrow\"\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}\n >\n <span className=\"w6w-muted w6w-small\">Saved tests</span>\n </div>\n {savedTestsError && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n {savedTestsError}\n </span>\n )}\n {railTests.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">No saved tests for this action yet.</p>\n ) : (\n <ul\n className=\"w6w-stack\"\n style={{ listStyle: \"none\", margin: 0, padding: 0, gap: \"var(--w6w-sp-1-5)\" }}\n >\n {railTests.map((t) => (\n <li key={t.id}>\n {/* Clicking a saved test loads it for editing — no per-row\n Load/Run/Delete buttons; those actions live at the modal bottom.\n Subtitle shows the last run (✓/✗ + relative time), falling back\n to the last-saved time when the test has never been run. */}\n <ListItem\n title={t.name}\n subtitle={\n t.lastRunAt ? (\n <span>\n <span\n style={{ color: t.lastRunOk ? \"var(--w6w-success)\" : \"var(--w6w-danger)\" }}\n >\n {t.lastRunOk ? \"✓\" : \"✗\"}\n </span>{\" \"}\n {t.lastRunSummary ? `${t.lastRunSummary} · ` : \"\"}\n {relativeTime(t.lastRunAt)}\n </span>\n ) : (\n `saved ${relativeTime(t.updatedAt)}`\n )\n }\n active={t.id === editingTestId}\n onClick={() => loadSavedTest(t)}\n />\n </li>\n ))}\n </ul>\n )}\n\n {/* Run history (F-1): the connection's recent tester runs for this action,\n from the unified `run_log` ledger. Read-only rows (no onClick) — this is\n a log, not a loadable input like the saved tests above. Only rendered\n when the api exposes `listTestRuns` (optional member) and there is\n history to show, so a consumer without it degrades to no section. */}\n {api.listTestRuns && railRunHistory.length > 0 && (\n <>\n <div\n className=\"w6w-field-labelrow\"\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}\n >\n <span className=\"w6w-muted w6w-small\">Recent runs</span>\n </div>\n <ul\n className=\"w6w-stack\"\n style={{ listStyle: \"none\", margin: 0, padding: 0, gap: \"var(--w6w-sp-1-5)\" }}\n >\n {railRunHistory.map((r) => (\n <li key={r.id}>\n <ListItem\n title={\n <span>\n <span style={{ color: r.ok ? \"var(--w6w-success)\" : \"var(--w6w-danger)\" }}>\n {r.ok ? \"✓\" : \"✗\"}\n </span>{\" \"}\n {r.actionKey}\n </span>\n }\n subtitle={\n <span>\n {r.summary ? `${r.summary} · ` : \"\"}\n {relativeTime(r.occurredAt)}\n </span>\n }\n />\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n ) : null;\n\n // Nullable: `editingTestId` can be seeded from a studio deep link before\n // `savedTests` itself has finished fetching, so this may not resolve yet.\n const deletingTestName = savedTests?.find((t) => t.id === editingTestId)?.name;\n\n return (\n <div className={`w6w-stack${embedded ? \" w6w-tester-embedded-root\" : \"\"}`}>\n {/* Action picker — only when the caller isn't controlling the selection. */}\n {!action &&\n (actions.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">This app exposes no actions.</p>\n ) : (\n // biome-ignore lint/a11y/noLabelWithoutControl: Combobox renders its own <select>/<input> INSIDE this label, so the field text labels the control at runtime; the rule cannot see through the component boundary.\n <label className=\"w6w-field\">\n <span>Action{selectedKey ? \"\" : \" *\"}</span>\n <Combobox\n value={pickedKey}\n placeholder=\"— pick an action —\"\n onChange={setPickedKey}\n options={sortedActions.map((a) => ({\n value: a.key,\n label: `${a.title ?? a.key} (${a.key})`,\n }))}\n />\n </label>\n ))}\n\n {selectedAction ? (\n <>\n <div>\n <strong>\n {selectedAction.title ?? selectedAction.key}{\" \"}\n <code className=\"w6w-muted\">{selectedAction.key}</code>\n </strong>\n {selectedAction.description && (\n <p className=\"w6w-muted w6w-small\" style={{ margin: \"var(--w6w-sp-0-5) 0 0\" }}>\n {selectedAction.description}\n </p>\n )}\n </div>\n\n {(() => {\n // The scrollable tester content: params editor + error + result. Shared\n // by every layout (inline body, pop-out modal, embedded footer layout)\n // so it stays a single instance bound to the single `values` state.\n const errorBox = error ? (\n <div className=\"w6w-result w6w-error\">\n <strong>{error.headline}</strong>\n {error.hint && <div style={{ marginTop: \"var(--w6w-sp-1-5)\" }}>{error.hint}</div>}\n {error.detail && (\n <div\n className=\"w6w-muted w6w-small\"\n style={{\n marginTop: \"var(--w6w-sp-1-5)\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n }}\n >\n {error.detail}\n </div>\n )}\n </div>\n ) : null;\n const resultBlock =\n result !== undefined ? (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-1)\" }}>\n <strong className=\"w6w-small\">Result</strong>\n <ResultViewer value={result} />\n </div>\n ) : null;\n const paramsAndResult = (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {paramsRegion}\n {overridesRegion}\n {errorBox}\n {resultBlock}\n <ApiCallsPanel calls={apiCalls} />\n </div>\n );\n // Bottom-anchored actions: Run / Save always; Delete only when an\n // editing id is set (an already-saved test is loaded). In embedded mode\n // this becomes a bottom-pinned footer outside the scroll region.\n const actionBar = (\n <div\n className={`w6w-tester-actions${\n embedded || modalOpen ? \" w6w-tester-actions-footer\" : \"\"\n }`}\n style={{ display: \"flex\", gap: \"var(--w6w-sp-2)\" }}\n >\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={running || overridesInvalid}\n onClick={run}\n >\n {running ? \"Running…\" : \"Run action\"}\n </button>\n {connectionId && (\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={handleSaveClick}>\n Save test\n </button>\n )}\n {connectionId && editingTestId && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n style={{ marginLeft: \"auto\", color: \"var(--w6w-danger)\" }}\n onClick={() => setConfirmDeleteOpen(true)}\n >\n Delete\n </button>\n )}\n </div>\n );\n // The tester body: params + result + actions, stacked. Rendered inline\n // when the pop-out modal is closed, and inside the pop-out modal (left\n // pane, saved-tests rail on the right) when open.\n const body = (\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {paramsAndResult}\n {actionBar}\n </div>\n );\n // Host-embedded: the host owns the modal chrome, so fill it as a\n // full-height flex column — params + saved-tests rail scroll, the action\n // bar is pinned to the bottom as a non-scrolling footer.\n if (embedded) {\n return (\n <div className=\"w6w-tester-embedded\">\n <div className=\"w6w-tester-embedded-scroll\">\n {/* Card layout: params, result and (with a connection) saved\n tests + history each in a `.card`, stacked in one column. */}\n <div className=\"w6w-card-stack\">\n <div className=\"card\">\n <div className=\"section-head\">\n <h3>Parameters</h3>\n </div>\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {paramsRegion}\n {overridesRegion}\n {errorBox}\n </div>\n </div>\n {(resultBlock || apiCalls.length > 0) && (\n <div className=\"card\">\n <div className=\"section-head\">\n <h3>Result</h3>\n </div>\n <div className=\"w6w-stack\" style={{ gap: \"var(--w6w-sp-3)\" }}>\n {result !== undefined && <ResultViewer value={result} />}\n <ApiCallsPanel calls={apiCalls} />\n </div>\n </div>\n )}\n {savedTestsRail && (\n <div className=\"card\">\n <div className=\"section-head\">\n <h3>Saved tests and history</h3>\n </div>\n {savedTestsRail}\n </div>\n )}\n </div>\n </div>\n {actionBar}\n </div>\n );\n }\n return modalOpen ? (\n <Modal\n title={`Edit params — ${selectedAction.title ?? selectedAction.key}`}\n onClose={() => setModalOpen(false)}\n size=\"full\"\n >\n {/* The pop-out's own internal scroll boundary (T1.4.1 round 2): with\n `-full`'s `overflow: hidden` live, the dialog itself no longer\n scrolls, so params + result (+ the saved-tests rail) get a\n dedicated scroll region here and the action bar stays a pinned\n footer below it — mirrors `.w6w-tester-embedded-scroll`'s\n mechanism (see styles.css), just for this own-pop-out layout\n instead of the host-embedded one. */}\n <div className=\"w6w-tester-popout\">\n <div className=\"w6w-tester-popout-scroll\">\n {savedTestsRail ? (\n <div\n style={{\n display: \"flex\",\n gap: \"var(--w6w-sp-4)\",\n alignItems: \"flex-start\",\n }}\n >\n <div style={{ flex: 1, minWidth: 0 }}>{paramsAndResult}</div>\n <div style={{ width: 260, flexShrink: 0 }}>{savedTestsRail}</div>\n </div>\n ) : (\n paramsAndResult\n )}\n </div>\n {actionBar}\n </div>\n </Modal>\n ) : (\n body\n );\n })()}\n\n {nameModalOpen && (\n <Modal title=\"Save test\" onClose={() => setNameModalOpen(false)}>\n <form\n className=\"w6w-stack\"\n style={{ gap: \"var(--w6w-sp-3)\" }}\n onSubmit={(e) => {\n e.preventDefault();\n void submitSaveTest();\n }}\n >\n <label className=\"w6w-field\">\n <span>Name this saved test</span>\n <input\n type=\"text\"\n value={pendingName}\n placeholder=\"e.g. valid sender\"\n onChange={(e) => setPendingName(e.target.value)}\n />\n </label>\n {savedTestsError && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n {savedTestsError}\n </span>\n )}\n <div\n style={{ display: \"flex\", gap: \"var(--w6w-sp-2)\", justifyContent: \"flex-end\" }}\n >\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setNameModalOpen(false)}\n >\n Cancel\n </button>\n <button type=\"submit\" className=\"w6w-btn\" disabled={!pendingName.trim()}>\n Save\n </button>\n </div>\n </form>\n </Modal>\n )}\n\n {confirmDeleteOpen && (\n <ConfirmModal\n title=\"Delete saved test\"\n message={\n deletingTestName\n ? `Delete \"${deletingTestName}\"? This cannot be undone.`\n : \"Delete this saved test? This cannot be undone.\"\n }\n confirmLabel=\"Delete\"\n onConfirm={() => {\n setConfirmDeleteOpen(false);\n void deleteCurrentTest();\n }}\n onClose={() => setConfirmDeleteOpen(false)}\n />\n )}\n </>\n ) : (\n !action && <p className=\"w6w-muted w6w-small\">Pick an action above to test it.</p>\n )}\n </div>\n );\n}\n","import { yaml } from \"@codemirror/lang-yaml\";\nimport { EditorView } from \"@codemirror/view\";\nimport CodeMirror from \"@uiw/react-codemirror\";\nimport { useMemo } from \"react\";\nimport { CheckGlyph, CopyGlyph } from \"./components/Copyable.tsx\";\nimport { useCopyToClipboard } from \"./components/use-copy.ts\";\nimport { EDITOR_THEME_SPEC } from \"./editor-theme.ts\";\nimport { useEffectiveTheme } from \"./theme.ts\";\nimport type { ThemeMode } from \"./types.ts\";\n\nexport interface YamlEditorProps {\n value: string;\n onChange: (value: string) => void;\n\n /** Placeholder text shown when value is empty. */\n placeholder?: string;\n /** Minimum editor height. Defaults to \"240px\". */\n minHeight?: string;\n /** Maximum editor height before scrolling. Defaults to no cap. */\n maxHeight?: string;\n /**\n * Explicit editor height. Pass `\"100%\"` to fill a flex parent (the whole-config\n * \"code\" view). Omit to let the editor grow with its content between\n * `minHeight` and `maxHeight` — an inline YAML/group field wants this.\n */\n height?: string;\n\n /** Read-only mode — useful for previewing a stored definition. */\n readOnly?: boolean;\n\n /**\n * Explicit theme. If omitted, the editor auto-detects `data-theme` on\n * `<html>` and falls back to `prefers-color-scheme` — same behavior as\n * `<AppIcon>`. Uses CodeMirror's built-in one-dark for dark mode.\n */\n theme?: ThemeMode;\n\n /** Accessible label for the editor. */\n \"aria-label\"?: string;\n\n /**\n * Render an in-box copy-to-clipboard button, a direct child of this\n * component's own `.w6w-yaml-editor` wrapper (sibling to the CodeMirror\n * mount — no extra DOM node). Copies the current `value` verbatim.\n *\n * On by default; disable only when the containing view supplies its own copy button.\n */\n copyable?: boolean;\n}\n\n/**\n * YAML editor built on CodeMirror 6. Syntax highlighting, folding, gutter,\n * and line numbers. Themed with the `--w6w-*` custom properties so it\n * inherits from the consumer's palette.\n *\n * ```tsx\n * <YamlEditor value={text} onChange={setText} minHeight=\"320px\" />\n * ```\n */\nexport function YamlEditor(props: YamlEditorProps) {\n const theme = useEffectiveTheme(props.theme);\n // Only mounted when `copyable` is on, but the hook itself must run\n // unconditionally (Rules of Hooks) — it is inert (no button, no listener)\n // until `copy()` is actually invoked from the button below.\n const { copied, copy } = useCopyToClipboard(props.value);\n const extensions = useMemo(() => [yaml(), EditorView.theme(EDITOR_THEME_SPEC)], []);\n\n function handleChange(next: string) {\n props.onChange(next);\n }\n\n return (\n <div className=\"w6w-yaml-editor\" aria-label={props[\"aria-label\"] ?? \"YAML editor\"}>\n <CodeMirror\n value={props.value}\n onChange={handleChange}\n extensions={extensions}\n placeholder={props.placeholder}\n readOnly={props.readOnly}\n // `readOnly` alone only blocks CodeMirror's own transactions\n // (`EditorState.readOnly`) — it leaves the content DOM\n // `contenteditable=\"true\"`, so a screen reader / a11y test still sees\n // it as an editable field. `editable` is the separate switch that\n // actually sets `contenteditable` (`EditorView.editable`); tying it to\n // `readOnly` here makes the prop mean what its name says.\n editable={!props.readOnly}\n theme={theme}\n height={props.height}\n minHeight={props.minHeight ?? \"240px\"}\n maxHeight={props.maxHeight}\n basicSetup={{\n lineNumbers: true,\n foldGutter: true,\n highlightActiveLine: !props.readOnly,\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n }}\n />\n {props.copyable !== false && (\n <>\n <button\n type=\"button\"\n className={`w6w-icon-btn w6w-copyable-btn${copied ? \" is-copied\" : \"\"}`}\n aria-label=\"Copy\"\n onClick={() => void copy()}\n >\n {copied ? <CheckGlyph /> : <CopyGlyph />}\n </button>\n {/* Same live-region convention as `Copyable.tsx:141-147`: the\n button's accessible name stays constant, so this announces the\n result. */}\n <span className=\"w6w-copyable-status\" aria-live=\"polite\">\n {copied ? \"Copied\" : \"\"}\n </span>\n </>\n )}\n </div>\n );\n}\n","import { Copyable } from \"./Copyable.tsx\";\n\n/** The single truncation marker every crop arm uses — matches\n * `studio/src/lib/page-title.ts:53-56`'s convention (one `…`, U+2026, never\n * three periods). */\nconst MARKER = \"…\";\n\n/**\n * Truncate `value` on a character budget, keeping `chars` VALUE characters and\n * adding {@link MARKER} on top (the marker is extra, not counted against\n * `chars`) — mirrors `page-title.ts`'s `clamp()` in STYLE (a single budget,\n * slice + marker, pure) but NOT its arithmetic: `clamp` slices at\n * `MAX - 1` so its marker counts inside the budget, which is the wrong shape\n * here (see `CopyableText.test.ts`'s fixture table).\n *\n * `chars` omitted, less than 1, or covering the whole value: returned as-is,\n * no marker.\n */\nexport function cropText(\n value: string,\n chars?: number,\n crop: \"start\" | \"end\" | \"middle\" = \"end\",\n): string {\n if (chars === undefined || chars < 1 || chars >= value.length) return value;\n\n if (crop === \"start\") {\n return `${MARKER}${value.slice(value.length - chars)}`;\n }\n if (crop === \"end\") {\n return `${value.slice(0, chars)}${MARKER}`;\n }\n\n // middle\n const head = Math.ceil(chars / 2);\n const tail = chars - head;\n return `${value.slice(0, head)}${MARKER}${value.slice(value.length - tail)}`;\n}\n\nexport interface CopyableTextProps {\n /** The full string. Always what gets written to the clipboard, regardless\n * of how much of it the cropped display shows. */\n value: string;\n /** How many VALUE characters to show. Omitted, `< 1`, or `>= value.length`\n * ⇒ shown in full. */\n chars?: number;\n /** Where the marker goes. Default `\"end\"`. */\n crop?: \"start\" | \"end\" | \"middle\";\n /** Accessible name of the copy button. Default \"Copy\" (per `Copyable`). */\n label?: string;\n className?: string;\n /** Forwarded to `Copyable`. See its own doc for the revert-delay caveat. */\n copiedMs?: number;\n}\n\n/**\n * A chrome-less, croppable copy-to-clipboard text — for a value too long to\n * show in full inline (an id, a token, a URL fragment) that still needs to be\n * copyable exactly.\n *\n * Composes `Copyable` rather than widening it (`Copyable`'s box chrome has 9\n * existing call sites depending on it) — `readOnly` + the\n * `.w6w-copyable--bare` modifier (`_copyable.scss`) strip the box, and the\n * FULL `value` is what `Copyable` receives, so a click always copies the\n * whole string even when the display is cropped. No `navigator.clipboard`\n * call lives in this file — that stays `Copyable`'s alone.\n */\nexport function CopyableText(props: CopyableTextProps) {\n const { value, chars, crop = \"end\", label, className, copiedMs } = props;\n const cropped = cropText(value, chars, crop);\n const classes = [\"w6w-copyable--bare\", className].filter(Boolean).join(\" \");\n\n return (\n <Copyable value={value} readOnly label={label} className={classes} copiedMs={copiedMs}>\n <span>{cropped}</span>\n </Copyable>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * The four health states a probe can report — a thin LOCAL copy of the RFC's\n * `HealthReport.state` union. `@w6w/ui` deliberately keeps a small literal type\n * here rather than depend on `@w6w/types`, so the display component stays a\n * pure-presentation leaf with no transport/spec coupling.\n */\nexport type HealthPillState = \"ok\" | \"degraded\" | \"down\" | \"unknown\";\n\nexport interface HealthStatusPillProps {\n /** Which health state to render — drives the colour + default label. */\n state: HealthPillState;\n /** Override the visible text (defaults to a humanised form of `state`). */\n label?: ReactNode;\n /** Accessible label for the pill (falls back to the visible text). */\n ariaLabel?: string;\n}\n\nconst DEFAULT_LABELS: Record<HealthPillState, string> = {\n ok: \"Operational\",\n degraded: \"Degraded\",\n down: \"Down\",\n unknown: \"Unknown\",\n};\n\n/**\n * A small, theme-aware status pill for a single health state.\n *\n * Renders a coloured dot + label using the `--w6w-health-*` tokens, so a host\n * can restyle every state by overriding those custom properties (see\n * `styles.css`). Colour is never the only signal — the text label carries the\n * same meaning for accessibility.\n */\nexport function HealthStatusPill({ state, label, ariaLabel }: HealthStatusPillProps) {\n const text = label ?? DEFAULT_LABELS[state];\n\n return (\n <span className={`w6w-health-pill w6w-health-pill-${state}`} aria-label={ariaLabel}>\n <span className=\"w6w-health-pill-dot\" aria-hidden=\"true\" />\n <span className=\"w6w-health-pill-label\">{text}</span>\n </span>\n );\n}\n","/**\n * The four states a single day of the strip can be in — a thin LOCAL copy of the\n * RFC's `HealthReport.state` union, exactly as `HealthStatusPill` keeps one. The\n * duplication is deliberate: it keeps `@w6w/ui` a pure-presentation leaf with no\n * transport/spec coupling, so nothing here has to move when the spec package does.\n *\n * There is no fifth state. A day on which the account made no calls at all is\n * `unknown`, never `ok` — an unverified day must never be presented as a healthy\n * one (`rfcs/healthcheck.md`: `unknown` ranks above `ok` for that reason).\n */\nexport type UptimeCellState = \"ok\" | \"degraded\" | \"down\" | \"unknown\";\n\n/** One cell: the day it stands for, and the state already decided for it. */\nexport interface UptimeDay {\n /** The day this cell represents, e.g. `2026-07-27`. Shown verbatim in the tooltip. */\n day: string;\n /** The state for that day. The strip renders it; it never decides it. */\n state: UptimeCellState;\n /** Tooltip override. Defaults to `<day> — <state label>`. */\n label?: string;\n}\n\nexport interface UptimeStripProps {\n /**\n * The days to render, oldest first, one cell each. The component makes no\n * assumption about how many there are — a caller showing a 30-day window\n * passes 30, and a younger account can pass fewer.\n */\n days: UptimeDay[];\n /**\n * Accessible label for the strip as a whole (it is exposed as one image, not\n * as N unlabelled boxes). Defaults to `<n>-day status`.\n */\n ariaLabel?: string;\n}\n\nconst STATE_LABELS: Record<UptimeCellState, string> = {\n ok: \"Operational\",\n degraded: \"Degraded\",\n down: \"Down\",\n unknown: \"Unknown\",\n};\n\n/**\n * A fixed-height strip of one cell per day, for \"how has this service behaved\n * lately\" at a glance.\n *\n * Purely presentational — it is handed an array of ALREADY-DECIDED states and\n * renders exactly those. No rules, no roll-up and no judgement about what counts\n * as broken live in this package; whatever decided the states owns that.\n *\n * Colour is never the only signal (same rule as `HealthStatusPill`, which pairs\n * its dot with a text label). Thirty cells cannot carry thirty labels, so the\n * strip signals twice in two other ways:\n * - every cell carries a `title` with its day and state, and\n * - the FILL HEIGHT encodes severity, so the row survives greyscale and\n * colour-blind viewing: `ok` is a short baseline bar, `degraded` a taller\n * one, `down` fills the cell, and `unknown` is a hatched outline with no\n * solid fill at all (nothing was measured — it is not a good day and not a\n * bad one).\n *\n * Colour itself comes from the shared `--w6w-health-*` tokens through the single\n * `--w6w-health-color` indirection the health pill uses, so a host that\n * overrides a token restyles the pill and the strip together.\n */\nexport function UptimeStrip({ days, ariaLabel }: UptimeStripProps) {\n if (days.length === 0) return null;\n\n return (\n <div\n className=\"w6w-uptime-strip\"\n role=\"img\"\n aria-label={ariaLabel ?? `${days.length}-day status`}\n >\n {days.map((entry, i) => (\n <span\n // Days are expected to be unique, but the index keeps the key stable\n // even if a caller repeats one — same guard as `ApiCallsPanel`.\n key={`${entry.day}-${i}`}\n className={`w6w-uptime-cell w6w-uptime-cell-${entry.state}`}\n title={entry.label ?? `${entry.day} — ${STATE_LABELS[entry.state]}`}\n />\n ))}\n </div>\n );\n}\n","/**\n * Pure formatting + geometry helpers for the server-resources family, kept in\n * their own module so they carry no React and can be unit-tested on their own.\n *\n * `ServerResourceSample` is a thin LOCAL copy of the sampler's wire sample\n * (`plan.md` §Pinned wire) — the same deliberate duplication `UptimeStrip.tsx`\n * keeps of the health union, and for the same reason: it keeps `@w6w/ui` a\n * pure-presentation leaf with no transport/spec coupling, so nothing here has\n * to move when the server's payload grows a field.\n *\n * Every helper is TOTAL: an unknown number is never rendered as `0`, it is\n * rendered as an em dash. A node whose CPU reading is missing must not read as\n * an idle node.\n */\n\n/** One sample of the host's resource usage, exactly as the server sends it. */\nexport interface ServerResourceSample {\n /** ISO-8601 instant the sample was taken. */\n ts: string;\n cpus: number | null;\n cpuLimit: number | null;\n load1: number | null;\n load5: number | null;\n load15: number | null;\n memoryTotal: number | null;\n memoryAvailable: number | null;\n memoryLimit: number | null;\n processRss: number | null;\n processHeapUsed: number | null;\n processHeapTotal: number | null;\n}\n\n/** What an unknown value renders as. Never `0`, never an empty cell. */\nconst UNKNOWN = \"—\";\n\n/** Binary magnitude suffixes, index-aligned with the 1024ᵏ divisor. */\nconst BYTE_UNITS = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\"] as const;\n\n/**\n * A byte count as a short human string: exact bytes below 1 KiB (`1023 B`),\n * one decimal place per binary magnitude from KiB up (`1.5 KiB`, `15.6 GiB`).\n * `null` (nothing measured) is `—`.\n */\nexport function formatBytes(n: number | null): string {\n if (n === null || !Number.isFinite(n)) return UNKNOWN;\n if (n < 1024) return `${Math.round(n)} B`;\n\n let value = n;\n let unit = 0;\n while (value >= 1024 && unit < BYTE_UNITS.length - 1) {\n value /= 1024;\n unit += 1;\n }\n return `${value.toFixed(1)} ${BYTE_UNITS[unit]}`;\n}\n\n/**\n * A 0…1-ish fraction as a whole-percent string (`0.123` → `12%`). Not clamped:\n * a load above the CPU count is real and reads `135%`. `null` is `—`.\n */\nexport function formatPercent(f: number | null): string {\n if (f === null || !Number.isFinite(f)) return UNKNOWN;\n return `${Math.round(f * 100)}%`;\n}\n\n/**\n * `load1` against the effective CPU budget — the container's `cpuLimit` when\n * the server set one, otherwise the host CPU count. `null` when either operand\n * is unknown or the divisor is ≤ 0 (a zero-CPU budget is not \"0% busy\", it is\n * \"not measurable\").\n */\nexport function cpuLoadFraction(s: ServerResourceSample | undefined): number | null {\n if (s === undefined) return null;\n if (s.load1 === null) return null;\n const divisor = s.cpuLimit ?? s.cpus;\n if (divisor === null || divisor <= 0) return null;\n return s.load1 / divisor;\n}\n\n/**\n * Used memory as a fraction of total: `(memoryTotal − memoryAvailable) /\n * memoryTotal`. `null` when either operand is unknown or the total is ≤ 0.\n */\nexport function memoryUsedFraction(s: ServerResourceSample | undefined): number | null {\n if (s === undefined) return null;\n const { memoryTotal, memoryAvailable } = s;\n if (memoryTotal === null || memoryAvailable === null) return null;\n if (memoryTotal <= 0) return null;\n return (memoryTotal - memoryAvailable) / memoryTotal;\n}\n\n/** `v` pinned into `[lo, hi]`. */\nfunction clamp(v: number, lo: number, hi: number): number {\n if (v < lo) return lo;\n return v > hi ? hi : v;\n}\n\n/**\n * The `points` attribute of a sparkline polyline, hand-drawn — this package\n * has no chart dependency on purpose (D-5), and a polyline over ~60 samples\n * does not justify one.\n *\n * The x axis is positional (`i / (n − 1) · width`), so a gap in the series\n * still advances the line; `y` is inverted (SVG grows downward) and scaled\n * against `max`. Nulls are SKIPPED, not plotted as zero, and a series of fewer\n * than two values has no line at all (`\"\"` — a single point is not a shape).\n * `max ≤ 0` flattens the line along the baseline rather than dividing by it.\n *\n * Every coordinate is rounded to two decimals so the attribute stays short and\n * a snapshot of it stays readable.\n */\nexport function sparklinePoints(\n values: readonly (number | null)[],\n width: number,\n height: number,\n max: number,\n): string {\n const n = values.length;\n if (n < 2) return \"\";\n\n const points: string[] = [];\n for (let i = 0; i < n; i++) {\n const v = values[i];\n if (v === null) continue;\n const x = (i / (n - 1)) * width;\n const y = max <= 0 ? height : height - (clamp(v, 0, max) / max) * height;\n points.push(`${Number(x.toFixed(2))},${Number(y.toFixed(2))}`);\n }\n return points.join(\" \");\n}\n","/**\n * The server-resources display family — four PURE PRESENTATIONAL variants over\n * the same array of samples: a large card, a small card, a left-rail strip and\n * a header badge.\n *\n * There is no data layer here, on purpose (plan.md §Pinned decisions: \"no\n * transport in ui\"): every variant is handed `samples` and renders the LAST\n * one, plus a sparkline drawn from the whole array. Nothing in this file reads\n * a network, a context or a host API — the caller owns the stream and the\n * operator gate.\n *\n * The sparkline is hand-rolled inline SVG rather than a chart dependency: a\n * polyline over ~60 points is a dozen lines of arithmetic (see\n * `sparklinePoints`), and `@w6w/ui` carrying recharts or d3 for it would be\n * unjustified weight for every consumer (D-5).\n *\n * An unknown value is never rendered as `0` — it is the em dash `formatBytes` /\n * `formatPercent` return for `null`. An unreported CPU reading must not read as\n * an idle node. The same applies to `samples: []`: every variant still renders\n * (all dashes, no line), so a caller never has to branch before mounting.\n */\nimport {\n type ServerResourceSample,\n cpuLoadFraction,\n formatBytes,\n formatPercent,\n memoryUsedFraction,\n sparklinePoints,\n} from \"./server-resources-format.ts\";\n\nexport interface ServerResourcesProps {\n /**\n * The samples to render, oldest first. The LAST entry is the current reading;\n * the whole array is the sparkline's series. May be empty — then every value\n * reads `—` and no line is drawn.\n */\n samples: readonly ServerResourceSample[];\n}\n\nexport interface ServerResourcesCardProps extends ServerResourcesProps {\n /** Heading text. Defaults to `Server resources`. */\n title?: string;\n /** The sampler's cadence, in ms. When given, the card shows `Sampled every Ns`. */\n intervalMs?: number;\n}\n\nexport interface ServerResourcesRailProps extends ServerResourcesProps {\n /**\n * When given, the rail shows one button that asks the caller to open the full\n * view. The rail never opens anything itself — mounting is the caller's job.\n */\n onExpand?: () => void;\n}\n\n/** What an unknown value renders as — the same dash the format helpers return. */\nconst UNKNOWN = \"—\";\n\n/** Sparkline geometry. The viewBox is 100 × 24 units, scaled by CSS. */\nconst SPARK_WIDTH = 100;\nconst SPARK_HEIGHT = 24;\n\n/** The sparkline. Deliberately NOT the shared `Icon` (`../components/Icon.tsx`):\n * nothing here is a fixed glyph — `points` is computed from the data, the\n * viewBox is this chart's own 100 × 24 units (scaled by CSS) rather than a\n * 24 × 24 icon box, and the stroke is the accent token, not `currentColor`. */\nfunction Sparkline({\n values,\n max,\n className,\n}: {\n values: readonly (number | null)[];\n max: number;\n className: string;\n}) {\n const points = sparklinePoints(values, SPARK_WIDTH, SPARK_HEIGHT, max);\n if (points === \"\") return null;\n\n return (\n <svg\n className={className}\n viewBox={`0 0 ${SPARK_WIDTH} ${SPARK_HEIGHT}`}\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <polyline\n points={points}\n fill=\"none\"\n stroke=\"var(--w6w-accent)\"\n strokeWidth={2}\n vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n );\n}\n\n/**\n * A fraction as a two-decimal string (`0.5` → `0.50`), or `—` when unknown.\n * The fixed precision is what keeps the three load averages visually aligned.\n */\nfunction formatLoad(n: number | null): string {\n return n === null ? UNKNOWN : n.toFixed(2);\n}\n\n/**\n * The largest value a series of fractions is drawn against — at least 1, so a\n * quiet host draws a flat-ish line near the baseline instead of amplifying\n * its own noise to a full-height sawtooth.\n */\nfunction fractionMax(values: readonly (number | null)[]): number {\n let max = 1;\n for (const v of values) if (v !== null && v > max) max = v;\n return max;\n}\n\n/** A labelled reading plus the sparkline of its series. */\nfunction MetricRow({\n label,\n value,\n values,\n max,\n}: {\n label: string;\n value: string;\n values: readonly (number | null)[];\n max: number;\n}) {\n return (\n <li className=\"w6w-server-resources__row\">\n <span className=\"w6w-server-resources__label\">{label}</span>\n <span className=\"w6w-server-resources__value\">{value}</span>\n <Sparkline className=\"w6w-server-resources__spark\" values={values} max={max} />\n </li>\n );\n}\n\n/** The one-sample readings every variant shows, computed once per render. */\nfunction readings(samples: readonly ServerResourceSample[]) {\n const last = samples[samples.length - 1];\n const cpuValues = samples.map((s) => cpuLoadFraction(s));\n const memoryValues = samples.map((s) => memoryUsedFraction(s));\n const rssValues = samples.map((s) => s.processRss);\n return { last, cpuValues, memoryValues, rssValues };\n}\n\n/**\n * The large variant: three readings (CPU, memory, process RSS), each with its\n * own sparkline, plus the load averages and — when the caller knows it — the\n * sampling cadence. This is the Console/Modal body.\n */\nexport function ServerResourcesCard({\n samples,\n title = \"Server resources\",\n intervalMs,\n}: ServerResourcesCardProps) {\n const { last, cpuValues, memoryValues, rssValues } = readings(samples);\n\n return (\n <section className=\"w6w-server-resources w6w-server-resources--card\" aria-label={title}>\n <h3 className=\"w6w-server-resources__title\">{title}</h3>\n <ul className=\"w6w-server-resources__rows\">\n <MetricRow\n label=\"CPU\"\n value={formatPercent(cpuLoadFraction(last))}\n values={cpuValues}\n max={fractionMax(cpuValues)}\n />\n <MetricRow\n label=\"Memory\"\n value={formatPercent(memoryUsedFraction(last))}\n values={memoryValues}\n max={1}\n />\n <MetricRow\n label=\"Process\"\n value={formatBytes(last?.processRss ?? null)}\n values={rssValues}\n max={fractionMax(rssValues)}\n />\n </ul>\n <p className=\"w6w-server-resources__meta\">\n {`Load ${formatLoad(last?.load1 ?? null)} / ${formatLoad(last?.load5 ?? null)} / ${formatLoad(\n last?.load15 ?? null,\n )}`}\n </p>\n {intervalMs !== undefined && (\n <p className=\"w6w-server-resources__meta\">{`Sampled every ${intervalMs / 1000}s`}</p>\n )}\n </section>\n );\n}\n\n/**\n * The small variant: CPU and memory only, one sparkline (CPU). For a compact\n * surface that has room for a headline and a shape, but not for a third\n * reading or the load breakdown.\n */\nexport function ServerResourcesCardSmall({ samples, title = \"Server\" }: ServerResourcesCardProps) {\n const { last, cpuValues } = readings(samples);\n\n return (\n <section className=\"w6w-server-resources w6w-server-resources--small\" aria-label={title}>\n <h3 className=\"w6w-server-resources__title\">{title}</h3>\n <ul className=\"w6w-server-resources__rows\">\n <MetricRow\n label=\"CPU\"\n value={formatPercent(cpuLoadFraction(last))}\n values={cpuValues}\n max={fractionMax(cpuValues)}\n />\n <li className=\"w6w-server-resources__row\">\n <span className=\"w6w-server-resources__label\">Memory</span>\n <span className=\"w6w-server-resources__value\">\n {formatPercent(memoryUsedFraction(last))}\n </span>\n </li>\n </ul>\n </section>\n );\n}\n\n/**\n * The left-rail variant: a stacked CPU and MEM reading, each with a sparkline,\n * sized to fit a ~200 px column. When the caller passes `onExpand` it also\n * shows the single \"show me the rest\" button; without one it is read-only\n * decoration and renders no interactive element at all.\n */\nexport function ServerResourcesRail({ samples, onExpand }: ServerResourcesRailProps) {\n const { last, cpuValues, memoryValues } = readings(samples);\n\n return (\n <aside className=\"w6w-server-resources w6w-server-resources--rail\">\n <div className=\"w6w-server-resources__rail-row\">\n <span className=\"w6w-server-resources__label\">CPU</span>\n <span className=\"w6w-server-resources__value\">{formatPercent(cpuLoadFraction(last))}</span>\n <Sparkline\n className=\"w6w-server-resources__spark\"\n values={cpuValues}\n max={fractionMax(cpuValues)}\n />\n </div>\n <div className=\"w6w-server-resources__rail-row\">\n <span className=\"w6w-server-resources__label\">MEM</span>\n <span className=\"w6w-server-resources__value\">\n {formatPercent(memoryUsedFraction(last))}\n </span>\n <Sparkline className=\"w6w-server-resources__spark\" values={memoryValues} max={1} />\n </div>\n {onExpand !== undefined && (\n <button\n type=\"button\"\n className=\"w6w-server-resources__expand\"\n aria-label=\"Show server resources\"\n onClick={onExpand}\n >\n Details\n </button>\n )}\n </aside>\n );\n}\n\n/**\n * The header badge: one line, `CPU <pct> · MEM <pct>`, no sparkline (a badge is\n * a fixed-height strip of text, and a line there would be unreadable). The\n * whole string is a single text node so assistive tech reads it as one phrase.\n */\nexport function ServerResourcesBadge({ samples }: ServerResourcesProps) {\n const last = samples[samples.length - 1];\n const cpu = formatPercent(cpuLoadFraction(last));\n const mem = formatPercent(memoryUsedFraction(last));\n\n return (\n <span className=\"w6w-server-resources w6w-server-resources--badge\">\n {`CPU ${cpu} · MEM ${mem}`}\n </span>\n );\n}\n","/**\n * Pure geometry for `HistoryTimeline`'s vendor lane — positioning a vendor\n * incident bar on the SAME percentage scale the execution lane's day cells\n * use, so the two series can never drift apart (`HistoryTimeline.tsx`'s\n * alignment invariant). Deliberately split out of the component: a function\n * that reads a clock itself makes that invariant unobservable to a gate, so\n * `nowMs` is always a parameter here, never `Date.now()`.\n *\n * No JSX, no React import — this file is imported directly by its own test\n * (`__tests__/HistoryTimeline.test.ts`) with no transpile step.\n */\nimport type { HistoryWindow, VendorIncidentBar } from \"./HistoryTimeline.tsx\";\n\n/**\n * Minimum visible width for a bar, as a percentage of the window's span. A\n * point-in-time entry (no `startedAt`) has zero duration and would otherwise\n * be invisible; a very short span is floored to the same width so it never\n * shrinks below it either.\n */\nexport const MIN_BAR_WIDTH_PCT = 1;\n\nexport interface BarPlacement {\n /** Left edge, as a percentage of the window's span, clamped to `[0, 100]`. */\n leftPct: number;\n /** Width, as a percentage of the window's span. Never below `MIN_BAR_WIDTH_PCT`. */\n widthPct: number;\n /** `true` if the bar's start was clamped to the window's left edge. */\n clippedStart: boolean;\n /** `true` if the bar's end was clamped to the window's right edge. */\n clippedEnd: boolean;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Places one vendor incident bar on the window's `[from T00:00:00Z, to+1 day\n * T00:00:00Z)` span.\n *\n * - A bar's start is `startedAt ?? updatedAt`; with neither present there is\n * nothing to place, so this returns `null` (B5).\n * - Its end is `resolvedAt ?? (startedAt !== undefined ? nowMs : start)` — an\n * open incident (has `startedAt`, no `resolvedAt`) therefore runs to\n * `nowMs`, and a feed-only entry with no `startedAt` is a point in time,\n * not a span (B3).\n * - A bar wholly outside the window (ends before it starts, or starts at or\n * after it ends) returns `null` (B4). One overlapping an edge is clamped\n * into the window, with `clippedStart`/`clippedEnd` set accordingly.\n */\nexport function placeIncidentBar(\n window: HistoryWindow,\n bar: VendorIncidentBar,\n nowMs: number,\n): BarPlacement | null {\n const start = bar.startedAt ?? bar.updatedAt;\n if (start === undefined) return null;\n\n const startMs = Date.parse(start);\n const endMs =\n bar.resolvedAt !== undefined\n ? Date.parse(bar.resolvedAt)\n : bar.startedAt !== undefined\n ? nowMs\n : startMs;\n\n const windowStartMs = Date.parse(`${window.from}T00:00:00.000Z`);\n const windowEndMs = Date.parse(`${window.to}T00:00:00.000Z`) + DAY_MS;\n const spanMs = windowEndMs - windowStartMs;\n\n if (endMs < windowStartMs || startMs >= windowEndMs) return null;\n\n const clippedStart = startMs < windowStartMs;\n const clippedEnd = endMs > windowEndMs;\n\n // The clamp to [0, 100] (B2) happens HERE, on the raw timestamps, and is\n // the ONLY place either bound is clamped — `leftPct`/`widthPct` below are\n // plain arithmetic on the clamped values, so there is no second, redundant\n // clamp for a mutation to skip past undetected.\n const clampedStartMs = Math.max(startMs, windowStartMs);\n const clampedEndMs = Math.min(endMs, windowEndMs);\n\n const leftPct = ((clampedStartMs - windowStartMs) / spanMs) * 100;\n const rawWidthPct = ((clampedEndMs - clampedStartMs) / spanMs) * 100;\n const widthPct = Math.max(rawWidthPct, MIN_BAR_WIDTH_PCT);\n\n return { leftPct, widthPct, clippedStart, clippedEnd };\n}\n","import type { UptimeCellState, UptimeDay } from \"./UptimeStrip.tsx\";\nimport { placeIncidentBar } from \"./history-scale.ts\";\n\n/** The calendar window both lanes are plotted against. Both bounds inclusive. */\nexport interface HistoryWindow {\n /** Inclusive first calendar day, `YYYY-MM-DD`. */\n from: string;\n /** Inclusive last calendar day, `YYYY-MM-DD`. */\n to: string;\n}\n\n/** One entry in the vendor's incident feed. */\nexport interface VendorIncidentBar {\n id?: string;\n title: string;\n state: UptimeCellState;\n /** ISO instant. Absent = a point-in-time update, not a span. */\n startedAt?: string;\n updatedAt?: string;\n /** ISO instant. Absent WITH `startedAt` present = still open. */\n resolvedAt?: string;\n components?: string[];\n link?: string;\n}\n\nexport interface HistoryTimelineProps {\n window: HistoryWindow;\n /** Execution lane, oldest first, one entry per calendar day. */\n days: UptimeDay[];\n /** Vendor lane. `undefined` = this vendor publishes no incident history at all. */\n incidents?: VendorIncidentBar[];\n /** Overrides the vendor lane's empty text. */\n vendorEmptyLabel?: string;\n /** Clock injection for tests and for an open incident's right edge. Defaults to `Date.now()`. */\n nowMs?: number;\n ariaLabel?: string;\n}\n\nconst STATE_LABELS: Record<UptimeCellState, string> = {\n ok: \"Operational\",\n degraded: \"Degraded\",\n down: \"Down\",\n unknown: \"Unknown\",\n};\n\nconst NO_FEED_LABEL = \"This vendor publishes no incident history.\";\nconst QUIET_LABEL = \"No incidents in this window.\";\n\nfunction barTitle(bar: VendorIncidentBar): string {\n const start = bar.startedAt ?? bar.updatedAt;\n const parts = [bar.title];\n if (bar.components !== undefined && bar.components.length > 0) {\n parts.push(`(${bar.components.join(\", \")})`);\n }\n if (start !== undefined) {\n parts.push(\n bar.resolvedAt !== undefined ? `${start} – ${bar.resolvedAt}` : `${start} – ongoing`,\n );\n }\n return parts.join(\" \");\n}\n\n/**\n * Two time series — our per-day execution history and the vendor's incident\n * history — plotted on one shared x-axis, so \"our calls failed *during* that\n * vendor incident\" is a visible alignment rather than a claim.\n *\n * Purely presentational, same discipline as `UptimeStrip`: `days` is already\n * one already-decided state per calendar day (no sort, no reverse, no gap\n * fill), and `incidents` is already the vendor's own feed. This component\n * places them; it makes no judgement about what counts as an incident.\n *\n * `incidents === undefined` (\"this vendor publishes no incident history\") and\n * `incidents === []` (\"nothing happened in this window\") are different facts\n * and render different empty-row text — Stripe is the first, a quiet Slack\n * window is the second. Either way the axis and the execution lane render in\n * full, at full width: a vendor with no feed never shrinks the half of the\n * chart that does have data.\n *\n * Severity is encoded twice, same rule as `UptimeStrip` and `HealthStatusPill`:\n * a per-state class AND a geometry difference (fill height on a day cell,\n * clip markers on a bar), never colour alone. Every cell and every bar\n * carries a `title`.\n */\nexport function HistoryTimeline({\n window: win,\n days,\n incidents,\n vendorEmptyLabel,\n nowMs = Date.now(),\n ariaLabel,\n}: HistoryTimelineProps) {\n const n = days.length;\n const cellWidthPct = n > 0 ? 100 / n : 0;\n\n const emptyLabel =\n incidents === undefined\n ? (vendorEmptyLabel ?? NO_FEED_LABEL)\n : incidents.length === 0\n ? (vendorEmptyLabel ?? QUIET_LABEL)\n : null;\n\n return (\n <div className=\"w6w-history-timeline\" role=\"img\" aria-label={ariaLabel ?? `${n}-day history`}>\n <div className=\"w6w-history-plot\">\n <div className=\"w6w-history-lane w6w-history-lane-execution\">\n {days.map((entry, i) => (\n <span\n // Days are expected to be unique, but the index keeps the key\n // stable even if a caller repeats one — same guard `UptimeStrip` uses.\n key={`${entry.day}-${i}`}\n className={`w6w-history-cell w6w-history-cell-${entry.state}`}\n style={{ left: `${i * cellWidthPct}%`, width: `${cellWidthPct}%` }}\n title={entry.label ?? `${entry.day} — ${STATE_LABELS[entry.state]}`}\n />\n ))}\n </div>\n <div className=\"w6w-history-lane w6w-history-lane-vendor\">\n {emptyLabel !== null ? (\n <span className=\"w6w-history-empty\" title={emptyLabel}>\n {emptyLabel}\n </span>\n ) : (\n incidents?.map((bar, i) => {\n const placement = placeIncidentBar(win, bar, nowMs);\n if (placement === null) return null;\n const clipClass = [\n placement.clippedStart ? \"w6w-history-bar-clip-start\" : \"\",\n placement.clippedEnd ? \"w6w-history-bar-clip-end\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n return (\n <span\n key={bar.id ?? `${bar.title}-${i}`}\n className={`w6w-history-bar w6w-history-bar-${bar.state}${clipClass ? ` ${clipClass}` : \"\"}`}\n style={{ left: `${placement.leftPct}%`, width: `${placement.widthPct}%` }}\n title={barTitle(bar)}\n />\n );\n })\n )}\n </div>\n <div className=\"w6w-history-axis\">\n <span className=\"w6w-history-tick w6w-history-tick-start\" style={{ left: \"0%\" }}>\n {win.from}\n </span>\n <span className=\"w6w-history-tick w6w-history-tick-end\" style={{ left: \"100%\" }}>\n {win.to}\n </span>\n </div>\n </div>\n </div>\n );\n}\n","import { type ReactNode, useId, useState } from \"react\";\nimport { IconButton } from \"./IconButton.tsx\";\n\nexport interface InfoTipProps {\n /** Accessible name AND tooltip of the toggle button (e.g. \"About client secrets\"). */\n label: string;\n /** The explanation, rendered only while expanded. */\n children: ReactNode;\n className?: string;\n}\n\n/**\n * A small \"i\" button that reveals a muted explanation block on click — for\n * copy that would otherwise clutter a modal. Collapsed by default; the button\n * carries `aria-expanded` and `aria-controls` pointing at the block, and the\n * block is not rendered at all while collapsed.\n */\nexport function InfoTip({ label, children, className }: InfoTipProps) {\n const [open, setOpen] = useState(false);\n const id = useId();\n return (\n <span className={[\"w6w-info-tip\", className ?? \"\"].filter(Boolean).join(\" \")}>\n <IconButton\n label={label}\n icon=\"info\"\n aria-expanded={open}\n aria-controls={id}\n onClick={() => setOpen((o) => !o)}\n />\n {open && (\n <span id={id} className=\"w6w-info-tip-body w6w-muted w6w-small\">\n {children}\n </span>\n )}\n </span>\n );\n}\n","import { IconButton } from \"./IconButton.tsx\";\n\nexport interface EditButtonProps {\n label: string;\n onClick: () => void;\n disabled?: boolean;\n className?: string;\n \"data-testid\"?: string;\n}\n\n/** An `IconButton` bundling the canonical pencil glyph — `icons.tsx`'s `edit`,\n * the two-path Feather pencil — with no `danger` styling. */\nexport function EditButton(props: EditButtonProps) {\n const { label, onClick, disabled, className, ...rest } = props;\n return (\n <IconButton\n label={label}\n onClick={onClick}\n disabled={disabled}\n className={className}\n icon=\"edit\"\n data-testid={rest[\"data-testid\"]}\n />\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { Icon } from \"./Icon.tsx\";\n\nexport interface RepoSyncIndicatorProps {\n /** Branch name, e.g. \"main\". */\n branch: string;\n /** Already-shortened commit sha (the consumer formats it — D-6). `null` renders no sha. */\n shortSha: string | null;\n /** Already-formatted last-sync text, e.g. \"3/9/2026, 12:16:29 PM\" or \"Never synced\".\n * `null` renders no time row. */\n lastSyncLabel: string | null;\n /** Fired when the flyout's \"Sync now\" item is activated. The consumer owns the mutation. */\n onSyncNow: () => void;\n /** True while the consumer's sync is in flight. */\n syncing?: boolean;\n className?: string;\n \"data-testid\"?: string;\n}\n\n/**\n * A compact header control showing a repo glyph, a branch name and a short\n * commit sha, with an inline flyout menu carrying the sync detail and a\n * \"Sync now\" action the consumer wires.\n *\n * `@w6w/ui` never fetches and holds no studio policy\n * (`studio/src/ui/ExpressionScope.tsx:40-41`, extended by D-6) — this\n * component takes already-formatted strings and a callback.\n *\n * The open/close + outside-click + Escape state machine mirrors\n * `studio/src/components/Layout.tsx:222-328`'s `ProjectMenu()` (D-3: no\n * shared Menu/Popover/Dropdown primitive — there is exactly one consumer).\n */\nexport function RepoSyncIndicator(props: RepoSyncIndicatorProps) {\n const { branch, shortSha, lastSyncLabel, onSyncNow, syncing, className, ...rest } = props;\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onDown = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && setOpen(false);\n document.addEventListener(\"mousedown\", onDown);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"mousedown\", onDown);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [open]);\n\n return (\n <div\n className={`w6w-repo-sync${className ? ` ${className}` : \"\"}`}\n ref={ref}\n data-testid={rest[\"data-testid\"]}\n >\n <button\n type=\"button\"\n className=\"w6w-repo-sync-trigger\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-busy={syncing}\n onClick={() => setOpen((v) => !v)}\n >\n <span className=\"w6w-repo-sync-icon\">\n {/* The connection provider's mark — `icons.tsx`'s `github` (`RepoBinding.provider`\n is always `\"github\"` today), 16px, the set's default. */}\n <Icon name=\"github\" />\n {/* The in-flight badge over the mark while `syncing`: `icons.tsx`'s `sync`\n (Feather `refresh-cw`), shrunk to 10×10 for this corner use and spun by\n `.w6w-repo-sync-spin`, which `Icon` merges with `w6w-icon`. */}\n {syncing && <Icon name=\"sync\" size={10} className=\"w6w-repo-sync-spin\" />}\n </span>\n <span className=\"w6w-repo-sync-branch\">{branch}</span>\n {shortSha != null && <code className=\"w6w-repo-sync-sha\">{shortSha}</code>}\n </button>\n {open && (\n <div className=\"w6w-repo-sync-menu\" role=\"menu\">\n <div className=\"w6w-repo-sync-detail\">\n <span>{branch}</span>\n {shortSha != null && <code>{shortSha}</code>}\n {lastSyncLabel != null && <span>{lastSyncLabel}</span>}\n </div>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"w6w-repo-sync-item\"\n data-testid=\"repo-sync-now\"\n disabled={syncing}\n onClick={onSyncNow}\n >\n {syncing ? \"Syncing…\" : \"Sync now\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * The five states a workflow step's execution can be in — a thin LOCAL copy\n * of the workflow spec's `StepStatus` union\n * (`packages/w6w-workflow/packages/types/mod.ts`). `@w6w/ui` deliberately\n * keeps a small literal type here rather than depend on `@w6w/workflow-types`,\n * so this stays a pure-presentation leaf with no transport/spec coupling —\n * the same precedent `HealthStatusPill`'s `HealthPillState` establishes.\n */\nexport type StepStatus = \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n\n/**\n * Why a `skipped` step did not run — the engine's `NodeExecution.skipReason`, again a thin\n * LOCAL literal. `not_on_path`: the step is not downstream of the fired trigger (or outside a\n * run-from-node scope), so it was never part of the run; the other three are real skips. A\n * record from before the engine stamped reasons has none.\n */\nexport type SkipReason = \"not_on_path\" | \"condition\" | \"stopped\" | \"disabled\";\n\n/**\n * The five states a whole EXECUTION (an invocation, an endpoint call, a\n * workflow run) can be in — the run-level sibling of `StepStatus`, and again a\n * thin LOCAL literal rather than an import of any spec/wire type. The two\n * unions differ exactly where runs and steps differ: a run can be `queued`\n * before it starts and `canceled` after it started, while a step inside a run\n * can be `pending` or `skipped` (a run is never either). They are deliberately\n * NOT merged into one five/six-member union — `ExecutionList` and the step\n * panel must each accept only their own vocabulary.\n */\nexport type ExecutionStatus = \"queued\" | \"running\" | \"succeeded\" | \"failed\" | \"canceled\";\n\nexport interface StepStatusPillProps {\n /**\n * Which state to render — drives the colour + default label. Accepts both\n * vocabularies: a workflow step's `StepStatus` and a whole run's\n * `ExecutionStatus` (the pill is only a coloured label, so it does not care\n * which of the two a host is describing).\n */\n state: StepStatus | ExecutionStatus;\n /** Override the visible text (defaults to a humanised form of `state`). */\n label?: ReactNode;\n /** Accessible label for the pill (falls back to the visible text). */\n ariaLabel?: string;\n}\n\nconst DEFAULT_LABELS: Record<StepStatus | ExecutionStatus, string> = {\n pending: \"Pending\",\n running: \"Running\",\n succeeded: \"Succeeded\",\n failed: \"Failed\",\n skipped: \"Skipped\",\n queued: \"Queued\",\n canceled: \"Canceled\",\n};\n\n/**\n * A small, theme-aware status pill for one workflow step's execution state.\n *\n * Mirrors `HealthStatusPill` shape for shape: a state union, a\n * `DEFAULT_LABELS` record, a coloured dot + text label using one\n * `--w6w-step-color` custom property per modifier class, and the\n * `w6w-step-pill w6w-step-pill-${state}` className convention. Colour is\n * never the only signal — the text label carries the same meaning for\n * accessibility. Five states rather than `HealthStatusPill`'s four, so this\n * is a mirror of that shape, not a shared implementation.\n *\n * Renders BOTH vocabularies through the one prop: `StepStatus` (a step inside\n * a run) and `ExecutionStatus` (a whole run). The union is widened at the\n * PROP only — `StepStatus` itself is unchanged, so the step panel's own type\n * cannot silently grow run-only states.\n */\nexport function StepStatusPill({ state, label, ariaLabel }: StepStatusPillProps) {\n const text = label ?? DEFAULT_LABELS[state];\n\n return (\n <span className={`w6w-step-pill w6w-step-pill-${state}`} aria-label={ariaLabel}>\n <span className=\"w6w-step-pill-dot\" aria-hidden=\"true\" />\n <span className=\"w6w-step-pill-label\">{text}</span>\n </span>\n );\n}\n","/**\n * Pure duration/time formatters for the execution-history family, kept in\n * their own module so they carry no React and can be unit-tested on their own\n * — the same split `server-resources-format.ts` establishes.\n *\n * Both are TOTAL: a duration that was never measured (a still-running or\n * queued run) is rendered as an em dash, never as `0 ms` — \"unknown\" must not\n * read as \"instant\".\n */\n\n/** What an unmeasured/unknown value renders as. Never `0`. */\nconst UNKNOWN = \"—\";\n\nconst MS_PER_SECOND = 1000;\nconst MS_PER_MINUTE = 60_000;\n\n/**\n * A run duration as a short human string: whole milliseconds below a second\n * (`999 ms`), one decimal place in seconds below a minute (`1.5 s`), and\n * `2m 5s` from a minute up. `null`/`undefined` (nothing measured), `NaN` and\n * negatives are all `—`.\n */\nexport function formatDurationMs(ms: number | null | undefined): string {\n if (ms == null || !Number.isFinite(ms) || ms < 0) return UNKNOWN;\n if (ms < MS_PER_SECOND) return `${Math.round(ms)} ms`;\n if (ms < MS_PER_MINUTE) return `${(ms / MS_PER_SECOND).toFixed(1)} s`;\n return `${Math.floor(ms / MS_PER_MINUTE)}m ${Math.round((ms % MS_PER_MINUTE) / MS_PER_SECOND)}s`;\n}\n\n/**\n * An ISO-8601 instant as a short, locale-formatted date+time (`Sep 22, 2026,\n * 10:00 AM` under the default locale). The locale is the HOST's\n * (`undefined`), so the string follows the viewer's own settings rather than\n * baking one in. A string `Date` cannot parse is returned UNCHANGED — an\n * unrenderable timestamp is shown as the wire value, never as \"Invalid Date\".\n */\nexport function formatExecutionTime(iso: string): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return iso;\n return date.toLocaleString(undefined, { dateStyle: \"medium\", timeStyle: \"short\" });\n}\n","import type { ReactNode } from \"react\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { ListItem } from \"./ListItem.tsx\";\nimport type { ExecutionStatus } from \"./StepStatusPill.tsx\";\nimport { StepStatusPill } from \"./StepStatusPill.tsx\";\nimport { formatDurationMs, formatExecutionTime } from \"./execution-format.ts\";\n\n/** What kind of callable a run belongs to. A thin LOCAL literal — the same\n * deliberate duplication `StepStatusPill`'s unions keep. */\nexport type ExecutionKind = \"function\" | \"endpoint\" | \"workflow\";\n\n/** One past execution's display row — an already-mapped slice of the host's\n * history payload. The HOST maps its own record into this shape (the same\n * \"host owns the data, the list is presentational\" split `ExecutionLogPanel`\n * establishes): this component never fetches, paginates or reaches for an SDK. */\nexport interface ExecutionListItem {\n /** Stable id for this row — what `onSelect` reports and `selectedId` matches. */\n id: string;\n kind: ExecutionKind;\n /** The callable's name/key this run belongs to. */\n callableName: string;\n status: ExecutionStatus;\n /** ISO-8601 instant the run started. */\n startedAt: string;\n /** Wall-clock duration once the run has finished; `null` while it is still\n * queued/running (rendered as `—`). */\n durationMs: number | null;\n /** The execution this one is a re-run of — the row then carries a \"Re-run\"\n * tag. `null`/omitted ⇒ an ordinary execution. */\n rerunOf?: string | null;\n /** How the run was started (`manual`, `schedule`, `webhook`, `event`, `replay`, or any other\n * value the host passes through). `null`/omitted ⇒ no trigger segment. */\n trigger?: string | null;\n /** The trigger node the run entered through, shown beside the trigger. */\n triggerNodeId?: string | null;\n /** The start of the run's input as JSON text, shown as a one-line snippet. `null`/omitted ⇒\n * no snippet. */\n inputPreview?: string | null;\n}\n\nexport interface ExecutionListProps {\n /** The page of past executions, rendered in exactly this order — never re-sorted. */\n items: ExecutionListItem[];\n /** The row to highlight as current. `null`/omitted ⇒ no row is active. */\n selectedId?: string | null;\n /** Supplied ⇒ rows are clickable and report their id here. Omitted ⇒ every\n * row is a plain, non-interactive row. */\n onSelect?: (id: string) => void;\n /**\n * `true` ⇒ each row's title is the callable's name and its subtitle carries\n * the kind + start time (the project-wide history view). `false` ⇒ the title\n * is the start time and the subtitle is the run id (the per-callable view,\n * where the callable is already known). Defaults to `false`.\n */\n showCallable?: boolean;\n /** `true` ⇒ the loading branch while there is nothing to show yet. */\n loading?: boolean;\n /** Shown instead of the list when `items` is empty. */\n emptyLabel?: ReactNode;\n /** Whether a previous page exists — drives the pager's `Previous` state. */\n hasPrev?: boolean;\n /** Whether a next page exists — drives the pager's `Next` state. */\n hasNext?: boolean;\n /** Supplied ⇒ the pager renders and `Previous` calls this. */\n onPrev?: () => void;\n /** Supplied ⇒ the pager renders and `Next` calls this. */\n onNext?: () => void;\n /** Supplied ⇒ every row gets a \"Re-run\" control beside it that reports the\n * row's id here. Omitted ⇒ no control. */\n onRerun?: (id: string) => void;\n /** The row whose re-run is in flight — its control is disabled. While any\n * re-run is in flight every row's control is disabled, so two can never\n * overlap. `null`/omitted ⇒ none. */\n rerunningId?: string | null;\n}\n\n/** Row subtitle's kind prefix, in the `showCallable` view. */\nconst KIND_LABEL: Record<ExecutionKind, string> = {\n function: \"Function\",\n endpoint: \"Endpoint\",\n workflow: \"Workflow\",\n};\n\n/** Known trigger kinds' labels; any other value is shown as given. */\nconst TRIGGER_LABEL: Record<string, string> = {\n manual: \"Manual\",\n schedule: \"Schedule\",\n webhook: \"Webhook\",\n event: \"Event\",\n replay: \"Replay\",\n};\n\n/** The row's trigger segment — `Event · order_placed_1` — or `null` when the host gave none. */\nfunction triggerText(item: ExecutionListItem): string | null {\n if (!item.trigger) return null;\n const label = TRIGGER_LABEL[item.trigger] ?? item.trigger;\n return item.triggerNodeId ? `${label} · ${item.triggerNodeId}` : label;\n}\n\n/**\n * A paged list of past executions: one row per run, click-to-select, with a\n * prev/next pager.\n *\n * A pure display leaf — no fetching, no polling, no sorting, no local\n * selection state. It renders `items` in the order given, reports a click, and\n * reports a page request; the host owns which page is loaded and which row is\n * selected.\n */\nexport function ExecutionList({\n items,\n selectedId = null,\n onSelect,\n showCallable = false,\n loading = false,\n emptyLabel,\n hasPrev,\n hasNext,\n onPrev,\n onNext,\n onRerun,\n rerunningId = null,\n}: ExecutionListProps) {\n // Rendered in EVERY branch below, deliberately: a host that reports it can\n // go back to a previous page must still offer that control from an empty\n // page (the state reached by paging past the last run) and while a page is\n // loading.\n const pager =\n onPrev || onNext ? (\n <div className=\"w6w-execution-list-pager\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-list-prev\"\n disabled={!hasPrev}\n onClick={onPrev}\n >\n Previous\n </button>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-list-next\"\n disabled={!hasNext}\n onClick={onNext}\n >\n Next\n </button>\n </div>\n ) : null;\n\n let body: ReactNode;\n if (loading && items.length === 0) {\n body = <p data-testid=\"execution-list-loading\">Loading…</p>;\n } else if (items.length === 0) {\n body = <p data-testid=\"execution-list-empty\">{emptyLabel ?? \"No executions yet.\"}</p>;\n } else {\n body = (\n <ul className=\"w6w-execution-list-rows\">\n {items.map((item) => (\n <li key={item.id} data-testid=\"execution-row\" data-execution-id={item.id}>\n <ListItem\n icon={<StepStatusPill state={item.status} />}\n title={\n <>\n {showCallable ? item.callableName : formatExecutionTime(item.startedAt)}\n {item.rerunOf && (\n <span\n className=\"w6w-execution-rerun-tag\"\n data-testid=\"execution-row-rerun-tag\"\n title={`Re-run of ${item.rerunOf}`}\n >\n Re-run\n </span>\n )}\n </>\n }\n subtitle={\n <>\n {showCallable\n ? `${KIND_LABEL[item.kind]} · ${formatExecutionTime(item.startedAt)}`\n : item.id}\n {triggerText(item) && (\n <span className=\"w6w-execution-trigger\" data-testid=\"execution-row-trigger\">\n {` · ${triggerText(item)}`}\n </span>\n )}\n {item.inputPreview && (\n <>\n {\" · \"}\n <code\n className=\"w6w-execution-input-preview\"\n data-testid=\"execution-row-input\"\n title={item.inputPreview}\n >\n {item.inputPreview}\n </code>\n </>\n )}\n </>\n }\n trailing={formatDurationMs(item.durationMs)}\n active={item.id === selectedId}\n onClick={onSelect ? () => onSelect(item.id) : undefined}\n />\n {onRerun && (\n <IconButton\n icon=\"sync\"\n label=\"Re-run\"\n title={item.id === rerunningId ? \"Re-running…\" : \"Re-run with the same input\"}\n className=\"w6w-execution-list-rerun\"\n data-testid=\"execution-row-rerun\"\n disabled={rerunningId !== null}\n onClick={() => onRerun(item.id)}\n />\n )}\n </li>\n ))}\n </ul>\n );\n }\n\n return (\n <div className=\"w6w-execution-list\" data-testid=\"execution-list\">\n {body}\n {pager}\n </div>\n );\n}\n","import type { StateWarningCode } from \"@w6w/expr\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { CodeBlock } from \"../CodeBlock.tsx\";\nimport { conditionCombinatorLabel, conditionOperatorLabel } from \"../condition-editor.ts\";\nimport { internalNodeDef } from \"../flow-types.ts\";\nimport type { StepMeta } from \"../provider.tsx\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { ResultViewer } from \"./ResultViewer.tsx\";\nimport { StepStatusPill } from \"./StepStatusPill.tsx\";\nimport type { SkipReason, StepStatus } from \"./StepStatusPill.tsx\";\n\n/** What a step is: the app and action it uses, and whether it is a trigger (`uses.trigger`). */\nexport interface ExecutionLogNode {\n app: string;\n action: string;\n trigger?: boolean;\n appName?: string;\n actionName?: string;\n}\n\n/** A node's kind and display names, a built-in `@w6w/*` node resolved from its own definition. */\nfunction describeNode(node: ExecutionLogNode): {\n trigger: boolean;\n appName: string;\n actionName: string;\n} {\n const builtin = internalNodeDef(node.app, node.action);\n return {\n trigger: node.trigger === true || builtin?.group === \"trigger\",\n appName: node.appName ?? builtin?.displayName ?? node.app,\n actionName: node.actionName ?? builtin?.label ?? node.action,\n };\n}\n\n/**\n * A step's or run's failure, already normalised by the HOST from the workflow\n * spec's `StepError` (`code`/`message`/`phase`/`retryable`). The panel never\n * parses an `unknown` error itself — same \"host owns the data\" split as the\n * rest of this file. Rendered in `TriggerFillForm`'s error visual: a\n * `.w6w-result.w6w-error` box, an optional `<code>` badge line, then the message.\n */\nexport interface ExecutionLogError {\n /** `StepError.code`. Optional: the host may normalise an error that carries no code. */\n code?: string;\n /** The human-readable reason. Never empty when the host supplies it. */\n message: string;\n /** `StepError.phase`, when known. Carried for the host; not rendered. */\n phase?: string;\n /** `StepError.retryable`, when known. Carried for the host; not rendered. */\n retryable?: boolean;\n}\n\n/**\n * One entry of `RunState.stepErrors` — a step failure the run recorded and\n * moved past (`onError: \"continue-record\"`, or a failure an error edge\n * handled), so the run itself may still have succeeded.\n */\nexport interface ExecutionLogRecordedError {\n /** The step the error belongs to. */\n stepId: string;\n /** Human-readable step name. Falls back to `stepId` when rendered. */\n label?: string;\n error: ExecutionLogError;\n}\n\n/**\n * One step's display row — an already-mapped, already-resolved slice of a\n * `RunState`/`StepExecution` (workflow spec). The HOST maps its own run\n * state into this shape (same \"host owns the data, the panel is\n * presentational\" split `readOnly` already establishes elsewhere in this\n * package) — this component never fetches, polls, or reaches for an SDK.\n */\nexport interface ExecutionLogStep {\n /** Stable id for this row — typically the step id from the workflow definition. */\n id: string;\n /** Human-readable step name. Falls back to `id` when omitted. */\n label?: string;\n status: StepStatus;\n /**\n * Why a `skipped` step did not run (`StepExecution.skipReason`). `not_on_path` rows leave the\n * list for the \"other paths\" footer; the rest show a short reason beside the Skipped pill.\n * Absent (a run recorded before reasons existed) ⇒ a plain Skipped row, as before.\n */\n skipReason?: SkipReason;\n /** ISO-8601 timestamp the step started, once it has. */\n startedAt?: string;\n /** ISO-8601 timestamp the step finished, once it has. */\n finishedAt?: string;\n /** The resolved input sent to the step's action, once it is known. */\n input?: unknown;\n /** The step's output, once it has one. */\n output?: unknown;\n /** Captured console output (also present when a script throws). */\n logs?: string[];\n /**\n * What ran (`StepExecution.meta`): app, version, action and connection id. Shown as a\n * Metadata block after Output. Absent or `null` ⇒ no block at all (R-12: no filler).\n */\n meta?: StepMeta | null;\n /**\n * What this step IS, from the workflow definition — shown on the row itself so a run reads as\n * \"Trigger · Cohost · Order Placed\" rather than a bare node id. `appName`/`actionName` are the\n * host's display names for a registered app; a built-in `@w6w/*` node is named here from its\n * own definition, and anything unnamed falls back to the raw id. Absent ⇒ the row shows its\n * label alone, as before.\n */\n node?: ExecutionLogNode;\n /**\n * Why the step failed (`StepExecution.error`, \"present on failed\"). Rendered\n * below the row's box and outside its lazy `<details>` body, so the reason\n * reads without expanding the row.\n */\n error?: ExecutionLogError;\n /** For each only (I4): the per-iteration body-step records, index ascending. */\n iterations?: ExecutionLogIteration[];\n /** Distinct iteration indices the run recorded (may exceed `iterations.length`). */\n iterationsTotal?: number;\n /** How many of those iterations failed. */\n iterationsFailed?: number;\n /** `true` when `iterations` holds fewer than `iterationsTotal`. */\n iterationsTruncated?: boolean;\n /**\n * The step's state writes (`stateWrites`, the run's state log rows for this step), in write\n * order: `state.<path>: old → new`, or a warning when `warning` is set (a `StateWarningCode`).\n * `item` is the For each item a hoisted body write came from. Absent, `null` or `[]` ⇒ no rows.\n */\n stateWrites?: Array<{\n path: string[];\n item?: number;\n old?: unknown;\n new?: unknown;\n warning?: string;\n }> | null;\n /**\n * The run's state tree after this step, shown as \"State after this step\" in the State block.\n * Absent or `null` ⇒ not shown; `{}` shows only alongside writes.\n */\n stateAfter?: Record<string, unknown> | null;\n}\n\n/** One For each iteration: its status and the body-step records, in execution order. */\nexport interface ExecutionLogIteration {\n /** 0-based; the same number as `foreach.index` in that iteration's expressions. */\n index: number;\n status: \"succeeded\" | \"failed\" | \"running\";\n /** The body step that failed, when one did. */\n failedNodeId?: string;\n steps: ExecutionLogStep[];\n}\n\n/** Server record key order is not execution order. Keep ties stable and never mutate props. */\nfunction chronologicalSteps(steps: readonly ExecutionLogStep[]): ExecutionLogStep[] {\n const time = (step: ExecutionLogStep) => {\n for (const value of [step.startedAt, step.finishedAt]) {\n const parsed = Date.parse(value ?? \"\");\n if (Number.isFinite(parsed)) return parsed;\n }\n return Number.POSITIVE_INFINITY;\n };\n return steps\n .map((step) => ({ step, time: time(step) }))\n .sort((a, b) => (a.time === b.time ? 0 : a.time - b.time))\n .map(({ step }) => step);\n}\n\nexport interface ExecutionLogPanelProps {\n /** Rendered earliest first by start time (finish time as fallback), then untimed steps. */\n steps: ExecutionLogStep[];\n /** Shown instead of the list when `steps` is empty. */\n emptyLabel?: ReactNode;\n /**\n * Supplied ⇒ the panel grows a header row carrying a dismiss control that\n * calls this and nothing else (T1.1.1). Omitted ⇒ no header row at all, no\n * extra DOM node. The panel still owns no run state — it only reports the\n * click; the host decides what dismissing means.\n */\n onDismiss?: () => void;\n /**\n * The run's own failure (`RunState.error`). Rendered below the dismiss head\n * and above the steps — in the empty branch too, since a run that failed\n * before any step ran has nothing else to say why.\n */\n runError?: ExecutionLogError;\n /**\n * Step failures the run recorded and moved past (`RunState.stepErrors`),\n * one error block each, in the order given, after `runError`.\n */\n stepErrors?: ExecutionLogRecordedError[];\n}\n\n/**\n * Read-only log of a workflow run's steps, in ascending execution time: each row is\n * the step's status pill, its timing, and its resolved input/output.\n *\n * A pure display leaf — no data fetching, no polling, no layout media\n * queries (the host docks the panel; see `_scale.scss`'s breakpoint\n * docstring). Fills whatever box its host gives it.\n */\nexport function ExecutionLogPanel({\n steps,\n emptyLabel,\n onDismiss,\n runError,\n stepErrors,\n}: ExecutionLogPanelProps) {\n // Rendered by BOTH branches below, deliberately: the reported repro (T-1) is\n // a canvas whose log panel shows \"No nodes have run yet.\" — a header mounted\n // only above the `<ol>` would be invisible in exactly that state, and that is\n // the state the dismiss control exists to get the user out of.\n const head = onDismiss ? (\n <div className=\"w6w-execution-log-head\">\n <IconButton label=\"Dismiss run log\" data-testid=\"execution-log-dismiss\" onClick={onDismiss}>\n ×\n </IconButton>\n </div>\n ) : null;\n\n // Same both-branches rule as `head`: a run that failed before its first step\n // is exactly the empty branch. Nothing to report ⇒ no wrapper node at all.\n const recorded = stepErrors ?? [];\n const errors =\n runError || recorded.length > 0 ? (\n <div className=\"w6w-execution-log-errors w6w-stack\">\n {runError && <ExecutionLogErrorBlock error={runError} />}\n {recorded.map((entry, index) => (\n <ExecutionLogErrorBlock\n // `stepId` alone may repeat (a step retried into the record twice).\n key={`${entry.stepId}:${index}`}\n label={entry.label ?? entry.stepId}\n error={entry.error}\n />\n ))}\n </div>\n ) : null;\n\n // A step on another path (not downstream of the fired trigger) was never part of this run:\n // it is not a skip, so it leaves the list for one collapsed footer line.\n const inRun = chronologicalSteps(steps.filter((s) => !isOffPath(s)));\n const offPath = steps.filter(isOffPath);\n const footer = offPath.length > 0 ? <ExecutionLogOffPath steps={offPath} /> : null;\n\n if (inRun.length === 0) {\n return (\n <>\n {head}\n {errors}\n <div className=\"w6w-execution-log-empty\">\n <p className=\"w6w-muted w6w-small\">{emptyLabel ?? \"No nodes have run yet.\"}</p>\n </div>\n {footer}\n </>\n );\n }\n\n return (\n <>\n {head}\n {errors}\n <ol className=\"w6w-execution-log\">\n {inRun.map((step) => (\n <ExecutionLogRow key={step.id} step={step} />\n ))}\n </ol>\n {footer}\n </>\n );\n}\n\nconst isOffPath = (step: ExecutionLogStep) =>\n step.status === \"skipped\" && step.skipReason === \"not_on_path\";\n\n/** The short reason shown beside a real skip's pill. */\nconst SKIP_REASON_LABELS: Record<Exclude<SkipReason, \"not_on_path\">, string> = {\n condition: \"condition false\",\n stopped: \"run stopped\",\n disabled: \"disabled\",\n};\n\n/** \"N steps on other paths, not part of this run\" — collapsed; expands to their names. */\nfunction ExecutionLogOffPath({ steps }: { steps: ExecutionLogStep[] }) {\n const n = steps.length;\n return (\n <details className=\"w6w-execution-log-off-path\" data-testid=\"execution-log-off-path\">\n <summary className=\"w6w-muted w6w-small\">\n {`${n} ${n === 1 ? \"step\" : \"steps\"} on other paths, not part of this run`}\n </summary>\n <ul className=\"w6w-muted w6w-small\">\n {steps.map((s) => (\n <li key={s.id}>{s.label ?? s.id}</li>\n ))}\n </ul>\n </details>\n );\n}\n\n/**\n * Collapsed-by-default disclosure per step (REVIEW.md R-1) — reuses\n * `.w6w-section`'s bordered `<details>` idiom (`ApiCallsPanel.tsx`,\n * `ParamsForm.tsx`'s `section: \"collapsible\"`), not a bespoke card. The\n * `<summary>` is the one-line scan line (pill + label + timing, unchanged\n * content from the old always-visible row header); Input/Output move inside\n * the details body, and are only mounted into the DOM once opened — a\n * closed run of N steps costs N compact rows, not N×2 rendered JSON blocks.\n *\n * A step with neither `input` nor `output` has nothing to disclose: it\n * renders a plain, non-interactive row (still `.w6w-section`-styled for\n * visual consistency with its siblings) rather than an empty `<details>` a\n * user opens only to find \"Not available.\" twice (A3). An `error` alone is\n * not something to disclose either: it renders on every row as a sibling\n * AFTER the row's box — outside the lazily mounted `<details>` body (so it\n * reads while collapsed and never mounts twice once opened) and outside the\n * `<summary>` (whose phrasing-content model and click-to-toggle make it the\n * wrong home for a selectable block of text).\n */\nfunction ExecutionLogRow({ step }: { step: ExecutionLogStep }) {\n const [open, setOpen] = useState(false);\n const node = step.node ? describeNode(step.node) : null;\n const header = (\n <div className=\"w6w-execution-log-row-header\">\n <StepStatusPill state={step.status} />\n {node && (\n <span\n className={`w6w-execution-log-kind${node.trigger ? \" w6w-execution-log-kind-trigger\" : \"\"}`}\n data-testid=\"execution-log-kind\"\n >\n {node.trigger ? \"Trigger\" : \"Node\"}\n </span>\n )}\n <span className=\"w6w-execution-log-row-title\">\n <span className=\"w6w-execution-log-row-label\">{step.label ?? step.id}</span>\n {node && (\n <span className=\"w6w-execution-log-row-uses\" data-testid=\"execution-log-uses\">\n {node.appName === node.actionName\n ? node.appName\n : `${node.appName} · ${node.actionName}`}\n </span>\n )}\n </span>\n {step.status === \"skipped\" && step.skipReason && step.skipReason !== \"not_on_path\" && (\n <span className=\"w6w-execution-log-skip-reason\" data-testid=\"execution-log-skip-reason\">\n {SKIP_REASON_LABELS[step.skipReason]}\n </span>\n )}\n <StepTiming startedAt={step.startedAt} finishedAt={step.finishedAt} />\n </div>\n );\n\n const error = step.error ? <ExecutionLogErrorBlock error={step.error} /> : null;\n const loop = Array.isArray(step.iterations) ? <ExecutionLogIterations step={step} /> : null;\n\n const state = hasStateBlock(step) ? <ExecutionLogState step={step} /> : null;\n\n if (\n step.input === undefined &&\n step.output === undefined &&\n !step.meta &&\n !state &&\n !step.logs?.length\n ) {\n return (\n <li className=\"w6w-execution-log-row\">\n <div className=\"w6w-section\">{header}</div>\n {error}\n {loop}\n </li>\n );\n }\n\n return (\n <li className=\"w6w-execution-log-row\">\n <details className=\"w6w-section\" open={open} onToggle={(e) => setOpen(e.currentTarget.open)}>\n <summary className=\"w6w-section-summary\">{header}</summary>\n {open && (\n <div className=\"w6w-execution-log-row-body w6w-section-body w6w-stack\">\n <ExecutionLogConditions input={step.input} />\n <ExecutionLogJson title=\"Input\" value={step.input} />\n <ExecutionLogJson title=\"Output\" value={step.output} />\n {!!step.logs?.length && (\n <div className=\"w6w-execution-log-json w6w-stack\">\n <strong className=\"w6w-small\">Console</strong>\n <CodeBlock code={step.logs.join(\"\\n\")} language=\"plaintext\" />\n </div>\n )}\n {step.meta && (\n <div className=\"w6w-execution-log-json w6w-stack\">\n <strong className=\"w6w-small\">Metadata</strong>\n <CodeBlock code={JSON.stringify(step.meta, null, 2)} language=\"json\" />\n </div>\n )}\n {state}\n </div>\n )}\n </details>\n {error}\n {loop}\n </li>\n );\n}\n\n/**\n * A For each row's per-iteration view: a summary (count, failures, pointer at the\n * failing body step), one presentational chip per served iteration, and one\n * sub-row per body step with its own iteration `<select>` (failed iteration\n * preselected, else the last served one). Pure props -> DOM; no fetching.\n */\nfunction ExecutionLogIterations({ step }: { step: ExecutionLogStep }) {\n const iterations = [...(step.iterations ?? [])].sort((a, b) => a.index - b.index);\n const total = step.iterationsTotal ?? iterations.length;\n const failedCount =\n step.iterationsFailed ?? iterations.filter((it) => it.status === \"failed\").length;\n const firstFailed = iterations.find((it) => it.status === \"failed\");\n const defaultIndex = firstFailed?.index ?? iterations[iterations.length - 1]?.index;\n\n const bodyIds: string[] = [];\n const labels = new Map<string, string>();\n for (const s of chronologicalSteps(iterations.flatMap((it) => it.steps))) {\n if (!labels.has(s.id)) {\n bodyIds.push(s.id);\n labels.set(s.id, s.label ?? s.id);\n }\n }\n const failedId =\n firstFailed?.failedNodeId ?? firstFailed?.steps.find((s) => s.status === \"failed\")?.id;\n\n return (\n <div className=\"w6w-execution-log-foreach w6w-stack\">\n <div className=\"w6w-small\" data-testid=\"execution-log-foreach-summary\">\n <span>\n {total === 1 ? \"1 item\" : `${total} items`}\n {failedCount > 0 ? ` · ${failedCount} failed` : \"\"}\n </span>\n {firstFailed && failedId !== undefined && (\n <div>\n {labels.get(failedId) ?? failedId} failed in iteration {firstFailed.index}\n </div>\n )}\n {step.iterationsTruncated === true && (\n <div className=\"w6w-muted\">{`showing ${iterations.length} of ${total}`}</div>\n )}\n </div>\n <div className=\"w6w-execution-log-iteration-chips\">\n {iterations.map((it) => (\n <span\n key={it.index}\n className={`w6w-execution-log-iteration-chip w6w-execution-log-iteration-chip-${it.status}`}\n data-testid=\"execution-log-iteration-chip\"\n data-status={it.status}\n >\n {it.index} · {it.status}\n </span>\n ))}\n </div>\n <ul className=\"w6w-execution-log-subrows\">\n {bodyIds.map((id) => (\n <ExecutionLogBodyStep\n key={id}\n id={id}\n label={labels.get(id) ?? id}\n iterations={iterations}\n initial={defaultIndex}\n />\n ))}\n </ul>\n </div>\n );\n}\n\nfunction ExecutionLogBodyStep({\n id,\n label,\n iterations,\n initial,\n}: {\n id: string;\n label: string;\n iterations: ExecutionLogIteration[];\n initial: number | undefined;\n}) {\n const [selected, setSelected] = useState<number | undefined>(initial);\n const record = iterations.find((it) => it.index === selected)?.steps.find((s) => s.id === id);\n return (\n <li className=\"w6w-execution-log-subrow w6w-stack\">\n <div className=\"w6w-execution-log-subrow-head\">\n <strong className=\"w6w-small\">{label}</strong>\n <select\n className=\"w6w-select\"\n aria-label={`Iteration for ${label}`}\n data-testid=\"execution-log-iteration-select\"\n value={selected === undefined ? \"\" : String(selected)}\n onChange={(e) => setSelected(Number(e.currentTarget.value))}\n >\n {iterations.map((it) => (\n <option key={it.index} value={String(it.index)}>\n {`iteration ${it.index} (${it.status})`}\n </option>\n ))}\n </select>\n </div>\n {record ? (\n <ol className=\"w6w-execution-log\">\n <ExecutionLogRow key={selected} step={record} />\n </ol>\n ) : (\n <p className=\"w6w-muted w6w-small\">Did not run in this iteration.</p>\n )}\n </li>\n );\n}\n\n/**\n * `TriggerFillForm`'s StepError visual, reused rather than re-invented: the\n * `.w6w-result.w6w-error` box, an optional muted `<code>` line, then the\n * message. `label` (recorded step errors only) names the step on a line above.\n * The code line's spacing lives in `_execution-log.scss` as tokens instead of\n * `TriggerFillForm`'s inline style — same values (`0.75` opacity, a 4px gap).\n */\nfunction ExecutionLogErrorBlock({ error, label }: { error: ExecutionLogError; label?: string }) {\n return (\n <div className=\"w6w-result w6w-error\">\n {label !== undefined && <strong className=\"w6w-execution-log-error-label\">{label}</strong>}\n {error.code && (\n <div className=\"w6w-small w6w-execution-log-error-code\">\n <code>{error.code}</code>\n </div>\n )}\n {error.message}\n </div>\n );\n}\n\n/**\n * \"started / finished, or elapsed\" (A2): both timestamps render verbatim\n * plus the computed elapsed duration between them; only `startedAt` renders\n * as \"Started <ts>\"; neither renders as a plain dash. Never a live-ticking\n * clock — a `setInterval` would make this component a timer owner rather\n * than a pure function of its props.\n */\nfunction StepTiming({ startedAt, finishedAt }: { startedAt?: string; finishedAt?: string }) {\n if (startedAt && finishedAt) {\n const elapsed = formatElapsed(startedAt, finishedAt);\n return (\n <span className=\"w6w-execution-log-timing\">\n {startedAt} → {finishedAt}\n {elapsed && <span> ({elapsed})</span>}\n </span>\n );\n }\n if (startedAt) {\n return <span className=\"w6w-execution-log-timing\">Started {startedAt}</span>;\n }\n return <span className=\"w6w-execution-log-timing\">—</span>;\n}\n\nfunction formatElapsed(startedAt: string, finishedAt: string): string | null {\n const startMs = Date.parse(startedAt);\n const endMs = Date.parse(finishedAt);\n if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || endMs < startMs) return null;\n const ms = endMs - startMs;\n if (ms < 1000) return `${ms}ms`;\n const totalSeconds = ms / 1000;\n if (totalSeconds < 60) return `${totalSeconds.toFixed(1)}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = Math.round(totalSeconds % 60);\n return `${minutes}m ${seconds}s`;\n}\n\n/** Each payload starts collapsed and mounts its read-only JSON tree on demand.\n * The shared viewer provides key folding, Expand/Collapse all and full-value copy.\n * Force JSON so an output string stays a string, even when it contains HTML or JSON text. */\nfunction ExecutionLogJson({ title, value }: { title: string; value: unknown }) {\n const [open, setOpen] = useState(false);\n if (value === undefined) {\n return (\n <div className=\"w6w-execution-log-json w6w-stack\">\n <strong className=\"w6w-small\">{title}</strong>\n <p className=\"w6w-muted w6w-small\">Not available.</p>\n </div>\n );\n }\n return (\n <details\n className=\"w6w-execution-log-json\"\n open={open}\n onToggle={(e) => {\n if (e.target === e.currentTarget) setOpen(e.currentTarget.open);\n }}\n >\n <summary>\n <strong className=\"w6w-small\">{title}</strong>\n </summary>\n {open && <ResultViewer value={value} format=\"json\" />}\n </details>\n );\n}\n\ninterface ConditionRow {\n left: unknown;\n op: string;\n right: unknown;\n result: boolean;\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** The engine's `{ conditions, combinator? }` trace on a record, if it carries one, with the\n * record's own resolved `condition` as the overall result. */\nfunction conditionTrace(\n v: unknown,\n): { rows: ConditionRow[]; combinator?: string; result?: boolean } | undefined {\n if (!isRecord(v) || !Array.isArray(v.conditions)) return;\n const rows = v.conditions.filter(\n (r): r is ConditionRow => isRecord(r) && typeof r.op === \"string\" && \"result\" in r,\n );\n if (rows.length === 0) return;\n return {\n rows,\n combinator: typeof v.combinator === \"string\" ? v.combinator : undefined,\n result: typeof v.condition === \"boolean\" ? v.condition : undefined,\n };\n}\n\n/**\n * An If / Stop workflow / Router input's resolved comparisons as a left | operator | right |\n * result table — what was compared, not only `condition: true`. The engine records them\n * beside the boolean (`{ conditions: [{ left, op, right, result }], combinator? }`; a Router\n * per route); a record without that trace renders nothing, and the raw Input below still\n * shows everything.\n */\nfunction ExecutionLogConditions({ input }: { input: unknown }) {\n const groups: { title?: string; trace: NonNullable<ReturnType<typeof conditionTrace>> }[] = [];\n const own = conditionTrace(input);\n if (own) groups.push({ trace: own });\n if (isRecord(input) && Array.isArray(input.routes)) {\n for (const route of input.routes) {\n const trace = conditionTrace(route);\n if (!trace || !isRecord(route)) continue;\n groups.push({ title: String(route.label ?? route.id ?? \"Route\"), trace });\n }\n }\n if (groups.length === 0) return null;\n return (\n <div className=\"w6w-execution-log-json w6w-stack\" data-testid=\"execution-log-conditions\">\n <strong className=\"w6w-small\">Condition</strong>\n {groups.map(({ title, trace }, g) => (\n <div key={title ?? g} className=\"w6w-stack\">\n {title && <span className=\"w6w-small w6w-muted\">{title}</span>}\n {((trace.combinator && trace.rows.length > 1) || trace.result !== undefined) && (\n <span className=\"w6w-small w6w-muted\" data-testid=\"execution-log-condition-summary\">\n {trace.combinator &&\n trace.rows.length > 1 &&\n conditionCombinatorLabel(trace.combinator)}\n {trace.combinator && trace.rows.length > 1 && trace.result !== undefined && \" · \"}\n {trace.result !== undefined && (\n <>\n Result:{\" \"}\n <span\n className={\n trace.result\n ? \"w6w-execution-log-condition-true\"\n : \"w6w-execution-log-condition-false\"\n }\n >\n {trace.result ? \"true\" : \"false\"}\n </span>\n </>\n )}\n </span>\n )}\n <div className=\"w6w-data-table-frame\">\n <table className=\"w6w-data-table w6w-execution-log-conditions\">\n <thead>\n <tr>\n <th>Left</th>\n <th>Operator</th>\n <th>Right</th>\n <th>Result</th>\n </tr>\n </thead>\n <tbody>\n {trace.rows.map((row, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and never reorder.\n <tr key={i}>\n <td>\n <code>{operandText(row.left)}</code>\n </td>\n <td>{conditionOperatorLabel(row.op)}</td>\n <td>\n <code>{operandText(row.right)}</code>\n </td>\n <td\n className={\n row.result\n ? \"w6w-execution-log-condition-true\"\n : \"w6w-execution-log-condition-false\"\n }\n >\n {row.result ? \"true\" : \"false\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n ))}\n </div>\n );\n}\n\n/** A resolved operand as JSON, so `\"\"`, `\"5\"` vs `5` and `null` read apart. */\nfunction operandText(value: unknown): string {\n return JSON.stringify(value) ?? \"undefined\";\n}\n\n/** Plain-language text for each state-write warning code — never the raw code. */\nconst STATE_WARNING_LABELS: Record<StateWarningCode, string> = {\n not_object: \"Not written — the output isn't an object, so it can't be merged at the root\",\n missing_source: \"Not written — the output has no value at that field\",\n null_append: \"Not appended — the value was null\",\n append_not_array: \"Not appended — the existing value isn't a list\",\n write_too_large: \"Not written — the value is too large\",\n run_too_large: \"Not written — the run's state would grow past its size limit\",\n too_deep: \"Not written — the value is nested too deeply\",\n key_too_long: \"Not written — a key in the value is too long\",\n forbidden_key: \"Not written — the value uses a reserved key name\",\n log_truncated: \"Later state changes aren't shown — the run's state log reached its limit\",\n};\n\nfunction stateWarningLabel(code: string): string {\n return Object.hasOwn(STATE_WARNING_LABELS, code)\n ? STATE_WARNING_LABELS[code as StateWarningCode]\n : code;\n}\n\nfunction hasStateBlock(step: ExecutionLogStep): boolean {\n const hasWrites = Array.isArray(step.stateWrites) && step.stateWrites.length > 0;\n const after = step.stateAfter;\n const hasAfter = typeof after === \"object\" && after !== null;\n return hasWrites || (hasAfter && Object.keys(after).length > 0);\n}\n\nconst STATE_VALUE_MAX = 120;\n\nfunction stateValueText(v: unknown): string {\n if (v === undefined) return \"(not set)\";\n const text = JSON.stringify(v) ?? String(v);\n return text.length > STATE_VALUE_MAX ? `${text.slice(0, STATE_VALUE_MAX)}…` : text;\n}\n\n/**\n * The State block: one row per state write in the order the run recorded them\n * (`state.<path>: old → new`, or the warning that stopped it), then the run's\n * state tree after this step. Rendered only when there is something to show.\n */\nfunction ExecutionLogState({ step }: { step: ExecutionLogStep }) {\n const writes = Array.isArray(step.stateWrites) ? step.stateWrites : [];\n const after = step.stateAfter;\n return (\n <div className=\"w6w-execution-log-state w6w-stack\" data-testid=\"execution-log-state\">\n <strong className=\"w6w-small\">State</strong>\n {writes.length > 0 && (\n <ul className=\"w6w-execution-log-state-writes\">\n {writes.map((w, i) => {\n const path = Array.isArray(w.path) ? w.path : [];\n const label = `state${path.length ? `.${path.join(\".\")}` : \"\"}${w.item !== undefined ? ` (item ${w.item})` : \"\"}`;\n return w.warning !== undefined ? (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional, never reordered\n key={i}\n className=\"w6w-execution-log-state-write w6w-execution-log-state-warning w6w-small\"\n data-testid=\"execution-log-state-write\"\n data-warning={w.warning}\n >\n {`${label}: ${stateWarningLabel(w.warning)}`}\n </li>\n ) : (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional, never reordered\n key={i}\n className=\"w6w-execution-log-state-write w6w-small\"\n data-testid=\"execution-log-state-write\"\n >\n {`${label}: ${stateValueText(w.old)} → ${stateValueText(w.new)}`}\n </li>\n );\n })}\n </ul>\n )}\n {typeof after === \"object\" && after !== null && (\n <div className=\"w6w-stack\" data-testid=\"execution-log-state-after\">\n <span className=\"w6w-small w6w-muted\">State after this step</span>\n <CodeBlock code={JSON.stringify(after, null, 2)} language=\"json\" />\n </div>\n )}\n </div>\n );\n}\n","import type { ExecutionKind } from \"./ExecutionList.tsx\";\nimport type { ExecutionStatus } from \"./StepStatusPill.tsx\";\n\n/**\n * The filter/search state of the history view — one plain object, owned by the\n * HOST. This component is fully controlled: it holds no state of its own, it\n * only renders `value` and reports the next one. Same \"host owns the data, the\n * control is presentational\" split `ExecutionList` establishes, and the same\n * reason: the host owns where the filters live (URL search params today, a\n * query cache tomorrow) and this leaf must not disagree with it.\n */\nexport interface ExecutionFilterValue {\n /** `\"\"` = \"no status filter\" (the `Any status` option), never `null`. */\n status: ExecutionStatus | \"\";\n /** `\"\"` = \"no kind filter\" (the `Any type` option). Only reachable when the\n * host renders the kind select (`showKind`). */\n kind: ExecutionKind | \"\";\n /** Inclusive lower bound on the run's start, as `YYYY-MM-DD` — exactly what\n * `input[type=date]` reports and accepts. `\"\"` = unbounded. */\n from: string;\n /** Inclusive upper bound on the run's start, same format. `\"\"` = unbounded. */\n to: string;\n /** Free-text query. D3: the server matches execution id + callable name/key,\n * never payload JSON. */\n q: string;\n}\n\nexport interface ExecutionFiltersProps {\n /** The current filter state — rendered verbatim, never re-derived. */\n value: ExecutionFilterValue;\n /** Called ONCE per user interaction with the ONE field that changed:\n * `{ ...value, <that field>: next }`. No debounce, no batching — the host\n * decides when a request is worth making (it may debounce `q` itself). */\n onChange: (next: ExecutionFilterValue) => void;\n /** `true` ⇒ the kind select renders between the status select and the date\n * bounds. Defaults to `false`: the per-callable history view already knows\n * the kind, so a kind filter there would be a control of one option. */\n showKind?: boolean;\n /** Placeholder for the search box. Defaults to `\"Search by id or name\"` —\n * the same two fields D3 pins the server-side search to. */\n searchPlaceholder?: string;\n /** `true` ⇒ every control (the clear button included) renders disabled — the\n * state a host uses while a request is already in flight. */\n disabled?: boolean;\n}\n\n/** The \"nothing filtered\" state — what Clear reports, and what a host starts\n * from. Kept module-local: it is one object literal, and a host that needs its\n * own initial value should own it (it must be encoded into a URL anyway). */\nconst EMPTY: ExecutionFilterValue = { status: \"\", kind: \"\", from: \"\", to: \"\", q: \"\" };\n\n/** `\"\"` first (the \"any\" option), then one entry per run state, capitalised. */\nconst STATUS_OPTIONS: Array<{ value: ExecutionStatus | \"\"; label: string }> = [\n { value: \"\", label: \"Any status\" },\n { value: \"queued\", label: \"Queued\" },\n { value: \"running\", label: \"Running\" },\n { value: \"succeeded\", label: \"Succeeded\" },\n { value: \"failed\", label: \"Failed\" },\n { value: \"canceled\", label: \"Canceled\" },\n];\n\nconst KIND_OPTIONS: Array<{ value: ExecutionKind | \"\"; label: string }> = [\n { value: \"\", label: \"Any type\" },\n { value: \"function\", label: \"Function\" },\n { value: \"endpoint\", label: \"Endpoint\" },\n { value: \"workflow\", label: \"Workflow\" },\n];\n\n/**\n * The history view's filter/search bar: free text, status, (optionally) kind,\n * and a start-date window, plus a Clear control that appears only once there is\n * something to clear.\n *\n * A pure controlled leaf. Every change reports exactly one field's new value,\n * spread over the value it was given — a control that rebuilt the whole object\n * would silently drop a sibling filter the moment the two are edited close\n * together, and the host is the only party that knows the authoritative value.\n *\n * Each control carries its own `aria-label`: the visible layout is one dense\n * row of heterogeneous controls (a search box, three or four dropdowns, two\n * date pickers) with no room for a label per control, so the accessible name is\n * what tells them apart.\n */\nexport function ExecutionFilters({\n value,\n onChange,\n showKind = false,\n searchPlaceholder = \"Search by id or name\",\n disabled = false,\n}: ExecutionFiltersProps) {\n const clearable =\n value.status !== \"\" ||\n value.kind !== \"\" ||\n value.from !== \"\" ||\n value.to !== \"\" ||\n value.q !== \"\";\n\n return (\n <div className=\"w6w-execution-filters\" data-testid=\"execution-filters\">\n <input\n type=\"search\"\n className=\"w6w-execution-filters-search\"\n data-testid=\"execution-filter-q\"\n aria-label=\"Search executions\"\n placeholder={searchPlaceholder}\n value={value.q}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, q: e.target.value })}\n />\n <select\n className=\"w6w-execution-filters-select\"\n data-testid=\"execution-filter-status\"\n aria-label=\"Status\"\n value={value.status}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, status: e.target.value as ExecutionStatus | \"\" })}\n >\n {STATUS_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {showKind && (\n <select\n className=\"w6w-execution-filters-select\"\n data-testid=\"execution-filter-kind\"\n aria-label=\"Type\"\n value={value.kind}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, kind: e.target.value as ExecutionKind | \"\" })}\n >\n {KIND_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n )}\n <input\n type=\"date\"\n className=\"w6w-execution-filters-date\"\n data-testid=\"execution-filter-from\"\n aria-label=\"From date\"\n value={value.from}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, from: e.target.value })}\n />\n <input\n type=\"date\"\n className=\"w6w-execution-filters-date\"\n data-testid=\"execution-filter-to\"\n aria-label=\"To date\"\n value={value.to}\n disabled={disabled}\n onChange={(e) => onChange({ ...value, to: e.target.value })}\n />\n {clearable && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-execution-filters-clear\"\n data-testid=\"execution-filter-clear\"\n disabled={disabled}\n onClick={() => onChange({ ...EMPTY })}\n >\n Clear\n </button>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { formatDurationMs } from \"./execution-format.ts\";\n\n/**\n * The aggregate numbers of a history view — the same rows the list shows,\n * rolled up (D1: stats are computed over the same visibility the list uses, so\n * the two can never disagree about who may see what).\n *\n * `succeeded`/`canceled` are carried even though the strip renders no card for\n * them today: the host's payload has them, the breakdown is what a host needs\n * for a chart or a chip row, and a host re-deriving them from the list would be\n * computing the same total a second time.\n */\nexport interface ExecutionStatsValue {\n /** Every run in the current filter — the denominator of `successRate`. */\n total: number;\n succeeded: number;\n failed: number;\n canceled: number;\n /** Runs that are queued or running right now. `> 0` is what makes the\n * `In flight` card exist at all. */\n inFlight: number;\n /** `0…1`, or `null` when the host has no rate to report (no runs at all —\n * a rate over zero runs is not 0%). */\n successRate: number | null;\n /** Mean wall-clock duration of the FINISHED runs, or `null` when none has\n * finished. */\n avgDurationMs: number | null;\n}\n\nexport interface ExecutionStatsProps {\n /** The aggregate, or `null` while nothing has loaded yet — rendered as `—`\n * per card rather than as a spinner, so the strip never changes height. */\n stats: ExecutionStatsValue | null;\n /** Caption above the cards, e.g. the window they cover (\"Last 7 days\").\n * Omitted ⇒ no node at all. */\n label?: ReactNode;\n}\n\n/** What an absent/unknown number renders as — never `0`, which would read as a\n * measured result. Same em dash `execution-format.ts` uses for the same\n * reason. */\nconst UNKNOWN = \"—\";\n\ninterface Card {\n testid: string;\n label: string;\n value: string;\n}\n\n/**\n * A headline strip of run aggregates: one big value over a muted label per\n * card.\n *\n * Promotes studio `DashboardPage.tsx`'s page-local `StatCard` into `ui`, with\n * two differences that come from this being a shared component rather than one\n * page's private helper: the values are pre-formatted here (a rate as `67%`, a\n * duration through `formatDurationMs`) so every consumer renders the same\n * string, and each card carries `data-stat-value` so a host can assert on the\n * value without re-parsing its own formatting.\n */\nexport function ExecutionStats({ stats, label }: ExecutionStatsProps) {\n const cards: Card[] = [\n {\n testid: \"execution-stat-total\",\n label: \"Executions\",\n value: stats ? String(stats.total) : UNKNOWN,\n },\n {\n testid: \"execution-stat-success-rate\",\n label: \"Success rate\",\n value: formatSuccessRate(stats?.successRate),\n },\n {\n testid: \"execution-stat-failed\",\n label: \"Failed\",\n value: stats ? String(stats.failed) : UNKNOWN,\n },\n {\n testid: \"execution-stat-avg-duration\",\n label: \"Avg duration\",\n value: stats ? formatDurationMs(stats.avgDurationMs) : UNKNOWN,\n },\n ];\n\n // The one CONDITIONAL card: a zero in-flight count is the steady state, and a\n // permanent \"In flight 0\" would draw the eye to the least interesting number\n // in the strip. A missing `stats` counts as zero, so the strip keeps four\n // cards while loading instead of five-then-four.\n if (stats && stats.inFlight > 0) {\n cards.push({\n testid: \"execution-stat-in-flight\",\n label: \"In flight\",\n value: String(stats.inFlight),\n });\n }\n\n return (\n <section className=\"w6w-execution-stats\" data-testid=\"execution-stats\">\n {label != null && <p className=\"w6w-execution-stats-label\">{label}</p>}\n <div className=\"w6w-execution-stats-cards\">\n {cards.map((card) => (\n <div key={card.testid} className=\"w6w-execution-stat\" data-testid={card.testid}>\n <span className=\"w6w-execution-stat-value\" data-stat-value={card.value}>\n {card.value}\n </span>\n <span className=\"w6w-execution-stat-label\">{card.label}</span>\n </div>\n ))}\n </div>\n </section>\n );\n}\n\n/**\n * A `0…1` rate as a whole-percent string (`0.666…` → `\"67%\"`, rounded rather\n * than floored so `2/3` does not read as `66%`).\n *\n * `null` (nothing to report) and a non-finite rate (a host dividing by zero\n * somewhere upstream) are both `—` — the same totality `formatDurationMs`\n * keeps, so no input can render `NaN%`.\n */\nfunction formatSuccessRate(rate: number | null | undefined): string {\n if (rate == null || !Number.isFinite(rate)) return UNKNOWN;\n return `${Math.round(rate * 100)}%`;\n}\n","import type { ReactNode } from \"react\";\nimport { CodeBlock } from \"../CodeBlock.tsx\";\nimport type { ExecutionKind } from \"./ExecutionList.tsx\";\nimport { ExecutionLogPanel } from \"./ExecutionLogPanel.tsx\";\nimport type { ExecutionLogStep } from \"./ExecutionLogPanel.tsx\";\nimport { Icon } from \"./Icon.tsx\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { StepStatusPill } from \"./StepStatusPill.tsx\";\nimport type { ExecutionStatus } from \"./StepStatusPill.tsx\";\nimport { formatDurationMs, formatExecutionTime } from \"./execution-format.ts\";\n\n/**\n * One past execution in full — an already-mapped slice of the host's history\n * payload, the detail-level sibling of `ExecutionListItem`. The HOST maps its\n * own record into this shape; this component never fetches, polls or reaches\n * for an SDK.\n *\n * D2: there is no log-line field anywhere in this shape, on purpose — \"logs\"\n * for an execution ARE its status, timing, input, output and error, and for a\n * workflow that is the per-step `steps` list below.\n */\nexport interface ExecutionDetailValue {\n id: string;\n kind: ExecutionKind;\n callableName: string;\n status: ExecutionStatus;\n /** ISO-8601 instant the run started. */\n startedAt: string;\n /** ISO-8601 instant the run finished, or `null` while it is still\n * queued/running (rendered as `—`). */\n finishedAt: string | null;\n /** Wall-clock duration once the run has finished, or `null` while it has not\n * (rendered as `—`). */\n durationMs: number | null;\n /** The run's own input, once it is known. `undefined` = \"not available\" (no\n * section); `null` = \"available, and it is null\" (section renders `null`). */\n input?: unknown;\n output?: unknown;\n /** The failure's payload for a failed run. `null`/`undefined` = no error\n * section at all — the reverse gate to `input`/`output`, because an error\n * that is `null` is the absence of an error. */\n error?: unknown;\n /** A workflow run's steps. `undefined` = not a step-bearing run (no section);\n * `[]` = it ran and no step did (the panel's own empty state). */\n steps?: ExecutionLogStep[];\n /** The execution this one is a re-run of — shown as \"Re-run of <id>\".\n * `null`/omitted ⇒ an ordinary execution, no line. */\n rerunOf?: string | null;\n}\n\nexport interface ExecutionDetailProps {\n /** The execution to show, or `null` when there is nothing to show yet. */\n execution: ExecutionDetailValue | null;\n /** `true` while the fetch for a `null` `execution` is still in flight —\n * renders the loading branch. Once an `execution` is present it is rendered\n * as-is: a host re-fetching (polling a running run) keeps showing the last\n * known state rather than flashing back to \"Loading…\". */\n loading?: boolean;\n /** A failure to surface, e.g. the fetch for this execution failed. Rendered\n * as an alert in EVERY branch — it is about the view, not about the run. */\n errorMessage?: ReactNode;\n /** Supplied ⇒ a dismiss control renders and calls this. Omitted ⇒ no\n * control. */\n onClose?: () => void;\n /** Supplied ⇒ the \"Open in visual editor\" button renders and calls this.\n * Omitted ⇒ no button (a function/endpoint run has no visual editor to open). */\n onOpenInEditor?: () => void;\n /** Supplied ⇒ a \"Back\" control renders above everything else and calls this\n * — for a host that shows this detail IN PLACE of the list it was opened\n * from. Omitted ⇒ no control. Rendered in every branch, so a view whose\n * fetch failed can still be left. */\n onBack?: () => void;\n /** Supplied ⇒ the \"Re-run\" button renders and calls this. Omitted ⇒ no button. */\n onRerun?: () => void;\n /** `true` while the host's re-run is in flight — the button is disabled and\n * says so. */\n rerunning?: boolean;\n /** Supplied ⇒ the \"Re-run of <id>\" id is a link that calls this with that\n * id, to open the original. Omitted ⇒ plain text. */\n onOpenExecution?: (id: string) => void;\n}\n\nconst KIND_LABEL: Record<ExecutionKind, string> = {\n function: \"Function\",\n endpoint: \"Endpoint\",\n workflow: \"Workflow\",\n};\n\n/** A value the section is showing that JSON cannot serialise (`undefined`,\n * a function, a symbol) renders as `null` rather than an empty block. */\nfunction toJson(value: unknown): string {\n return JSON.stringify(value, null, 2) ?? \"null\";\n}\n\n/**\n * Everything known about one past execution: which callable it was and how it\n * went, its timing, its own input/output/error, and — for a workflow run — the\n * per-step list.\n *\n * The per-step list sits directly under the timing, above the run's own\n * payloads: for a workflow it is the substance of the view (D2), and burying it\n * under three JSON blocks would make the run read as a function call with\n * appendices.\n *\n * A pure display leaf — no fetching, no polling, no live-ticking timer.\n */\nexport function ExecutionDetail({\n execution,\n loading = false,\n errorMessage,\n onClose,\n onOpenInEditor,\n onBack,\n onRerun,\n rerunning = false,\n onOpenExecution,\n}: ExecutionDetailProps) {\n return (\n <section className=\"w6w-execution-detail w6w-stack\" data-testid=\"execution-detail\">\n {onBack && (\n <div className=\"w6w-execution-detail-back\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-detail-back\"\n onClick={onBack}\n >\n <span aria-hidden=\"true\">←</span> Back\n </button>\n </div>\n )}\n {errorMessage != null && (\n <p\n role=\"alert\"\n className=\"w6w-execution-detail-error-message\"\n data-testid=\"execution-detail-error-message\"\n >\n {errorMessage}\n </p>\n )}\n {execution ? (\n <Body\n execution={execution}\n onClose={onClose}\n onOpenInEditor={onOpenInEditor}\n onRerun={onRerun}\n rerunning={rerunning}\n onOpenExecution={onOpenExecution}\n />\n ) : loading ? (\n <p className=\"w6w-muted\" data-testid=\"execution-detail-loading\">\n Loading…\n </p>\n ) : (\n <p className=\"w6w-muted\" data-testid=\"execution-detail-empty\">\n No execution selected.\n </p>\n )}\n </section>\n );\n}\n\nfunction Body({\n execution,\n onClose,\n onOpenInEditor,\n onRerun,\n rerunning,\n onOpenExecution,\n}: {\n execution: ExecutionDetailValue;\n onClose?: () => void;\n onOpenInEditor?: () => void;\n onRerun?: () => void;\n rerunning: boolean;\n onOpenExecution?: (id: string) => void;\n}) {\n const rerunOf = execution.rerunOf;\n return (\n <>\n <div className=\"w6w-execution-detail-head\">\n <div className=\"w6w-execution-detail-title\">\n <h3 className=\"w6w-execution-detail-name\">{execution.callableName}</h3>\n <div className=\"w6w-execution-detail-meta\">\n <StepStatusPill state={execution.status} />\n <span className=\"w6w-execution-detail-kind w6w-muted w6w-small\">\n {KIND_LABEL[execution.kind]}\n </span>\n </div>\n </div>\n {(onRerun || onOpenInEditor || onClose) && (\n <div className=\"w6w-execution-detail-actions\">\n {onRerun && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-execution-detail-rerun\"\n data-testid=\"execution-detail-rerun\"\n title=\"Run it again with the same input\"\n disabled={rerunning}\n onClick={onRerun}\n >\n <Icon name=\"sync\" size={14} /> {rerunning ? \"Re-running…\" : \"Re-run\"}\n </button>\n )}\n {onOpenInEditor && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"execution-detail-open-editor\"\n onClick={onOpenInEditor}\n >\n Open in visual editor\n </button>\n )}\n {onClose && (\n <IconButton label=\"Close\" data-testid=\"execution-detail-close\" onClick={onClose}>\n ×\n </IconButton>\n )}\n </div>\n )}\n </div>\n\n <p className=\"w6w-execution-detail-id-line\">\n <code className=\"w6w-execution-detail-id\" data-testid=\"execution-detail-id\">\n {execution.id}\n </code>\n </p>\n\n {rerunOf && (\n <p className=\"w6w-execution-detail-rerun-of\" data-testid=\"execution-detail-rerun-of\">\n <span className=\"w6w-execution-rerun-tag\">Re-run</span>\n <span className=\"w6w-muted w6w-small\">of</span>\n {onOpenExecution ? (\n <button\n type=\"button\"\n className=\"w6w-execution-detail-rerun-of-link\"\n data-testid=\"execution-detail-rerun-of-link\"\n onClick={() => onOpenExecution(rerunOf)}\n >\n <code>{rerunOf}</code>\n </button>\n ) : (\n <code>{rerunOf}</code>\n )}\n </p>\n )}\n\n <dl className=\"w6w-execution-detail-timing\">\n <TimingItem label=\"Started\" value={formatExecutionTime(execution.startedAt)} />\n <TimingItem\n label=\"Finished\"\n value={execution.finishedAt ? formatExecutionTime(execution.finishedAt) : \"—\"}\n />\n <TimingItem label=\"Duration\" value={formatDurationMs(execution.durationMs)} />\n </dl>\n\n {execution.steps !== undefined && (\n <section\n className=\"w6w-execution-detail-section w6w-stack\"\n data-testid=\"execution-detail-steps\"\n >\n <strong className=\"w6w-small\">Nodes</strong>\n <ExecutionLogPanel steps={execution.steps} emptyLabel=\"No nodes ran.\" />\n </section>\n )}\n\n {execution.input !== undefined && (\n <JsonSection title=\"Input\" testid=\"execution-detail-input\" value={execution.input} />\n )}\n {execution.output !== undefined && (\n <JsonSection title=\"Output\" testid=\"execution-detail-output\" value={execution.output} />\n )}\n {execution.error != null && (\n <JsonSection title=\"Error\" testid=\"execution-detail-error\" value={execution.error} />\n )}\n </>\n );\n}\n\nfunction TimingItem({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"w6w-execution-detail-timing-item\">\n <dt>{label}</dt>\n <dd>{value}</dd>\n </div>\n );\n}\n\n/**\n * One payload as read-only, syntax-highlighted JSON — `CodeBlock`, the same\n * idiom `ExecutionLogPanel` renders a step's input/output through (see its own\n * doc comment for why `CodeBlock` and not `JsonEditor`/`<pre>`).\n */\nfunction JsonSection({ title, testid, value }: { title: string; testid: string; value: unknown }) {\n return (\n <section className=\"w6w-execution-detail-section w6w-stack\" data-testid={testid}>\n <strong className=\"w6w-small\">{title}</strong>\n <CodeBlock code={toJson(value)} language=\"json\" />\n </section>\n );\n}\n","/**\n * How the reliability board arranges itself — the decisions that are arithmetic\n * rather than markup, kept pure (no React, no DOM) so they test without a DOM\n * and so `@w6w/embed` can import them beside the components.\n *\n * **None of these decide a STATE.** Every state read below arrived already\n * decided by the server; nothing here compares a ratio, applies a threshold to\n * call data, or invents a fifth word. What these decide is where a row is PUT,\n * which is presentation.\n */\n\n/** The four words the server uses for a health verdict. */\nexport type ReliabilityViewState = \"ok\" | \"degraded\" | \"down\" | \"unknown\";\n\n/**\n * The row shape the reliability components render — owned by `@w6w/ui` so it\n * imports nothing from the SDK. The SDK's `ReliabilityService` assigns to it\n * structurally; the generic functions below keep the caller's richer row type.\n */\nexport interface ReliabilityServiceView {\n appId: string;\n displayName: string;\n /** Inline icon fields — the board never asks a catalog for them. */\n iconSrc?: string;\n iconSrcDark?: string;\n brandColor?: string;\n /** \"Did YOUR calls succeed\". */\n state: ReliabilityViewState;\n calls: number;\n errors: { e4xx: number; e429: number; eAuth: number; e5xx: number };\n p95Ms: number | null;\n ongoingOutageId: string | null;\n /** One entry per calendar day, oldest first, exactly as the server sent it. */\n uptime: readonly { day: string; state: ReliabilityViewState }[];\n /** \"What does the vendor say about itself\"; `null` when no public check exists. */\n vendorStatus: { state: ReliabilityViewState; message: string | null } | null;\n /** The server's tier for the row — read, never re-derived. */\n attention: \"now\" | \"recent\" | \"none\";\n}\n\n/** One point of the performance scatter — a service with both a call volume and a measured p95. */\nexport interface PerformancePoint {\n appId: string;\n displayName: string;\n calls: number;\n p95Ms: number;\n state: ReliabilityViewState;\n /** Total errors across all four kinds — drives the point's size, not its position. */\n errorCount: number;\n}\n\n/**\n * Every service with at least one timed call, as a (calls, p95) point — what\n * the performance chart plots. Excludes `p95Ms: null`: there is no Y position\n * for a service with nothing timed.\n */\nexport function performancePoints(services: readonly ReliabilityServiceView[]): PerformancePoint[] {\n const points: PerformancePoint[] = [];\n for (const s of services) {\n if (s.p95Ms === null) continue;\n points.push({\n appId: s.appId,\n displayName: s.displayName,\n calls: s.calls,\n p95Ms: s.p95Ms,\n state: s.state,\n errorCount: s.errors.e4xx + s.errors.e429 + s.errors.eAuth + s.errors.e5xx,\n });\n }\n return points;\n}\n\n/**\n * Does this service want the reader's attention? READS the tier the server\n * sent (`attention`), never re-derives it from `state` or `vendorStatus`: the\n * server's `boardRank` is the one implementation, and a second copy here would\n * drift. `now` and `recent` both count; they differ in tense only.\n */\nexport function needsAttention(service: Pick<ReliabilityServiceView, \"attention\">): boolean {\n return service.attention === \"now\" || service.attention === \"recent\";\n}\n\n/** The board in its three groups, each keeping the server's own ordering. */\nexport interface BoardPartition<T extends ReliabilityServiceView = ReliabilityServiceView> {\n /** Broken right now, on either signal. */\n now: T[];\n /** Clear now, but this window holds a failed stretch or an open advisory. */\n recent: T[];\n /** Everything else, in the server's recency order. */\n clear: T[];\n}\n\n/**\n * Group the board without reordering within any group. Bucketing is not\n * sorting: each group comes out in the order it arrived. An unrecognised\n * `attention` value falls to `clear` rather than throwing — a client can be\n * older than the server that answered it.\n */\nexport function partitionBoard<T extends ReliabilityServiceView>(\n services: readonly T[],\n): BoardPartition<T> {\n const groups: BoardPartition<T> = { now: [], recent: [], clear: [] };\n for (const s of services) {\n if (s.attention === \"now\") groups.now.push(s);\n else if (s.attention === \"recent\") groups.recent.push(s);\n else groups.clear.push(s);\n }\n return groups;\n}\n\n/**\n * The uptime strip's cells for one service — the server's own array, in the\n * order it arrived (oldest first). A passthrough on purpose: no sort, no\n * reverse, no gap filling. The strip has no date axis, so a reversed array is\n * visually plausible and would silently move an outage to the wrong end.\n */\nexport function uptimeDays(service: Pick<ReliabilityServiceView, \"uptime\">): {\n day: string;\n state: ReliabilityViewState;\n}[] {\n return service.uptime.map((entry) => ({ day: entry.day, state: entry.state }));\n}\n\n/** Compact mode shows at most this many needs-attention cards, `now` filling first. */\nexport const ATTENTION_DISPLAY_CAP = 3;\n/** Compact mode shows this many table rows unless the caller passes `limit`. */\nexport const RECENT_DISPLAY_CAP = 5;\n\n/** What the board shows and what a display cap hid. */\nexport interface BoardDisplay<T extends ReliabilityServiceView = ReliabilityServiceView> {\n /** TRUE total of attention rows (the whole input, not the capped slice). */\n attentionCount: number;\n shownNow: T[];\n shownRecent: T[];\n hiddenAttentionCount: number;\n /** Table rows in the server's order, every attention tier included. */\n shownTable: T[];\n hiddenTableCount: number;\n}\n\n/**\n * Apply the display caps to the complete board. Compact: ≤ 3 attention cards\n * (`now` first, `recent` tops up) and `limit ?? 5` table rows; otherwise\n * uncapped. Hidden counts are computed from the full input, so they are real.\n */\nexport function displayBoard<T extends ReliabilityServiceView>(\n services: readonly T[],\n opts: { compact?: boolean; limit?: number } = {},\n): BoardDisplay<T> {\n const compact = opts.compact ?? false;\n const { now, recent } = partitionBoard(services);\n const attentionCount = now.length + recent.length;\n const shownNow = compact ? now.slice(0, ATTENTION_DISPLAY_CAP) : now;\n const shownRecent = compact\n ? recent.slice(0, Math.max(0, ATTENTION_DISPLAY_CAP - shownNow.length))\n : recent;\n const shownTable = compact ? services.slice(0, opts.limit ?? RECENT_DISPLAY_CAP) : [...services];\n return {\n attentionCount,\n shownNow,\n shownRecent,\n hiddenAttentionCount: attentionCount - shownNow.length - shownRecent.length,\n shownTable,\n hiddenTableCount: services.length - shownTable.length,\n };\n}\n","import type { ReactElement, MouseEvent as ReactMouseEvent } from \"react\";\nimport { type ReliabilityServiceView, performancePoints } from \"../reliability-board-layout.ts\";\n\n/**\n * The performance chart — call volume × p95 latency, one point per API. One\n * axis never tells the whole story: a slow service nobody calls much matters\n * less than a slow service taking most of the traffic, so this is a real 2-axis\n * scatter, not a bar-per-app list.\n *\n * Ring colour carries exec status via the `--w6w-health-*` tokens (same as the\n * table's pills) and dot size carries the error count. Rows arrive with every\n * field they need; the chart makes no request.\n *\n * Navigation is the host's: with `getHref` each point is a real SVG `<a href>`;\n * a click calls `onOpen(appId, event)` and is never `preventDefault`ed here.\n * Neither given ⇒ points are not links.\n *\n * A fixed `viewBox` with a matching CSS `aspect-ratio` keeps points circular.\n * The y-axis runs INVERTED — 0ms at the top, the max at the bottom — so \"up\"\n * reads as \"better\" the same way \"right\" (more calls) does: the top-right\n * corner is fast AND heavily used.\n */\nconst WIDTH = 640;\nconst HEIGHT = 340;\nconst PAD = { top: 16, right: 24, bottom: 40, left: 56 };\n\nfunction niceMax(value: number): number {\n if (value <= 0) return 1;\n const magnitude = 10 ** Math.floor(Math.log10(value));\n const steps = [1, 2, 5, 10];\n for (const step of steps) {\n if (value <= step * magnitude) return step * magnitude;\n }\n return 10 * magnitude;\n}\n\nfunction ticks(max: number, count = 5): number[] {\n return Array.from({ length: count + 1 }, (_, i) => Math.round((max * i) / count));\n}\n\nexport interface ReliabilityChartProps<T extends ReliabilityServiceView = ReliabilityServiceView> {\n services: readonly T[];\n /** Real `<a href>` on each point when given. */\n getHref?: (appId: string) => string;\n /** Called on a point click; the host decides whether to `preventDefault`. */\n onOpen?: (appId: string, event: ReactMouseEvent<Element>) => void;\n}\n\nexport function ReliabilityChart<T extends ReliabilityServiceView>({\n services,\n getHref,\n onOpen,\n}: ReliabilityChartProps<T>): ReactElement {\n const points = performancePoints(services);\n\n if (points.length === 0) {\n return <p className=\"w6w-muted w6w-small\">No timed calls in this window yet.</p>;\n }\n\n const maxCalls = niceMax(Math.max(...points.map((p) => p.calls)));\n const maxP95 = niceMax(Math.max(...points.map((p) => p.p95Ms)));\n const maxErrors = Math.max(1, ...points.map((p) => p.errorCount));\n\n const plotW = WIDTH - PAD.left - PAD.right;\n const plotH = HEIGHT - PAD.top - PAD.bottom;\n const x = (calls: number) => PAD.left + (calls / maxCalls) * plotW;\n // Inverted on purpose — lower p95 (faster) sits HIGHER on the plot.\n const y = (p95: number) => PAD.top + (p95 / maxP95) * plotH;\n // 16px..30px icon diameter, scaled by error share.\n const iconSize = (errors: number) => 16 + (errors / maxErrors) * 14;\n\n const xTicks = ticks(maxCalls);\n const yTicks = ticks(maxP95);\n const yAxisTitleX = 18;\n const yAxisTitleY = PAD.top + plotH / 2;\n\n return (\n <div className=\"w6w-rel-scatter\">\n <svg\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n style={{ aspectRatio: `${WIDTH} / ${HEIGHT}` }}\n role=\"img\"\n aria-label=\"API performance: calls versus p95 latency, one point per API\"\n >\n <rect\n x={PAD.left}\n y={PAD.top}\n width={plotW}\n height={plotH}\n className=\"w6w-rel-scatter-plot-bg\"\n />\n\n {yTicks.map((t) => (\n <g key={`y-${t}`}>\n <line\n x1={PAD.left}\n x2={WIDTH - PAD.right}\n y1={y(t)}\n y2={y(t)}\n className=\"w6w-rel-scatter-grid\"\n />\n <text x={PAD.left - 8} y={y(t)} className=\"w6w-rel-scatter-axis-label\" textAnchor=\"end\">\n {t}\n </text>\n </g>\n ))}\n {xTicks.map((t) => (\n <text\n key={`x-${t}`}\n x={x(t)}\n y={HEIGHT - PAD.bottom + 18}\n className=\"w6w-rel-scatter-axis-label\"\n textAnchor=\"middle\"\n >\n {t}\n </text>\n ))}\n\n {/* Anchored on its own pivot so the rotation never leaves the viewBox. */}\n <text\n x={yAxisTitleX}\n y={yAxisTitleY}\n className=\"w6w-rel-scatter-axis-title\"\n textAnchor=\"middle\"\n transform={`rotate(-90, ${yAxisTitleX}, ${yAxisTitleY})`}\n >\n p95 (ms)\n </text>\n <text\n x={PAD.left + plotW / 2}\n y={HEIGHT - 4}\n className=\"w6w-rel-scatter-axis-title\"\n textAnchor=\"middle\"\n >\n calls in this window\n </text>\n\n {points.map((p) => {\n const size = iconSize(p.errorCount);\n const cx = x(p.calls);\n const cy = y(p.p95Ms);\n const dots = (\n <>\n <circle\n cx={cx}\n cy={cy}\n r={size / 2 + 2.5}\n className={`w6w-rel-scatter-ring w6w-rel-scatter-ring-${p.state}`}\n >\n <title>\n {p.displayName} — {p.calls} calls, {p.p95Ms} ms p95, {p.errorCount} errors\n </title>\n </circle>\n <circle\n cx={cx}\n cy={cy}\n r={size / 2}\n className={`w6w-rel-scatter-point w6w-rel-scatter-point-${p.state}`}\n />\n </>\n );\n if (getHref) {\n return (\n <a\n key={p.appId}\n href={getHref(p.appId)}\n className=\"w6w-rel-scatter-point-link\"\n onClick={onOpen ? (e) => onOpen(p.appId, e) : undefined}\n >\n {dots}\n </a>\n );\n }\n if (onOpen) {\n return (\n <g\n key={p.appId}\n // biome-ignore lint/a11y/useSemanticElements: an SVG group cannot be a <button>\n role=\"button\"\n tabIndex={0}\n className=\"w6w-rel-scatter-point-link\"\n onClick={(e) => onOpen(p.appId, e)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n (e.currentTarget as unknown as HTMLElement).dispatchEvent(\n new MouseEvent(\"click\", { bubbles: true }),\n );\n }\n }}\n >\n {dots}\n </g>\n );\n }\n return <g key={p.appId}>{dots}</g>;\n })}\n </svg>\n <p className=\"w6w-muted w6w-small w6w-rel-scatter-note\">\n Up is faster, right is more calls — top-right is the best outcome. Icon size is the error\n count in this window; ring colour is exec status.\n </p>\n </div>\n );\n}\n","import type { MouseEvent, ReactElement, ReactNode } from \"react\";\nimport {\n type ReliabilityServiceView,\n displayBoard,\n uptimeDays,\n} from \"../reliability-board-layout.ts\";\nimport { AppIcon } from \"./AppIcon.tsx\";\nimport { HealthStatusPill } from \"./HealthStatusPill.tsx\";\nimport { ReliabilityChart } from \"./ReliabilityChart.tsx\";\nimport { UptimeStrip } from \"./UptimeStrip.tsx\";\n\n/**\n * The reliability board's presentation: needs-attention cards, the\n * performance chart and the services table, drawn from rows passed in.\n * Router-free and request-free (no provider needed) — icons come from the\n * rows' own `iconSrc`/`iconSrcDark`/`brandColor`. Loading, error and\n * no-project states belong to whatever fetches the rows.\n *\n * Navigation, at every site (issue card, service cell, chart point): with\n * `getHref` a real anchor; a click calls `onOpen(appId, event)` and is never\n * `preventDefault`ed here; only `onOpen` ⇒ a button; neither ⇒ not a link.\n */\n\ntype Open = (appId: string, event: MouseEvent<Element>) => void;\n\nexport interface ReliabilityListWindow {\n from: string;\n to: string;\n days: number;\n}\n\nexport interface ReliabilityListProps<T extends ReliabilityServiceView = ReliabilityServiceView> {\n services: readonly T[];\n /** The window the rows cover; labels the heading. */\n window?: ReliabilityListWindow;\n /** Table column label (\"Last N days\"); defaults to `window?.days ?? 30`. */\n days?: number;\n /** Trim the display: ≤3 attention cards, `limit ?? 5` table rows, chart off. */\n compact?: boolean;\n /** Defaults to `!compact`. */\n showChart?: boolean;\n /** Compact table row cap (default 5). */\n limit?: number;\n getHref?: (appId: string) => string;\n onOpen?: Open;\n /** \"Show all services →\" / \"view all →\" render only when one of these is given. */\n showAllHref?: string;\n onShowAll?: (event: MouseEvent<Element>) => void;\n slots?: {\n /** Replaces the \"Service reliability\" title text. */\n header?: ReactNode;\n /** Rendered at the end of the heading row. */\n actions?: ReactNode;\n /** Replaces the \"No services yet\" message. */\n empty?: ReactNode;\n };\n}\n\n/** Short date for the window line (\"Jun 28 – Jul 27\"). */\nfunction formatDay(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleDateString(undefined, { month: \"short\", day: \"numeric\" });\n}\n\n/** The one anchor/button/plain wrapper every navigation site shares. */\nfunction Target({\n appId,\n className,\n title,\n getHref,\n onOpen,\n children,\n}: {\n appId: string;\n className: string;\n title?: string;\n getHref?: (appId: string) => string;\n onOpen?: Open;\n children: ReactNode;\n}) {\n if (getHref) {\n return (\n <a\n className={className}\n href={getHref(appId)}\n title={title}\n onClick={onOpen ? (e) => onOpen(appId, e) : undefined}\n >\n {children}\n </a>\n );\n }\n if (onOpen) {\n return (\n <button type=\"button\" className={className} title={title} onClick={(e) => onOpen(appId, e)}>\n {children}\n </button>\n );\n }\n return (\n <div className={className} title={title}>\n {children}\n </div>\n );\n}\n\n/** \"Did YOUR calls succeed\" — shared by the table cell and the issue card. */\nfunction ExecStatusSignal({ service }: { service: ReliabilityServiceView }) {\n return (\n <span className=\"w6w-rel-signal\">\n <HealthStatusPill state={service.state} />\n {service.ongoingOutageId && <span className=\"w6w-rel-tag\">outage open</span>}\n {service.calls === 0 && <span className=\"w6w-muted w6w-small\">no calls</span>}\n </span>\n );\n}\n\n/**\n * The API's own status, from the app's declared public health check. Kept a\n * SEPARATE signal from `ExecStatusSignal`: they answer different questions and\n * routinely disagree usefully. `null` ⇒ \"not published\", not an `unknown` pill.\n */\nfunction ApiStatusSignal({ vendor }: { vendor: ReliabilityServiceView[\"vendorStatus\"] }) {\n if (!vendor) return <span className=\"w6w-muted w6w-small\">not published</span>;\n // `unknown` is about US, not the API: we asked and could not tell.\n const unreadable = vendor.state === \"unknown\";\n return (\n <span className=\"w6w-rel-signal\" title={vendor.message ?? undefined}>\n <HealthStatusPill state={vendor.state} label={unreadable ? \"Unavailable\" : undefined} />\n {!unreadable && vendor.message && (\n <span className=\"w6w-rel-vendor-msg w6w-small\">{vendor.message}</span>\n )}\n </span>\n );\n}\n\ninterface NavProps {\n getHref?: (appId: string) => string;\n onOpen?: Open;\n}\n\nfunction IssueCard({ service, getHref, onOpen }: { service: ReliabilityServiceView } & NavProps) {\n return (\n <Target\n appId={service.appId}\n className=\"w6w-rel-issue-card\"\n title={`${service.displayName} — open service detail`}\n getHref={getHref}\n onOpen={onOpen}\n >\n <span className=\"w6w-rel-issue-head\">\n <AppIcon\n src={service.iconSrc}\n srcDark={service.iconSrcDark}\n brandColor={service.brandColor}\n name={service.displayName}\n size={24}\n />\n <span className=\"w6w-rel-issue-head-text\">\n <strong>{service.displayName}</strong>\n {service.attention === \"recent\" && (\n <span className=\"w6w-muted w6w-small\">trouble earlier in this window</span>\n )}\n </span>\n </span>\n <span className=\"w6w-rel-issue-signals\">\n <span className=\"w6w-rel-issue-signal\">\n <span className=\"w6w-muted w6w-small\">w6w exec</span>\n <ExecStatusSignal service={service} />\n </span>\n <span className=\"w6w-rel-issue-signal\">\n <span className=\"w6w-muted w6w-small\">API status</span>\n <ApiStatusSignal vendor={service.vendorStatus} />\n </span>\n </span>\n </Target>\n );\n}\n\nfunction ServiceTableRow({\n service,\n getHref,\n onOpen,\n}: { service: ReliabilityServiceView } & NavProps) {\n const noCalls = service.calls === 0;\n return (\n <tr\n className={`w6w-rel-tr${service.attention !== \"none\" ? \" w6w-rel-attention\" : \"\"}`}\n data-attention={service.attention === \"none\" ? undefined : service.attention}\n >\n <td className=\"w6w-rel-td-service\">\n <Target appId={service.appId} className=\"w6w-rel-open\" getHref={getHref} onOpen={onOpen}>\n <AppIcon\n src={service.iconSrc}\n srcDark={service.iconSrcDark}\n brandColor={service.brandColor}\n name={service.displayName}\n size={28}\n />\n <span className=\"w6w-rel-td-service-text\">\n <strong>{service.displayName}</strong>\n <code className=\"w6w-muted w6w-small\">{service.appId}</code>\n </span>\n </Target>\n </td>\n\n <td className=\"w6w-rel-td-status\">\n <span className=\"w6w-rel-status-row\">\n <span className=\"w6w-rel-status-label w6w-muted w6w-small\">Ops</span>\n <ExecStatusSignal service={service} />\n </span>\n <span className=\"w6w-rel-status-row\">\n <span className=\"w6w-rel-status-label w6w-muted w6w-small\">API</span>\n <ApiStatusSignal vendor={service.vendorStatus} />\n </span>\n </td>\n\n <td className=\"w6w-rel-td-uptime\">\n {noCalls ? (\n // A zero-call window is one identical hatched strip — the note says it better.\n <span className=\"w6w-rel-idle-note\">No calls in this window</span>\n ) : (\n <>\n {/* Oldest day first, exactly as the server sent it. */}\n <UptimeStrip\n days={uptimeDays(service)}\n ariaLabel={`${service.displayName}, ${service.uptime.length}-day status, oldest day first`}\n />\n <span className=\"w6w-muted w6w-small\">{service.calls} calls</span>\n </>\n )}\n </td>\n\n <td className=\"w6w-rel-td-p95\">{service.p95Ms === null ? \"—\" : `${service.p95Ms} ms`}</td>\n </tr>\n );\n}\n\nexport function ReliabilityList<T extends ReliabilityServiceView>({\n services,\n window: win,\n days,\n compact = false,\n showChart,\n limit,\n getHref,\n onOpen,\n showAllHref,\n onShowAll,\n slots,\n}: ReliabilityListProps<T>): ReactElement {\n const windowDays = days ?? win?.days ?? 30;\n // Reads `state` ONLY, on purpose: the card's copy says every service \"came\n // back ok\", a statement about YOUR CALLS that stays true while a vendor\n // reports an incident you have not hit. The grouping below reads `attention`.\n const allClear = services.length > 0 && services.every((s) => s.calls > 0 && s.state === \"ok\");\n const {\n attentionCount,\n shownNow,\n shownRecent,\n hiddenAttentionCount,\n shownTable,\n hiddenTableCount,\n } = displayBoard(services, { compact, limit });\n const shouldShowChart = showChart ?? !compact;\n const canShowAll = showAllHref !== undefined || onShowAll !== undefined;\n const showAllLink = (text: string): ReactNode => {\n const className = text.startsWith(\"Show\") ? \"w6w-muted w6w-small\" : undefined;\n if (showAllHref !== undefined) {\n return (\n <a href={showAllHref} className={className} onClick={onShowAll}>\n {text}\n </a>\n );\n }\n if (onShowAll) {\n return (\n <button\n type=\"button\"\n className={`w6w-rel-show-all${className ? ` ${className}` : \"\"}`}\n onClick={onShowAll}\n >\n {text}\n </button>\n );\n }\n return null;\n };\n\n return (\n <section className=\"w6w-rel-section\">\n <h3 className=\"w6w-rel-heading\">\n <span>\n {slots?.header ?? \"Service reliability\"}{\" \"}\n {win && (\n <span className=\"w6w-muted w6w-small\">\n {formatDay(win.from)} – {formatDay(win.to)} · {win.days} days\n </span>\n )}\n </span>\n {compact && showAllLink(\"Show all services →\")}\n {slots?.actions}\n </h3>\n\n <div className={compact ? \"w6w-rel-card\" : undefined}>\n <p className=\"w6w-muted w6w-small w6w-rel-intro\">\n Connected services across your account. Performance for the selected project.\n </p>\n\n {allClear && (\n <div className={compact ? \"w6w-rel-allclear\" : \"w6w-rel-card w6w-rel-allclear\"}>\n <h4>All clear</h4>\n <p>\n Every service you called in the last {windowDays} days came back{\" \"}\n <HealthStatusPill state=\"ok\" /> — no degraded stretches, no outages.\n </p>\n </div>\n )}\n\n {services.length === 0 &&\n (slots?.empty ?? (\n <div className={compact ? undefined : \"w6w-rel-card\"}>\n <p className=\"w6w-muted\">\n No services yet — connect an integration or use a service in this project.\n </p>\n </div>\n ))}\n\n {services.length > 0 && (\n <>\n {attentionCount > 0 && (\n <div className=\"w6w-rel-group\">\n <h4 className=\"w6w-rel-group-head\">\n Needs attention{\" \"}\n <span className=\"w6w-muted w6w-small\">\n {shownNow.length + shownRecent.length} of {attentionCount}\n </span>\n </h4>\n <div className=\"w6w-rel-issues\">\n {[...shownNow, ...shownRecent].map((s) => (\n <IssueCard key={s.appId} service={s} getHref={getHref} onOpen={onOpen} />\n ))}\n </div>\n {hiddenAttentionCount > 0 && (\n <p className=\"w6w-muted w6w-small w6w-rel-more-note\">\n {hiddenAttentionCount} more {hiddenAttentionCount === 1 ? \"needs\" : \"need\"}{\" \"}\n attention{canShowAll && <> — {showAllLink(\"view all →\")}</>}\n </p>\n )}\n </div>\n )}\n\n {shouldShowChart && (\n <div className=\"w6w-rel-group\">\n <h4 className=\"w6w-rel-group-head\">Performance across your APIs</h4>\n <ReliabilityChart services={services} getHref={getHref} onOpen={onOpen} />\n </div>\n )}\n\n {shownTable.length > 0 && (\n <div className=\"w6w-rel-group\">\n <h4 className=\"w6w-rel-group-head\">\n {compact ? \"Services\" : \"All services\"}{\" \"}\n <span className=\"w6w-muted w6w-small\">\n {compact ? `${shownTable.length} of ${services.length}` : services.length}\n </span>\n </h4>\n <div className=\"w6w-rel-table-wrap\">\n <table className=\"w6w-rel-table\">\n <thead>\n <tr>\n <th>Service</th>\n <th>Status</th>\n <th>Last {windowDays} days</th>\n <th>Latency</th>\n </tr>\n </thead>\n <tbody>\n {shownTable.map((s) => (\n <ServiceTableRow\n key={s.appId}\n service={s}\n getHref={getHref}\n onOpen={onOpen}\n />\n ))}\n </tbody>\n </table>\n </div>\n {hiddenTableCount > 0 && (\n <p className=\"w6w-muted w6w-small w6w-rel-more-note\">\n {hiddenTableCount} more{canShowAll && <> — {showAllLink(\"view all →\")}</>}\n </p>\n )}\n </div>\n )}\n </>\n )}\n </div>\n </section>\n );\n}\n","import type { MouseEvent, ReactNode } from \"react\";\n\nexport interface DataTableColumn<Row> {\n key: string;\n header: ReactNode;\n /** Omitted ⇒ the cell shows `String(row[key] ?? \"\")`. */\n render?: (row: Row) => ReactNode;\n width?: string;\n align?: \"left\" | \"right\" | \"center\";\n /** With `getRowHref`, wrap this column's cells in an anchor. Default true. */\n link?: boolean;\n}\n\nexport interface DataTableProps<Row> {\n columns: readonly DataTableColumn<Row>[];\n rows: readonly Row[];\n rowKey: (row: Row) => string;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onRowClick?: (row: Row, e: MouseEvent<Element>) => void;\n /** When set, every cell of a `link !== false` column wraps its content in `<a href>`. */\n getRowHref?: (row: Row) => string | undefined;\n /** Rendered in place of the body when there are no rows and not `loading`. */\n empty?: ReactNode;\n loading?: boolean;\n className?: string;\n testId?: string;\n rowTestId?: (row: Row) => string | undefined;\n}\n\nfunction cellValue<Row>(col: DataTableColumn<Row>, row: Row): ReactNode {\n if (col.render) return col.render(row);\n return String((row as Record<string, unknown>)[col.key] ?? \"\");\n}\n\nexport function DataTable<Row>(props: DataTableProps<Row>) {\n const { columns, rows, rowKey, onRowClick, getRowHref, empty, loading, className, testId } =\n props;\n if (rows.length === 0 && !loading && empty !== undefined && empty !== null) {\n return <>{empty}</>;\n }\n // The frame owns the ONE outer border + radius (T-3); the table and its cells\n // draw inner separators only, so no outer edge is painted twice.\n return (\n <div className=\"w6w-data-table-frame\">\n <table\n className={className ? `w6w-data-table ${className}` : \"w6w-data-table\"}\n data-testid={testId}\n aria-busy={loading ? true : undefined}\n >\n <thead>\n <tr>\n {columns.map((c) => (\n <th key={c.key} style={{ width: c.width, textAlign: c.align }} scope=\"col\">\n {c.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => {\n const href = getRowHref?.(row);\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: row click is a mouse convenience; keyboard users reach the row through its cell anchors (getRowHref) or the column's own controls.\n <tr\n key={rowKey(row)}\n data-testid={props.rowTestId?.(row)}\n className={onRowClick ? \"w6w-data-table-row-clickable\" : undefined}\n onClick={onRowClick ? (e) => onRowClick(row, e) : undefined}\n >\n {columns.map((c) => {\n const content = cellValue(c, row);\n return (\n <td key={c.key} style={{ textAlign: c.align }}>\n {href !== undefined && c.link !== false ? (\n <a className=\"w6w-data-table-link\" href={href}>\n {content}\n </a>\n ) : (\n content\n )}\n </td>\n );\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\nexport interface EmptyStateProps {\n title?: ReactNode;\n children?: ReactNode;\n action?: ReactNode;\n className?: string;\n testId?: string;\n}\n\nexport function EmptyState({ title, children, action, className, testId }: EmptyStateProps) {\n return (\n <div\n className={className ? `w6w-empty-state ${className}` : \"w6w-empty-state\"}\n data-testid={testId}\n >\n <div className=\"w6w-empty-state-inner\">\n {title !== undefined && title !== null && (\n <div className=\"w6w-empty-state-title\">{title}</div>\n )}\n {children !== undefined && children !== null && (\n <div className=\"w6w-empty-state-body\">{children}</div>\n )}\n {action !== undefined && action !== null && (\n <div className=\"w6w-empty-state-action\">{action}</div>\n )}\n </div>\n </div>\n );\n}\n","import { type MouseEvent, type ReactNode, useState } from \"react\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { EmptyState } from \"./EmptyState.tsx\";\n\n/** One row of a {@link CallableList}. The host decides `archived`; the list never learns a kind. */\nexport interface CallableListRow {\n id: string;\n title: ReactNode;\n description?: ReactNode;\n archived: boolean;\n /** Extra badges, rendered before the archived badge in the trailing slot. */\n badges?: ReactNode;\n /** Trailing content; sits inside the row's anchor when `getHref` is set, so keep it non-interactive. */\n trailing?: ReactNode;\n}\n\nexport interface CallableListProps {\n rows: readonly CallableListRow[];\n title: ReactNode;\n description?: ReactNode;\n /** Shown (inside an EmptyState) when no rows exist at all and not `loading`. */\n emptyCopy?: ReactNode;\n /** Label of the New button. Defaults to \"New\". */\n newLabel?: string;\n /** Tooltip (`title` attribute) on each openable row. */\n openRowTitle?: string;\n testIds?: { showArchived?: string; importOpen?: string; archivedBadge?: string };\n loading?: boolean;\n error?: string | null;\n /** The New button renders only when this is set. */\n onCreate?: () => void;\n /** New button is disabled and reads \"Creating…\" while true. */\n creating?: boolean;\n /** The Import button renders only when this is set. */\n onImport?: () => void;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onOpen?: (id: string, event: MouseEvent<Element>) => void;\n /** When set, each row is a real `<a href>`. */\n getHref?: (id: string) => string;\n /** Controlled \"Show archived\". Omit for an uncontrolled toggle that starts off. */\n showArchived?: boolean;\n onShowArchivedChange?: (next: boolean) => void;\n slots?: {\n /** Replaces the default title/description block (the Show-archived toggle stays). */\n header?: ReactNode;\n /** Rendered before Import/New. */\n actions?: ReactNode;\n /** Replaces `emptyCopy`. */\n empty?: ReactNode;\n };\n}\n\n/**\n * A presentational list of callables (Functions, Endpoints, Workflows): rows in, callbacks out.\n * Owns only the archived filter and its toggle; it knows no router, query, modal or kind.\n * Rows render through {@link DataTable}: a click handler with `onOpen`, anchors with `getHref`.\n * No visible rows renders an {@link EmptyState}; when only archived rows exist it offers \"Show archived\".\n */\nexport function CallableList({\n rows,\n title,\n description,\n emptyCopy,\n newLabel = \"New\",\n openRowTitle,\n testIds,\n loading,\n error,\n onCreate,\n creating,\n onImport,\n onOpen,\n getHref,\n showArchived: showArchivedProp,\n onShowArchivedChange,\n slots,\n}: CallableListProps) {\n const [showArchivedState, setShowArchivedState] = useState(false);\n const controlled = showArchivedProp !== undefined;\n const showArchived = controlled ? showArchivedProp : showArchivedState;\n const visible = showArchived ? rows : rows.filter((r) => !r.archived);\n const interactive = onOpen !== undefined || getHref !== undefined;\n const setShowArchived = (next: boolean) => {\n if (!controlled) setShowArchivedState(next);\n onShowArchivedChange?.(next);\n };\n const columns: DataTableColumn<CallableListRow>[] = [\n {\n key: \"main\",\n header: \"Name\",\n render: (row) => {\n const body = (\n <span className=\"w6w-callable-list-main\" title={interactive ? openRowTitle : undefined}>\n <span>{row.title}</span>\n {row.description != null && (\n <span className=\"w6w-muted w6w-small w6w-callable-list-row-desc\">\n {row.description}\n </span>\n )}\n </span>\n );\n // The click lands on the row (DataTable `onRowClick`); the button is the keyboard route in.\n return onOpen && !getHref ? (\n <button type=\"button\" className=\"w6w-callable-list-open\">\n {body}\n </button>\n ) : (\n body\n );\n },\n },\n {\n key: \"trail\",\n header: \"\",\n align: \"right\",\n render: (row) =>\n row.archived || row.badges != null || row.trailing != null ? (\n <span className=\"w6w-callable-list-trail\">\n {row.badges}\n {row.archived && (\n <span className=\"w6w-callable-list-badge\" data-testid={testIds?.archivedBadge}>\n archived\n </span>\n )}\n {row.trailing}\n </span>\n ) : null,\n },\n ];\n const archivedOnly = rows.length > 0 && visible.length === 0;\n\n return (\n <section className=\"w6w-callable-list\">\n <div className=\"w6w-callable-list-head\">\n <div className=\"w6w-callable-list-heading\">\n {slots?.header ?? (\n <>\n <h2 className=\"w6w-callable-list-title\">{title}</h2>\n {description != null && (\n <p className=\"w6w-muted w6w-small w6w-callable-list-description\">{description}</p>\n )}\n </>\n )}\n <label className=\"w6w-muted w6w-small w6w-callable-list-toggle\">\n <input\n type=\"checkbox\"\n checked={showArchived}\n data-testid={testIds?.showArchived}\n onChange={(e) => setShowArchived(e.target.checked)}\n />\n Show archived\n </label>\n </div>\n <div className=\"w6w-callable-list-actions\">\n {slots?.actions}\n {onImport && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid={testIds?.importOpen}\n onClick={onImport}\n >\n Import\n </button>\n )}\n {onCreate && (\n <button type=\"button\" className=\"w6w-btn\" disabled={creating} onClick={onCreate}>\n {creating ? \"Creating…\" : newLabel}\n </button>\n )}\n </div>\n </div>\n\n {error && <div className=\"w6w-error\">{error}</div>}\n\n <div className=\"w6w-callable-list-body\">\n {loading && <p className=\"w6w-muted\">Loading…</p>}\n {visible.length === 0 && !loading ? (\n archivedOnly ? (\n <EmptyState\n testId=\"w6w-callable-list-empty\"\n action={\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setShowArchived(true)}\n >\n Show archived\n </button>\n }\n >\n {rows.length === 1\n ? \"The only item is archived.\"\n : `All ${rows.length} items are archived.`}\n </EmptyState>\n ) : (\n <EmptyState testId=\"w6w-callable-list-empty\">{slots?.empty ?? emptyCopy}</EmptyState>\n )\n ) : (\n <DataTable\n columns={columns}\n rows={visible}\n rowKey={(r) => r.id}\n loading={loading}\n getRowHref={getHref ? (r) => getHref(r.id) : undefined}\n onRowClick={onOpen ? (r, event) => onOpen(r.id, event) : undefined}\n />\n )}\n </div>\n </section>\n );\n}\n","import type { MouseEvent, ReactNode } from \"react\";\nimport { type InlineAppMeta, resolveConnectionAppMeta } from \"../connection-app-meta.ts\";\nimport type { ConnectionSummary } from \"../types.ts\";\nimport { AppIcon } from \"./AppIcon.tsx\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\nimport { EditButton } from \"./EditButton.tsx\";\nimport { EmptyState } from \"./EmptyState.tsx\";\n\nexport interface ConnectionListProps {\n connections: readonly ConnectionSummary[];\n /**\n * App meta by id, used for rows whose own inline `app` is `undefined` (an older server).\n * Rows with an inline `app` object, or `null`, never consult it.\n */\n appsById?: ReadonlyMap<string, InlineAppMeta>;\n loading?: boolean;\n error?: string | null;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onOpen?: (id: string, event: MouseEvent<Element>) => void;\n /** When set, each openable row is a real `<a href>`. */\n getHref?: (id: string) => string;\n /**\n * Renders an Edit button per row. Pass it only when the host's adapter has `updateConnection`\n * (otherwise the modal it opens has nothing to save with).\n */\n onEdit?: (connection: ConnectionSummary) => void;\n /** Renders a Delete button per row. Confirmation and the delete call are the host's. */\n onDelete?: (connection: ConnectionSummary) => void;\n /** Disables every Delete button while a delete is in flight. */\n busy?: boolean;\n slots?: {\n /** Heading block above the rows. */\n header?: ReactNode;\n /** Trailing action(s) next to the header (e.g. an \"Add\" button). */\n actions?: ReactNode;\n /** Shown when there are no connections and the list is not `loading`. */\n empty?: ReactNode;\n };\n}\n\n/**\n * A presentational list of connections: rows in, callbacks out; it needs no provider. Rows render\n * through {@link DataTable} (name/app, status, and an Edit/Delete column that is never a link).\n *\n * A `builtIn` row (the server's synthetic \"no credential\" entry) is a plain non-interactive item:\n * no link, no `onOpen`, no Edit, no Delete, because the server 404s get/test/delete on its id.\n * Detection is `row.builtIn === true`, never an id prefix.\n */\nexport function ConnectionList({\n connections,\n appsById,\n loading,\n error,\n onOpen,\n getHref,\n onEdit,\n onDelete,\n busy,\n slots,\n}: ConnectionListProps) {\n const byId = appsById ?? new Map<string, InlineAppMeta>();\n const hasActions = onEdit !== undefined || onDelete !== undefined;\n const columns: DataTableColumn<ConnectionSummary>[] = [\n {\n key: \"name\",\n header: \"Name\",\n render: (c) => {\n const app = resolveConnectionAppMeta(c, byId);\n const name = c.displayName || c.id;\n return (\n <span className=\"w6w-connection-cell-name\">\n <AppIcon\n src={app?.iconSvg}\n srcDark={app?.iconSvgDark}\n brandColor={app?.brandColor}\n name={app?.displayName ?? c.appId}\n />\n <strong className=\"w6w-connection-name\" title={name}>\n {name}\n </strong>{\" \"}\n <span className=\"w6w-muted\">{app?.displayName ?? c.appId}</span>\n </span>\n );\n },\n },\n {\n key: \"status\",\n header: \"Status\",\n render: (c) => (\n <>\n auth <code>{c.authKey}</code> ·{\" \"}\n <span\n className={`w6w-connection-tag${c.state === \"connected\" ? \"\" : \" w6w-connection-tag-warn\"}`}\n >\n {c.state}\n </span>\n {c.lastTestOk === false && (\n <span\n className=\"w6w-connection-tag w6w-connection-tag-danger\"\n title=\"Last test failed — update or re-test.\"\n >\n invalid\n </span>\n )}\n </>\n ),\n },\n ];\n if (hasActions) {\n columns.push({\n key: \"actions\",\n header: \"\",\n align: \"right\",\n link: false,\n render: (c) =>\n c.builtIn === true ? null : (\n // Clicks here must not reach the row's onOpen.\n // biome-ignore lint/a11y/useKeyWithClickEvents: propagation guard only; the buttons inside are the controls.\n <div className=\"w6w-connection-row-actions\" onClick={(e) => e.stopPropagation()}>\n {onEdit && (\n <EditButton\n label=\"Edit\"\n onClick={() => onEdit(c)}\n data-testid={`connection-edit-${c.id}`}\n />\n )}\n {onDelete && (\n <DeleteButton\n label=\"Delete\"\n onClick={() => onDelete(c)}\n disabled={busy}\n data-testid={`connection-delete-${c.id}`}\n />\n )}\n </div>\n ),\n });\n }\n return (\n <section className=\"w6w-connection-list\">\n {(slots?.header != null || slots?.actions != null) && (\n <div className=\"w6w-connection-list-head\">\n <div className=\"w6w-connection-list-heading\">{slots?.header}</div>\n <div className=\"w6w-connection-list-actions\">{slots?.actions}</div>\n </div>\n )}\n {error && <div className=\"w6w-error\">{error}</div>}\n {loading && <p className=\"w6w-muted\">Loading…</p>}\n {connections.length === 0 && !loading ? (\n <EmptyState testId=\"w6w-connection-list-empty\">\n {slots?.empty ?? \"No connections yet.\"}\n </EmptyState>\n ) : (\n <DataTable\n columns={columns}\n rows={connections}\n rowKey={(c) => c.id}\n loading={loading}\n getRowHref={getHref ? (c) => (c.builtIn === true ? undefined : getHref(c.id)) : undefined}\n onRowClick={\n onOpen\n ? (c, event) => (c.builtIn === true ? undefined : onOpen(c.id, event))\n : undefined\n }\n />\n )}\n </section>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { AuthFieldsForm, parseJsonFields } from \"./components/AuthFieldsForm.tsx\";\nimport { bindingFieldsFor, buildBinding } from \"./components/CredentialPicker.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport type {\n AuthDef,\n AuthField,\n ConnectionBinding,\n ConnectionSummary,\n CredentialTestResult,\n ThemeMode,\n} from \"./types.ts\";\nimport { useEnterSubmit } from \"./use-enter-submit.ts\";\n\nexport interface EditConnectionModalProps {\n /** The row being edited. `builtIn` rows have nothing to edit: the modal shows a notice only. */\n connection: Pick<\n ConnectionSummary,\n \"id\" | \"appId\" | \"authKey\" | \"displayName\" | \"builtIn\" | \"credentialId\" | \"lastTestOk\"\n >;\n onClose: () => void;\n /** Fired after all changes are saved. The typed credential is cleared before this runs. */\n onSaved: (updated: ConnectionSummary) => void;\n /** Reserved for icon variants, like the other modals. */\n theme?: ThemeMode;\n}\n\n/**\n * Edit an existing connection: rename it and/or replace some of its credential fields. Runs on\n * the {@link useW6WApi} adapter alone. The server never returns the stored secret, so credential\n * fields start empty and blank means \"keep what is stored\" — only the fields the user filled are\n * sent, and the server merges them over the stored credential. Switching to a key/token auth\n * method replaces the full credential while preserving the connection ID. OAuth re-authorization\n * is not part of this modal.\n *\n * A connection that uses a stored credential (`connection.credentialId`), when the host supplies\n * `api.rotateCredential`, saves a full credential replacement through that adapter method.\n * Save also applies any name/binding changes. Other connections sharing the credential switch\n * to the replacement too.\n *\n * Needs `api.updateConnection`. Without it (or for a `builtIn` row) there is no Save button, a\n * one-line notice shows instead, and nothing is called. Hosts should not offer Edit in that case.\n */\nexport function EditConnectionModal({ connection, onClose, onSaved }: EditConnectionModalProps) {\n const api = useW6WApi();\n const update = api.updateConnection;\n const builtIn = connection.builtIn === true;\n const editable = !builtIn && typeof update === \"function\";\n\n const [displayName, setDisplayName] = useState(connection.displayName ?? \"\");\n const [authKey, setAuthKey] = useState(connection.authKey);\n const [credential, setCredential] = useState<Record<string, unknown>>({});\n const [auths, setAuths] = useState<AuthDef[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [pending, setPending] = useState(false);\n const [bindingVals, setBindingVals] = useState<Record<string, unknown>>({});\n const [connectionCount, setConnectionCount] = useState<number | null>(null);\n const [credentialContract, setCredentialContract] = useState<string | null>(null);\n const [health, setHealth] = useState<CredentialTestResult | null>(null);\n\n // The app's declared auth methods drive which credential fields to show.\n useEffect(() => {\n if (!editable) return;\n let canceled = false;\n setAuths(null);\n api\n .getAppAuth(connection.appId)\n .then((a) => !canceled && setAuths(a))\n .catch((e) => !canceled && setError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, editable, connection.appId]);\n\n const authDef = auths?.find((a) => a.key === authKey);\n const authChanged = authKey !== connection.authKey;\n const authChoices =\n auths?.filter(\n (a) =>\n a.key === connection.authKey ||\n (a.available !== false &&\n !a.autoSatisfied &&\n [\"apiKey\", \"bearer\", \"basic\", \"custom\"].includes(a.type)),\n ) ?? [];\n const isOAuth = authDef?.type === \"oauth2\";\n const fields: AuthField[] = isOAuth ? [] : (authDef?.fields ?? []);\n const credentialId = connection.credentialId;\n const storedCredential =\n !authChanged &&\n !!credentialId &&\n typeof api.rotateCredential === \"function\" &&\n (credentialContract !== null\n ? !credentialContract.startsWith(\"legacy:\")\n : authDef?.type === \"serviceAccount\") &&\n !isOAuth;\n const bindingFields =\n storedCredential && authDef?.serviceAccount ? bindingFieldsFor(authDef.serviceAccount) : [];\n\n // Impact of replacing a credential: how many connections share the stored credential.\n useEffect(() => {\n if (\n !editable ||\n authChanged ||\n isOAuth ||\n !credentialId ||\n typeof api.getCredential !== \"function\"\n )\n return;\n let canceled = false;\n api\n .getCredential(credentialId)\n .then((c) => {\n if (canceled) return;\n setConnectionCount(c.connectionCount);\n setCredentialContract(c.contract);\n })\n .catch(() => {});\n return () => {\n canceled = true;\n };\n }, [api, editable, authChanged, isOAuth, credentialId]);\n\n /** `null` = nothing to update. Only a changed name and non-blank credential fields are sent. */\n function buildBody(): {\n authKey?: string;\n displayName?: string;\n binding?: ConnectionBinding;\n credential?: Record<string, unknown>;\n } | null {\n if (storedCredential) {\n // Rename/binding only: the credential is never part of this body.\n const body: { displayName?: string; binding?: ConnectionBinding } = {};\n if (displayName !== (connection.displayName ?? \"\")) body.displayName = displayName;\n const binding = buildBinding(bindingFields, bindingVals);\n if (binding) body.binding = binding;\n return body.displayName === undefined && body.binding === undefined ? null : body;\n }\n const filled: Record<string, unknown> = {};\n for (const f of fields) {\n const v = credential[f.key];\n if (v !== undefined && v !== \"\") filled[f.key] = v;\n }\n const body: { authKey?: string; displayName?: string; credential?: Record<string, unknown> } =\n {};\n if (authChanged) {\n body.authKey = authKey;\n body.credential = filled;\n }\n if (displayName !== (connection.displayName ?? \"\")) body.displayName = displayName;\n if (Object.keys(filled).length > 0) body.credential = filled;\n return body.displayName === undefined && body.credential === undefined ? null : body;\n }\n\n async function save() {\n if (!editable || !update || pending) return;\n setError(null);\n const body = buildBody();\n const filled = Object.fromEntries(\n fields\n .filter((f) => credential[f.key] !== undefined && credential[f.key] !== \"\")\n .map((f) => [f.key, credential[f.key]]),\n );\n const hasCredential = Object.keys(filled).length > 0;\n if (!body && !hasCredential) {\n setError(\"Nothing to update — change the name or a credential or binding field.\");\n return;\n }\n if (authChanged || (storedCredential && hasCredential)) {\n const missing = fields.filter((f) => f.required && !(f.key in filled));\n if (missing.length > 0) {\n setError(`Enter the full new credential: ${missing.map((f) => f.label).join(\", \")}.`);\n return;\n }\n }\n const parsed = parseJsonFields(fields, filled);\n if (\"error\" in parsed) {\n setError(parsed.error);\n return;\n }\n setPending(true);\n let credentialSaved = false;\n try {\n if (storedCredential && hasCredential && credentialId && api.rotateCredential) {\n await api.rotateCredential(credentialId, { source: parsed.values });\n credentialSaved = true;\n setCredential({});\n setHealth(null);\n } else if (body?.credential) {\n body.credential = parsed.values;\n }\n // Replacing a stored credential leaves the connection row unchanged.\n const updated = body ? await update.call(api, connection.id, body) : connection;\n // Drop every typed secret before handing control back to the host.\n setCredential({});\n onSaved(updated);\n } catch (e) {\n // The rejection's message only — never the values the user typed.\n setError(\n credentialSaved\n ? `The credential was saved, but the other changes failed. Click Save to retry them. ${(e as Error).message}`\n : (e as Error).message,\n );\n } finally {\n setPending(false);\n }\n }\n\n async function checkHealth() {\n if (!credentialId || !api.testCredential) return;\n setError(null);\n try {\n setHealth(await api.testCredential(credentialId));\n } catch (e) {\n setError((e as Error).message);\n }\n }\n\n const enterSubmit = useEnterSubmit(save, { enabled: editable && !pending });\n\n return (\n <Modal title=\"Edit connection\" onClose={onClose}>\n <div className=\"w6w-stepconfig\">\n <div className=\"w6w-modal-body\">\n <div className=\"w6w-stack\">\n {builtIn && (\n <p className=\"w6w-muted w6w-small\">\n This connection is built in — it has no stored credential to edit.\n </p>\n )}\n {!builtIn && !editable && (\n <p className=\"w6w-muted w6w-small\">Editing connections is not available here.</p>\n )}\n {editable && (\n <>\n <label className=\"w6w-field\">\n <span>Display name</span>\n <input\n type=\"text\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n placeholder=\"Connection name\"\n maxLength={80}\n name=\"w6w-connection-label\"\n autoComplete=\"off\"\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n data-bwignore=\"true\"\n data-form-type=\"other\"\n {...enterSubmit}\n />\n </label>\n\n {authChoices.some((a) => a.key !== connection.authKey) && (\n <label className=\"w6w-field\">\n <span>Authentication method</span>\n <select\n name=\"w6w-connection-auth\"\n value={authKey}\n disabled={pending}\n onChange={(e) => {\n setAuthKey(e.target.value);\n setCredential({});\n setBindingVals({});\n setHealth(null);\n setError(null);\n }}\n >\n {!authChoices.some((a) => a.key === connection.authKey) && (\n <option value={connection.authKey}>{connection.authKey}</option>\n )}\n {authChoices.map((a) => (\n <option key={a.key} value={a.key}>\n {a.displayName ?? a.key}\n </option>\n ))}\n </select>\n </label>\n )}\n {authChanged && (\n <p className=\"w6w-muted w6w-small\">\n Enter the new credential and click Save. This connection stays linked to your\n existing workflows.\n </p>\n )}\n\n {auths === null && !error && (\n <p className=\"w6w-muted w6w-small\">Loading auth fields…</p>\n )}\n\n {isOAuth && (\n <p className=\"w6w-muted w6w-small\">\n {authChoices.some((a) => a.key !== connection.authKey)\n ? \"This connection uses OAuth. Choose another authentication method above to use a key or token.\"\n : \"This is an OAuth connection. You can rename it here; its credential is renewed by re-authorizing it.\"}\n </p>\n )}\n\n {storedCredential && bindingFields.length > 0 && (\n <>\n <p className=\"w6w-muted w6w-small\">\n Leave a binding field blank to keep it unchanged.\n </p>\n <AuthFieldsForm\n mode=\"edit\"\n fields={bindingFields}\n values={bindingVals}\n onChange={setBindingVals}\n enterSubmitProps={enterSubmit}\n />\n </>\n )}\n\n {storedCredential && (\n <div className=\"w6w-stack\" data-w6w=\"credential-section\">\n {typeof api.testCredential === \"function\" && (\n <div>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={checkHealth}\n >\n Test credential\n </button>\n {health && (\n <p className=\"w6w-small\" data-w6w=\"credential-health\">\n Credential health: {health.ok ? \"ok\" : (health.code ?? \"failed\")}\n </p>\n )}\n </div>\n )}\n <p className=\"w6w-small\" data-w6w=\"app-access\">\n App access:{\" \"}\n {connection.lastTestOk === true\n ? \"passed\"\n : connection.lastTestOk === false\n ? \"failed\"\n : \"never tested\"}\n </p>\n {fields.length > 0 && (\n <>\n <p className=\"w6w-muted w6w-small\">\n Leave the credential blank to keep it unchanged. To replace it, enter the\n full new credential and click Save.\n {connectionCount !== null &&\n connectionCount > 1 &&\n ` This credential is used by ${connectionCount} connections; saving a new credential updates all of them.`}\n </p>\n <AuthFieldsForm\n mode=\"edit\"\n fields={fields}\n values={credential}\n onChange={setCredential}\n enterSubmitProps={enterSubmit}\n />\n </>\n )}\n </div>\n )}\n\n {!storedCredential && fields.length > 0 && (\n <>\n {!authChanged && (\n <p className=\"w6w-muted w6w-small\">\n Leave a field blank to keep it unchanged. Filled fields replace the stored\n credential.\n </p>\n )}\n <AuthFieldsForm\n mode=\"edit\"\n fields={fields}\n values={credential}\n onChange={setCredential}\n enterSubmitProps={enterSubmit}\n />\n </>\n )}\n </>\n )}\n\n {error && <div className=\"w6w-result w6w-error\">{error}</div>}\n </div>\n </div>\n <div className=\"w6w-modal-actions\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n {editable && (\n <button type=\"button\" className=\"w6w-btn\" disabled={pending} onClick={save}>\n {pending ? \"Saving…\" : \"Save\"}\n </button>\n )}\n </div>\n </div>\n </Modal>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { AppIcon } from \"./components/AppIcon.tsx\";\nimport { CopyableText } from \"./components/CopyableText.tsx\";\nimport type { ConnectionSummary } from \"./types.ts\";\n\nexport interface ConnectionHeaderProps {\n conn: ConnectionSummary;\n /** The connection's app display meta (inline `app`, or the by-id record). */\n app:\n | { displayName?: string; iconSvg?: string; iconSvgDark?: string; brandColor?: string }\n | undefined;\n /** Actions slot, right-aligned (e.g. a Test or Edit button, or a back link). */\n children?: ReactNode;\n}\n\n/**\n * Connection identity strip: app icon, display name, copyable id, app id, auth key and state tag\n * (plus `invalid` after a failed test). Presentational; the actions live in `children`.\n */\nexport function ConnectionHeader({ conn, app, children }: ConnectionHeaderProps) {\n return (\n <div className=\"w6w-connection-header\" data-testid=\"connection-header\">\n <AppIcon\n src={app?.iconSvg}\n srcDark={app?.iconSvgDark}\n brandColor={app?.brandColor}\n name={app?.displayName ?? conn.appId}\n size={56}\n />\n <div className=\"w6w-connection-header-main\">\n <h2 className=\"w6w-connection-header-title\">{conn.displayName || conn.id}</h2>\n <p className=\"w6w-muted w6w-small w6w-connection-header-meta\">\n <CopyableText value={conn.id} className=\"w6w-connection-id-copy\" /> · App{\" \"}\n <code>{conn.appId}</code> · Auth <code>{conn.authKey}</code> ·{\" \"}\n <span\n className={`w6w-connection-tag${conn.state === \"connected\" ? \"\" : \" w6w-connection-tag-warn\"}`}\n >\n {conn.state}\n </span>\n {conn.lastTestOk === false && (\n <span\n className=\"w6w-connection-tag w6w-connection-tag-danger\"\n title=\"Last test failed — update or re-test.\"\n >\n invalid\n </span>\n )}\n </p>\n </div>\n {children && <div className=\"w6w-connection-header-actions\">{children}</div>}\n </div>\n );\n}\n","// BudgetMeter — a one-line usage-vs-limit meter for model budgets.\n//\n// Purely presentational: the host owns the numbers and decides what \"the\n// budget\" is (tokens, requests, currency). `format` is the host's hook for\n// rendering those numbers in its own unit; without it the raw values are\n// printed.\n//\n// `role=\"meter\"` (not `progressbar`) is the ARIA role for a measurement within\n// a known range, and the accessible name is the `label` prop. The bar is drawn\n// from two segments — `used` and, when non-zero, `reserved` — because a\n// reserved-but-not-yet-spent amount is a distinct quantity from spend and must\n// stay legible next to it. At or past the limit the root carries\n// `w6w-budget-meter-over`, which is the only hook styles use to switch the bar\n// to the danger colour.\n\nconst defaultFormat = (n: number): string => String(n);\n\n/** Clamp a 0..100 percentage and keep it to a stable number of decimals so the\n * inline `width` style does not wobble between renders. */\nfunction pct(value: number): number {\n const clamped = Math.min(100, Math.max(0, value));\n return Number(clamped.toFixed(4));\n}\n\nexport interface BudgetMeterProps {\n /** Accessible name and the visible caption. */\n label: string;\n /** Amount already consumed. */\n used: number;\n /** Upper bound `used` is measured against. */\n limit: number;\n /** Amount held back but not yet spent. The segment renders only when > 0. */\n reserved?: number;\n /** Formats every number the meter prints (visible text and aria-valuetext). */\n format?: (n: number) => string;\n className?: string;\n testId?: string;\n}\n\nexport function BudgetMeter({\n label,\n used,\n limit,\n reserved = 0,\n format,\n className,\n testId,\n}: BudgetMeterProps) {\n const fmt = format ?? defaultFormat;\n const hasReserved = Number.isFinite(reserved) && reserved > 0;\n const usedPct = limit > 0 ? pct((used / limit) * 100) : 100;\n // A reservation can never push the bar past a full track, so it only fills\n // what `used` leaves over.\n const reservedPct =\n hasReserved && limit > 0 ? pct(Math.min(100 - usedPct, (reserved / limit) * 100)) : 0;\n const over = used >= limit;\n const valueText = `${fmt(used)} / ${fmt(limit)}`;\n\n const classes = [\"w6w-budget-meter\"];\n if (over) classes.push(\"w6w-budget-meter-over\");\n if (className) classes.push(className);\n\n return (\n <div\n role=\"meter\"\n className={classes.join(\" \")}\n aria-label={label}\n aria-valuemin={0}\n aria-valuenow={used}\n aria-valuemax={limit}\n aria-valuetext={valueText}\n data-testid={testId}\n >\n <div className=\"w6w-budget-meter-head\">\n <span className=\"w6w-budget-meter-label\">{label}</span>\n <span className=\"w6w-budget-meter-value\">{valueText}</span>\n </div>\n <div className=\"w6w-budget-meter-track\">\n <div className=\"w6w-budget-meter-used\" style={{ width: `${usedPct}%` }} />\n {hasReserved && (\n <div className=\"w6w-budget-meter-reserved\" style={{ width: `${reservedPct}%` }} />\n )}\n </div>\n </div>\n );\n}\n","/**\n * The pure, data-free vocabulary of a Data store (F-2, lifted from Studio's\n * `lib/data-stores-view`, `data-cells`, `data-grid` and `data-store-errors`).\n *\n * One import point for every consumer (Studio, `@w6w/embed`, the components in\n * this package): the wire types, the closed kind/scalar vocabularies, the\n * cell text codec, the row-draft/write helpers and the error locator. Paths,\n * query builders and cache keys deliberately stay in Studio.\n *\n * Pure and dependency-free on purpose: no React, no SDK, no `fetch`, only\n * relative imports, so `node --test` loads it with nothing but type-stripping.\n */\n\n/** Display label per store kind (shared by every list and picker). */\nexport const DATA_STORE_KIND_LABEL = {\n kv: \"Key-value\",\n doc: \"Document\",\n table: \"Table\",\n} as const;\n\n// ── Wire vocabulary ──────────────────────────────────────────────────────────\n\n/**\n * The three store shapes. `kv` holds one value per key, `doc` holds a JSON\n * document per key, `table` holds rows whose columns are declared in the\n * store's schema.\n */\nexport type DataStoreKind = \"kv\" | \"doc\" | \"table\";\n\n/**\n * The server's scalar vocabulary (S-1). A value of this type is validated\n * server-side and stored as the string the caller sent — never coerced.\n */\nexport type ScalarType = \"string\" | \"number\" | \"integer\" | \"boolean\" | \"date\" | \"datetime\";\n\n/** One declared table column (S-2). `default` is the column's JSON default, verbatim. */\nexport interface TableColumn {\n name: string;\n type: ScalarType;\n required: boolean;\n default?: unknown;\n}\n\n/** A `kv` store's schema (S-2): one scalar type for every value. */\nexport interface KvSchema {\n valueType: ScalarType;\n}\n\n/** A `table` store's schema (S-2); `key` names the column whose cell is the row's key. */\nexport interface TableSchema {\n columns: TableColumn[];\n key?: string;\n}\n\n/** A store as the wire carries it (S-3). Timestamps are ISO-8601 strings. */\nexport interface DataStore {\n id: string;\n kind: DataStoreKind;\n name: string;\n description: string;\n project: string;\n schema: Record<string, unknown>;\n entryCount: number;\n sizeBytes: number;\n createdBy: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/** One entry as the wire carries it (S-3). `expiresAt` is `null` when the entry never expires. */\nexport interface Entry {\n key: string;\n value: unknown;\n version: number;\n sizeBytes: number;\n expiresAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** `GET /data-stores` — one page of stores plus the cursor for the next one. */\nexport interface DataStorePage {\n items: DataStore[];\n nextCursor?: string;\n}\n\n/** `GET /data-stores/:id/entries` — one page of entries (a table query never carries a cursor). */\nexport interface EntryPage {\n items: Entry[];\n nextCursor?: string;\n}\n\n/** `POST /data-stores/:id/import` — how many CSV rows the host upserted/appended. */\nexport interface ImportResult {\n imported: number;\n}\n\n/** `POST /data-stores` body. `schema` is the S-2 shape for the chosen `kind`. */\nexport interface DataStoreCreateInput {\n kind: DataStoreKind;\n name: string;\n description?: string;\n schema?: Record<string, unknown>;\n}\n\n/** `PATCH /data-stores/:id` body — every field optional, none of them the kind. */\nexport interface DataStorePatch {\n name?: string;\n description?: string;\n schema?: Record<string, unknown>;\n}\n\n/** The closed set of store kinds, in the order the create dialog offers them. */\nexport const DATA_STORE_KINDS = [\"kv\", \"doc\", \"table\"] as const;\n\n/** The closed set of scalar cell types, in the order the columns editor offers them. */\nexport const SCALAR_TYPES = [\"string\", \"number\", \"integer\", \"boolean\", \"date\", \"datetime\"] as const;\n\n/** R-7: a CSV upload is at most 5 MB (5 242 880 bytes). The client checks before sending. */\nexport const CSV_MAX_BYTES = 5_242_880;\n\n/**\n * A `kv` store's declared value type, defaulting to `\"string\"` — S-2's own\n * default, and the only safe reading of a schema the client did not write\n * (a store created before the field existed, or one whose schema is garbage).\n */\nexport function kvValueTypeOf(store: DataStore): ScalarType {\n const declared = store.schema?.valueType;\n return typeof declared === \"string\" && (SCALAR_TYPES as readonly string[]).includes(declared)\n ? (declared as ScalarType)\n : \"string\";\n}\n\n/**\n * A `table` store's schema, or `null` when the store is not a table or its\n * schema has no column array. `null` — not an empty column list — so the grid\n * can tell \"not a table\" from \"a table with nothing declared\".\n */\nexport function tableSchemaOf(store: DataStore): TableSchema | null {\n if (store.kind !== \"table\") return null;\n const columns = store.schema?.columns;\n if (!Array.isArray(columns)) return null;\n const key = store.schema?.key;\n return typeof key === \"string\"\n ? { columns: columns as TableColumn[], key }\n : { columns: columns as TableColumn[] };\n}\n\n/**\n * The filename to save an export under: the host's own `filename=\"…\"` from the\n * `Content-Disposition` header when it sent one, otherwise `<store name>.csv`.\n * A header without that parameter (`attachment` alone, or `null` when a\n * proxy stripped it) falls back rather than producing a nameless file.\n */\nexport function csvFilenameOf(contentDisposition: string | null, storeName: string): string {\n const quoted = contentDisposition?.match(/filename=\"([^\"]*)\"/);\n const name = quoted?.[1];\n return name !== undefined && name !== \"\" ? name : `${storeName}.csv`;\n}\n\n// ── Cell codec ──────────────────────────────────────────────────────────────\n\n/** Why a cell's text could not become a value. */\nexport type CellProblem =\n | \"required\"\n | \"not_a_number\"\n | \"not_an_integer\"\n | \"not_a_boolean\"\n | \"not_a_date\"\n | \"not_a_datetime\";\n\n/** The one sentence rendered beside the offending cell, per problem. */\nexport const CELL_PROBLEM_COPY: Record<CellProblem, string> = {\n required: \"Required.\",\n not_a_number: \"Enter a number.\",\n not_an_integer: \"Enter a whole number.\",\n not_a_boolean: \"Enter true or false.\",\n not_a_date: \"Enter a date as YYYY-MM-DD.\",\n not_a_datetime: \"Enter a date-time like 2026-01-31T09:30:00Z.\",\n};\n\n/** The JSON number grammar, without the forms JSON itself would not round-trip (`01`, `+1`, `.5`, `1.`). */\nconst NUMBER_TEXT = /^-?(0|[1-9]\\d*)(\\.\\d+)?([eE][+-]?\\d+)?$/;\n\n/** A whole number: no fraction, no exponent. */\nconst INTEGER_TEXT = /^-?(0|[1-9]\\d*)$/;\n\n/** `YYYY-MM-DD` — the calendar check is {@linkcode isRealDate}. */\nconst DATE_TEXT = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** RFC 3339 with an offset; the field ranges and the calendar are checked separately. */\nconst DATETIME_TEXT = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$/;\n\n/** Days in `month` (1–12) of `year`, Gregorian leap rule. */\nfunction daysInMonth(year: number, month: number): number {\n if (month === 2) {\n const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n return leap ? 29 : 28;\n }\n return [31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];\n}\n\n/** `YYYY-MM-DD` split into numbers, or `null` when it is not a real calendar day. */\nfunction readDate(text: string): { year: number; month: number; day: number } | null {\n if (!DATE_TEXT.test(text)) return null;\n const year = Number(text.slice(0, 4));\n const month = Number(text.slice(5, 7));\n const day = Number(text.slice(8, 10));\n if (month < 1 || month > 12) return null;\n if (day < 1 || day > daysInMonth(year, month)) return null;\n return { year, month, day };\n}\n\n/** The failure half of {@linkcode parseCell}'s answer, carrying the copy the cell renders. */\nfunction refuse(problem: CellProblem) {\n return { ok: false as const, problem, message: CELL_PROBLEM_COPY[problem] };\n}\n\n/**\n * Turn the text an operator typed into the value the wire takes, for a column\n * of `type`.\n *\n * `required` is applied to the EMPTY cell only (R-7): every other rule is the\n * server's own, so a cell this returns `ok` for is a cell the server accepts.\n * `string` is the one type that keeps the text as typed — trimming it would\n * silently edit the operator's value.\n */\nexport function parseCell(\n type: ScalarType,\n text: string,\n required: boolean,\n):\n | { ok: true; value: string | number | boolean | undefined }\n | { ok: false; problem: CellProblem; message: string } {\n const trimmed = text.trim();\n if (trimmed === \"\") {\n return required ? refuse(\"required\") : { ok: true, value: undefined };\n }\n switch (type) {\n case \"string\":\n return { ok: true, value: text };\n case \"number\": {\n if (!NUMBER_TEXT.test(trimmed)) return refuse(\"not_a_number\");\n const value = Number(trimmed);\n return Number.isFinite(value) ? { ok: true, value } : refuse(\"not_a_number\");\n }\n case \"integer\": {\n if (!INTEGER_TEXT.test(trimmed)) return refuse(\"not_an_integer\");\n const value = Number(trimmed);\n return Number.isSafeInteger(value) ? { ok: true, value } : refuse(\"not_an_integer\");\n }\n case \"boolean\": {\n if (trimmed === \"true\") return { ok: true, value: true };\n if (trimmed === \"false\") return { ok: true, value: false };\n return refuse(\"not_a_boolean\");\n }\n case \"date\":\n return readDate(trimmed) === null ? refuse(\"not_a_date\") : { ok: true, value: trimmed };\n case \"datetime\":\n return isDateTime(trimmed) ? { ok: true, value: trimmed } : refuse(\"not_a_datetime\");\n }\n}\n\n/** RFC 3339 text with a real calendar date, real clock fields and a well-formed offset. */\nfunction isDateTime(text: string): boolean {\n if (!DATETIME_TEXT.test(text)) return false;\n if (readDate(text.slice(0, 10)) === null) return false;\n const hour = Number(text.slice(11, 13));\n const minute = Number(text.slice(14, 16));\n const second = Number(text.slice(17, 19));\n if (hour > 23 || minute > 59 || second > 59) return false;\n const rest = text.slice(19);\n const zone = rest.match(/(Z|([+-])(\\d{2}):(\\d{2}))$/);\n if (zone === null || zone[1] === \"Z\") return true;\n return Number(zone[3]) <= 23 && Number(zone[4]) <= 59;\n}\n\n/**\n * The text to put in a cell for an already-typed value.\n *\n * `undefined`/`null` render as the empty cell (never `\"undefined\"` or `\"null\"`);\n * a string value for a string-ish column is shown as itself; a finite number\n * and a boolean render as their JSON literals; anything else (an object cell,\n * a `null` inside a document) falls back to its JSON text so the cell shows\n * what the server holds rather than `[object Object]`.\n */\nexport function serializeCell(type: ScalarType, value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (type === \"string\" || type === \"date\" || type === \"datetime\") {\n if (typeof value === \"string\") return value;\n }\n if (\n (type === \"number\" || type === \"integer\") &&\n typeof value === \"number\" &&\n Number.isFinite(value)\n ) {\n return String(value);\n }\n if (type === \"boolean\" && typeof value === \"boolean\") return value ? \"true\" : \"false\";\n const json = JSON.stringify(value);\n return json === undefined ? \"\" : json;\n}\n\n/**\n * Is an already-typed JSON value of `type`? The same rules {@linkcode parseCell}\n * applies to text, applied to a value that came back from the server — the grid\n * uses it to mark a row the server would refuse before the operator presses\n * Save. `required` plays no part here: an absent value is the caller's problem\n * to decide about, not this predicate's.\n */\nexport function isCellValue(type: ScalarType, value: unknown): boolean {\n switch (type) {\n case \"string\":\n return typeof value === \"string\";\n case \"number\":\n return typeof value === \"number\" && Number.isFinite(value);\n case \"integer\":\n return Number.isSafeInteger(value);\n case \"boolean\":\n return typeof value === \"boolean\";\n case \"date\":\n return typeof value === \"string\" && readDate(value) !== null;\n case \"datetime\":\n return typeof value === \"string\" && isDateTime(value);\n }\n}\n\n// ── Error locator ───────────────────────────────────────────────────────────\n\n/** What is shown when the server said nothing a human can read. */\nexport const DATA_STORE_ERROR_FALLBACK = \"The request failed.\";\n\n/** `rawRequest`'s `status: 0` — the request never reached the server. */\nexport const DATA_STORE_NETWORK_ERROR = \"Could not reach the server.\";\n\n/** A failure, flattened into the fields the page needs and nothing else. */\nexport interface DataStoreErrorLocator {\n /** Always present: the server's own sentence, or one of the two copy constants above. */\n message: string;\n /** The host's machine-readable code (`invalid_value`, `invalid_cursor`, …). */\n code?: string;\n /** The HTTP status; `0` is the transport-failure convention. */\n status?: number;\n /** The request-body field the host blamed. */\n field?: string;\n /** The 0-based CSV data row the host blamed (header excluded). */\n row?: number;\n /** The table column the host blamed. */\n column?: string;\n}\n\n/** A non-empty string, or `undefined`. */\nfunction textOf(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** A 0-based row index, or `undefined` — a negative or fractional row is not a row. */\nfunction rowOf(value: unknown): number | undefined {\n return Number.isInteger(value) && (value as number) >= 0 ? (value as number) : undefined;\n}\n\n/**\n * Read `{ error: { code, message, field, row, column } }` out of whatever the\n * caller has, adding `status` from `status` when that is a number.\n *\n * `body` is a value of unknown shape (a parsed JSON body, or the `.raw` of an\n * `ApiError`); the envelope is nested under `error`, and an unshaped body\n * contributes nothing rather than a guess.\n */\nfunction locatorFromEnvelope(\n body: unknown,\n fallbackMessages: unknown[],\n status: unknown,\n): DataStoreErrorLocator {\n const locator: DataStoreErrorLocator = { message: DATA_STORE_ERROR_FALLBACK };\n if (typeof status === \"number\") locator.status = status;\n const envelope =\n body !== null && typeof body === \"object\" ? (body as { error?: unknown }).error : undefined;\n if (envelope !== null && typeof envelope === \"object\") {\n const error = envelope as {\n code?: unknown;\n message?: unknown;\n field?: unknown;\n row?: unknown;\n column?: unknown;\n };\n const code = textOf(error.code);\n if (code !== undefined) locator.code = code;\n const field = textOf(error.field);\n if (field !== undefined) locator.field = field;\n const column = textOf(error.column);\n if (column !== undefined) locator.column = column;\n const row = rowOf(error.row);\n if (row !== undefined) locator.row = row;\n const message = textOf(error.message);\n if (message !== undefined) locator.message = message;\n }\n if (locator.message === DATA_STORE_ERROR_FALLBACK) {\n for (const candidate of fallbackMessages) {\n const message = textOf(candidate);\n if (message !== undefined) {\n locator.message = message;\n break;\n }\n }\n }\n return locator;\n}\n\n/**\n * Locate a thrown JSON-call failure: an `ApiError` (whose parsed body lives on\n * `.raw`), a plain `Error`, or anything else at all.\n *\n * The message falls back in that order — the envelope's `message`, the error's\n * own `message`, then {@linkcode DATA_STORE_ERROR_FALLBACK} — so an unfamiliar\n * throw still produces a sentence rather than an empty panel.\n */\nexport function locateDataStoreError(e: unknown): DataStoreErrorLocator {\n try {\n const shaped =\n e !== null && typeof e === \"object\"\n ? (e as { raw?: unknown; status?: unknown; message?: unknown })\n : undefined;\n const raw = shaped?.raw;\n const ownMessage = shaped?.message;\n return locatorFromEnvelope(raw, [ownMessage], shaped?.status);\n } catch {\n return { message: DATA_STORE_ERROR_FALLBACK };\n }\n}\n\n/**\n * Locate a CSV-call failure from P-RAW's `{status, text}` — the body is still\n * unparsed text because that transport does not know the content type.\n *\n * `status: 0` means the request never produced a response, and gets the\n * transport sentence rather than an attempt to parse an empty body. Otherwise\n * the body is parsed iff it is JSON: an HTML error page from a proxy is\n * `{status, message: fallback}`, not a crash.\n */\nexport function locateRawResponseError(res: {\n status: number;\n text: string;\n}): DataStoreErrorLocator {\n try {\n if (res.status === 0) {\n return {\n status: 0,\n code: \"network_error\",\n message: DATA_STORE_NETWORK_ERROR,\n };\n }\n let body: unknown;\n try {\n body = JSON.parse(res.text);\n } catch {\n return { status: res.status, message: DATA_STORE_ERROR_FALLBACK };\n }\n return locatorFromEnvelope(body, [], res.status);\n } catch {\n return { message: DATA_STORE_ERROR_FALLBACK };\n }\n}\n\n/** Where the message is rendered: under one table cell, under one form field, or over the whole form. */\nexport function errorPlacement(\n loc: DataStoreErrorLocator,\n):\n | { kind: \"cell\"; column: string; row?: number }\n | { kind: \"field\"; field: string }\n | { kind: \"form\" } {\n const column = textOf(loc.column);\n if (column !== undefined) {\n const row = rowOf(loc.row);\n return row === undefined ? { kind: \"cell\", column } : { kind: \"cell\", column, row };\n }\n const field = textOf(loc.field);\n if (field !== undefined) return { kind: \"field\", field };\n return { kind: \"form\" };\n}\n\n/**\n * The operator's 1-based line number in the CSV they uploaded, from the host's\n * 0-based data-row index: the header row is line 1, so data row 0 is line 2.\n */\nexport function csvLineOf(row: number): number {\n return row + 2;\n}\n\n// ── Row drafts and writes ───────────────────────────────────────────────────\n\n/**\n * The draft id of a row that does not exist yet: a NUL-prefixed sentinel, which\n * R-5 forbids a real key from ever being (no control characters in a key), so\n * `id === NEW_ROW_ID` and \"this row has no server-side key\" are the same fact.\n */\nexport const NEW_ROW_ID = \"\\u0000new\";\n\n/** Rendered beside a row whose `ifVersion` was stale — never as the server's sentence alone. */\nexport const VERSION_CONFLICT_COPY = \"Changed by someone else since you loaded it.\";\n\n/** A `doc` store holds a JSON object or array; anything else is not a document. */\nexport const DOC_VALUE_COPY = \"Enter a JSON object or array.\";\n\n/** R-7's client-side ceiling copy — the check runs before anything is sent. */\nexport const CSV_TOO_LARGE_COPY = \"The file is larger than 5 MB.\";\n\n/**\n * One row's editable state: the id it is saved under (`entry.key`, or\n * {@linkcode NEW_ROW_ID}), the version the save guards with (`null` for a new\n * row) and the cell TEXT per declared column (never a parsed value — the text\n * is what the operator is editing, and re-serialising it on every keystroke\n * would fight their cursor).\n */\nexport interface RowDraft {\n id: string;\n version: number | null;\n cells: Record<string, string>;\n}\n\n/**\n * An entry's value read as a table row: the object the server stored, or `{}`\n * for anything that is not a plain object (a `null`, an array, a scalar from a\n * column set that has since changed).\n */\nexport function rowValueOf(entry: Entry): Record<string, unknown> {\n const value = entry.value;\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\n/** The draft an entry starts as: its key, its version, and each declared column's text. */\nexport function draftFromEntry(entry: Entry, columns: readonly TableColumn[]): RowDraft {\n const row = rowValueOf(entry);\n const cells: Record<string, string> = {};\n for (const column of columns) cells[column.name] = serializeCell(column.type, row[column.name]);\n return { id: entry.key, version: entry.version, cells };\n}\n\n/**\n * The draft a brand-new row starts as: {@linkcode NEW_ROW_ID}, no version, and\n * each column seeded from its declared `default` (absent default = empty cell).\n */\nexport function newRowDraft(columns: readonly TableColumn[]): RowDraft {\n const cells: Record<string, string> = {};\n for (const column of columns) {\n cells[column.name] =\n column.default === undefined ? \"\" : serializeCell(column.type, column.default);\n }\n return { id: NEW_ROW_ID, version: null, cells };\n}\n\n/**\n * Which declared columns the operator actually changed, in DECLARED order.\n *\n * Declared order (not object order) so the answer is stable across browsers and\n * the row's Save button can decide \"dirty\" with one empty-array check. An\n * untouched draft is `[]`.\n */\nexport function dirtyColumns(\n draft: RowDraft,\n base: RowDraft,\n columns: readonly TableColumn[],\n): string[] {\n const dirty: string[] = [];\n for (const column of columns) {\n if ((draft.cells[column.name] ?? \"\") !== (base.cells[column.name] ?? \"\")) {\n dirty.push(column.name);\n }\n }\n return dirty;\n}\n\n/**\n * The row body a Save sends, or the per-cell refusals that stop it.\n *\n * Every DECLARED column is parsed through {@linkcode parseCell} with its own\n * `required` flag: an absent value omits the key entirely (R-7's empty-cell\n * rule, so the host's default applies), a `string` cell keeps its text verbatim\n * and every other type is the JSON value the server expects — never the typed\n * text. Failures are keyed by column name so the caller renders them under the\n * offending cell.\n */\nexport function buildRowValue(\n draft: RowDraft,\n columns: readonly TableColumn[],\n): { ok: true; value: Record<string, unknown> } | { ok: false; errors: Record<string, string> } {\n const value: Record<string, unknown> = {};\n const errors: Record<string, string> = {};\n for (const column of columns) {\n const parsed = parseCell(column.type, draft.cells[column.name] ?? \"\", column.required);\n if (parsed.ok) {\n if (parsed.value !== undefined) value[column.name] = parsed.value;\n } else {\n errors[column.name] = parsed.message;\n }\n }\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value };\n}\n\n/**\n * The `ttlSeconds` a save must resend so it does not CLEAR an existing expiry\n * (S-1: a PUT without `ttlSeconds` sets `expires_at = NULL`).\n *\n * `undefined` for an entry that never expires, for an unparseable timestamp and\n * for one already in the past — in all three cases sending nothing is correct\n * (and a non-positive TTL is not a TTL the host accepts). Rounded UP, so a save\n * one millisecond before the deadline does not shorten the entry's life.\n */\nexport function remainingTtlSeconds(expiresAt: string | null, nowMs: number): number | undefined {\n if (expiresAt === null) return undefined;\n const ms = Date.parse(expiresAt);\n if (!Number.isFinite(ms)) return undefined;\n const seconds = Math.ceil((ms - nowMs) / 1000);\n return seconds > 0 ? seconds : undefined;\n}\n\n/**\n * Which request a draft implies: an INSERT (`POST entries`, no `ifVersion`) for\n * a row that does not exist yet, otherwise a PUT under the row's key guarded by\n * the version the operator loaded.\n *\n * `ttlSeconds` is present ONLY when the caller has one: it reaches the wire as\n * a defining key, and an explicit `undefined` would be indistinguishable from\n * \"the caller measured nothing\".\n */\nexport function rowWriteOf(\n draft: RowDraft,\n value: Record<string, unknown>,\n ttlSeconds: number | undefined,\n):\n | { kind: \"insert\"; value: Record<string, unknown>; ttlSeconds?: number }\n | {\n kind: \"put\";\n key: string;\n value: Record<string, unknown>;\n ifVersion: number;\n ttlSeconds?: number;\n } {\n if (draft.id === NEW_ROW_ID) {\n return ttlSeconds === undefined\n ? { kind: \"insert\", value }\n : { kind: \"insert\", value, ttlSeconds };\n }\n const write = {\n kind: \"put\" as const,\n key: draft.id,\n value,\n ifVersion: draft.version ?? 0,\n };\n return ttlSeconds === undefined ? write : { ...write, ttlSeconds };\n}\n\n/**\n * The cell errors a refusal places, or `null` when it belongs somewhere else\n * (the form, a request-body field, a column this table does not declare).\n *\n * `null` is load-bearing: the grid renders `grid-error` exactly when this\n * returns `null`, so \"the message shows in one slot\" is a property of the\n * answer rather than of the caller's care.\n */\nexport function cellErrorsOf(\n loc: DataStoreErrorLocator,\n columns: readonly TableColumn[],\n): Record<string, string> | null {\n const placement = errorPlacement(loc);\n if (placement.kind !== \"cell\") return null;\n if (!columns.some((column) => column.name === placement.column)) return null;\n return { [placement.column]: loc.message };\n}\n\n/**\n * Is this failure the optimistic-concurrency refusal — and nothing else?\n *\n * `409` alone is not enough: `entry_exists` and `store_exists` share the status\n * and neither is fixed by reloading, so both halves of the locator must agree.\n */\nexport function isVersionConflict(loc: DataStoreErrorLocator): boolean {\n return loc.status === 409 && loc.code === \"version_conflict\";\n}\n\n/**\n * A `doc` store's value from the editor's text: any JSON object or array.\n *\n * A scalar is refused rather than wrapped — the store's own `doc` shape is an\n * object/array (S-2), and the host would refuse `42` anyway; failing here means\n * the operator sees why without a round trip. `null` parses but is not a\n * document, so it is refused with the same sentence.\n */\nexport function parseDocText(\n text: string,\n): { ok: true; value: object } | { ok: false; message: string } {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return { ok: false, message: DOC_VALUE_COPY };\n }\n if (parsed === null || typeof parsed !== \"object\") {\n return { ok: false, message: DOC_VALUE_COPY };\n }\n return { ok: true, value: parsed };\n}\n\n/**\n * A `kv` store's value from the editor's text.\n *\n * `string` is the one type whose text IS the value, empty string included (an\n * empty `string` entry is a real value, not an absent one), so it never passes\n * through {@linkcode parseCell} — which reads an empty cell as absent. Every\n * other type is parsed exactly as a table cell would be, `required` on, because\n * a kv entry always has a value.\n */\nexport function kvValueOf(\n type: ScalarType,\n text: string,\n): { ok: true; value: unknown } | { ok: false; message: string } {\n if (type === \"string\") return { ok: true, value: text };\n const parsed = parseCell(type, text, true);\n return parsed.ok ? { ok: true, value: parsed.value } : { ok: false, message: parsed.message };\n}\n\n/**\n * What a CSV import's `RawResponse` says to the operator.\n *\n * The host is the only parser (R-7): a `200` reports how many rows it took, and\n * a refusal is located rather than interpreted — a `row` becomes the operator's\n * own 1-based line (`csvLineOf`), the `column` is named when the host named one,\n * and everything else is the host's sentence verbatim.\n */\nexport function csvImportMessage(res: { status: number; text: string }): {\n ok: boolean;\n message: string;\n} {\n if (res.status === 200) {\n let imported = 0;\n try {\n const body = JSON.parse(res.text) as { imported?: unknown };\n if (typeof body.imported === \"number\" && Number.isFinite(body.imported)) {\n imported = body.imported;\n }\n } catch {\n imported = 0;\n }\n return {\n ok: true,\n message: `Imported ${imported} row${imported === 1 ? \"\" : \"s\"}.`,\n };\n }\n const loc = locateRawResponseError(res);\n if (loc.row === undefined) return { ok: false, message: loc.message };\n const where = loc.column\n ? `Line ${csvLineOf(loc.row)}, column ${loc.column}`\n : `Line ${csvLineOf(loc.row)}`;\n return { ok: false, message: `${where}: ${loc.message}` };\n}\n","import type { MouseEvent, ReactNode } from \"react\";\nimport { DATA_STORE_KIND_LABEL, type DataStore } from \"../data-stores/data-store-view.ts\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\nimport { EditButton } from \"./EditButton.tsx\";\nimport { EmptyState } from \"./EmptyState.tsx\";\nimport { formatBytes } from \"./server-resources-format.ts\";\n\nexport interface DataStoreListProps {\n stores: readonly DataStore[];\n loading?: boolean;\n error?: string | null;\n /** Row click. The event is passed through untouched; the host may `preventDefault`. */\n onOpen?: (id: string, event: MouseEvent<Element>) => void;\n /** When set, each row is a real `<a href>`. */\n getHref?: (id: string) => string;\n /** Renders an Edit button per row. */\n onEdit?: (store: DataStore) => void;\n /** Renders an Archive button per row. Confirmation and the archive call are the host's. */\n onArchive?: (store: DataStore) => void;\n /** Disables every Archive button while an archive is in flight. */\n busy?: boolean;\n /** Size formatter; defaults to the package's `formatBytes` (`2.0 KiB`). */\n formatSize?: (bytes: number) => string;\n slots?: {\n /** Heading block above the rows. */\n header?: ReactNode;\n /** Trailing action(s) next to the header (e.g. a \"New store\" button). */\n actions?: ReactNode;\n /** Shown when there are no stores and the list is not `loading`. */\n empty?: ReactNode;\n };\n}\n\n/**\n * A presentational list of Data stores: rows in, callbacks out; it needs no provider. Rows render\n * through {@link DataTable} (name, kind, entry count, size, last update, and an Edit/Archive column\n * that is never a link).\n */\nexport function DataStoreList({\n stores,\n loading,\n error,\n onOpen,\n getHref,\n onEdit,\n onArchive,\n busy,\n formatSize,\n slots,\n}: DataStoreListProps) {\n const size = formatSize ?? formatBytes;\n const hasActions = onEdit !== undefined || onArchive !== undefined;\n const columns: DataTableColumn<DataStore>[] = [\n { key: \"name\", header: \"Name\", render: (s) => <strong>{s.name}</strong> },\n { key: \"kind\", header: \"Kind\", render: (s) => DATA_STORE_KIND_LABEL[s.kind] },\n { key: \"entries\", header: \"Entries\", align: \"right\", render: (s) => String(s.entryCount) },\n { key: \"size\", header: \"Size\", align: \"right\", render: (s) => size(s.sizeBytes) },\n {\n key: \"updated\",\n header: \"Updated\",\n render: (s) => new Date(s.updatedAt).toLocaleString(),\n },\n ];\n if (hasActions) {\n columns.push({\n key: \"actions\",\n header: \"\",\n align: \"right\",\n link: false,\n render: (s) => (\n // Clicks here must not reach the row's onOpen.\n // biome-ignore lint/a11y/useKeyWithClickEvents: propagation guard only; the buttons inside are the controls.\n <div className=\"w6w-data-row-actions\" onClick={(e) => e.stopPropagation()}>\n {onEdit && (\n <EditButton\n label=\"Edit\"\n onClick={() => onEdit(s)}\n data-testid={`data-store-edit-${s.id}`}\n />\n )}\n {onArchive && (\n <DeleteButton\n label=\"Archive\"\n onClick={() => onArchive(s)}\n disabled={busy}\n data-testid={`data-store-archive-${s.id}`}\n />\n )}\n </div>\n ),\n });\n }\n return (\n <section className=\"w6w-data-store-list\">\n {(slots?.header != null || slots?.actions != null) && (\n <div className=\"w6w-data-store-list-head\">\n <div className=\"w6w-data-store-list-heading\">{slots?.header}</div>\n <div className=\"w6w-data-store-list-actions\">{slots?.actions}</div>\n </div>\n )}\n {error && <div className=\"w6w-error\">{error}</div>}\n {loading && <p className=\"w6w-muted\">Loading…</p>}\n {stores.length === 0 && !loading ? (\n <EmptyState testId=\"w6w-data-store-list-empty\">\n {slots?.empty ?? \"No data stores yet.\"}\n </EmptyState>\n ) : (\n <DataTable\n columns={columns}\n rows={stores}\n rowKey={(s) => s.id}\n loading={loading}\n getRowHref={getHref ? (s) => getHref(s.id) : undefined}\n onRowClick={onOpen ? (s, event) => onOpen(s.id, event) : undefined}\n />\n )}\n </section>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport {\n SCALAR_TYPES,\n type ScalarType,\n type TableColumn,\n parseCell,\n serializeCell,\n} from \"../data-stores/data-store-view.ts\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\n\n/**\n * The `table` kind's column list: a controlled row editor (rows + `onChange(next)`; the column\n * list itself is never copied).\n *\n * The **key column** select is the one piece of the schema a row cannot decide for itself: only a\n * column that is `required` and typed `string` or `integer` may be a row's key, so the select\n * offers only those rows. A column renamed, retyped or un-required out of that set resets the\n * selection to `\"\"` (\"generated keys\") rather than holding a key the server would reject.\n *\n * `columnErrors` is keyed by column NAME (what the host's error envelope names in\n * `error.column`), so a 400 lands under the row that caused it.\n *\n * Each row also takes a **default**, typed as text and parsed with the column's type: empty or\n * refused text leaves the column with no `default` key at all, a valid one stores the typed value\n * (`7`, `true`), never the text.\n */\nexport interface ColumnsEditorProps {\n columns: TableColumn[];\n onChange: (next: TableColumn[]) => void;\n /** The selected key column's name, or `\"\"` for \"generated keys\". */\n keyColumn: string;\n onKeyColumnChange: (k: string) => void;\n /** One message per column name, from the server's `error.column`. */\n columnErrors: Record<string, string>;\n}\n\n/** The key column's eligibility rule. */\nfunction eligibleAsKey(c: TableColumn): boolean {\n return c.name !== \"\" && c.required === true && (c.type === \"string\" || c.type === \"integer\");\n}\n\n/** `column` with its default replaced by the parse of `text`; no `default` key unless it parsed. */\nfunction withDefault(column: TableColumn, text: string): { column: TableColumn; error?: string } {\n const { default: _old, ...rest } = column;\n const parsed = parseCell(column.type, text, false);\n if (!parsed.ok) return { column: rest, error: parsed.message };\n if (parsed.value === undefined) return { column: rest };\n return { column: { ...rest, default: parsed.value } };\n}\n\ninterface DefaultDraft {\n text: string;\n error?: string;\n}\n\nexport function ColumnsEditor(props: ColumnsEditorProps) {\n const { columns, onChange, keyColumn, onKeyColumnChange, columnErrors } = props;\n // The text typed into each row's default box, by row position. A row with no draft shows the\n // serialization of the column's own default.\n const [drafts, setDrafts] = useState<Record<number, DefaultDraft>>({});\n\n const eligible = columns.filter(eligibleAsKey);\n const eligibleKey = eligible.some((c) => c.name === keyColumn) ? keyColumn : \"\";\n\n // The selection cannot survive its column leaving the eligible set.\n useEffect(() => {\n if (keyColumn !== \"\" && eligibleKey === \"\") onKeyColumnChange(\"\");\n }, [keyColumn, eligibleKey, onKeyColumnChange]);\n\n function addColumn() {\n onChange([...columns, { name: \"\", type: \"string\", required: false }]);\n }\n function updateColumn(i: number, next: Partial<TableColumn>) {\n onChange(columns.map((c, idx) => (idx === i ? { ...c, ...next } : c)));\n }\n function setDefault(i: number, type: ScalarType, text: string, extra?: Partial<TableColumn>) {\n const base = { ...columns[i], ...extra, type } as TableColumn;\n const { column, error } = withDefault(base, text);\n setDrafts((d) => ({ ...d, [i]: error === undefined ? { text } : { text, error } }));\n onChange(columns.map((c, idx) => (idx === i ? column : c)));\n }\n function removeColumn(i: number) {\n setDrafts((d) => {\n const next: Record<number, DefaultDraft> = {};\n for (const [k, v] of Object.entries(d)) {\n const n = Number(k);\n if (n < i) next[n] = v;\n else if (n > i) next[n - 1] = v;\n }\n return next;\n });\n onChange(columns.filter((_, idx) => idx !== i));\n }\n\n return (\n <div className=\"w6w-data-columns\">\n <div className=\"w6w-data-columns-head\">\n <h3>Columns</h3>\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={addColumn}>\n + Add column\n </button>\n </div>\n <p className=\"w6w-muted w6w-small\">\n Each column has a name, a scalar type, whether it must be set, and an optional default.\n </p>\n {columns.length === 0 && <p className=\"w6w-muted w6w-small\">No columns yet.</p>}\n <ul className=\"w6w-data-columns-list\" data-testid=\"data-columns\">\n {columns.map((c, i) => {\n const draft = drafts[i];\n const text = draft?.text ?? serializeCell(c.type, c.default);\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and reorderable\n <li key={i} className=\"w6w-data-columns-row\">\n <input\n type=\"text\"\n value={c.name}\n placeholder=\"name\"\n aria-label=\"Column name\"\n onChange={(e) => updateColumn(i, { name: e.target.value })}\n />\n <select\n value={c.type}\n aria-label=\"Column type\"\n onChange={(e) => setDefault(i, e.target.value as ScalarType, text)}\n >\n {SCALAR_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <label className=\"w6w-data-columns-required\">\n <input\n type=\"checkbox\"\n checked={c.required}\n aria-label=\"Required\"\n onChange={(e) => updateColumn(i, { required: e.target.checked })}\n />\n <span className=\"w6w-muted w6w-small\">required</span>\n </label>\n <input\n type=\"text\"\n value={text}\n placeholder=\"default\"\n aria-label=\"Column default\"\n onChange={(e) => setDefault(i, c.type, e.target.value)}\n />\n <DeleteButton\n label={`Remove column ${c.name || i + 1}`}\n onClick={() => removeColumn(i)}\n />\n {draft?.error !== undefined && (\n <div\n className=\"w6w-result w6w-error w6w-data-columns-error\"\n data-testid={`data-store-column-default-error-${i}`}\n >\n {draft.error}\n </div>\n )}\n {c.name !== \"\" && columnErrors[c.name] !== undefined && (\n <div\n className=\"w6w-result w6w-error w6w-data-columns-error\"\n data-testid={`data-store-column-error-${c.name}`}\n >\n {columnErrors[c.name]}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n <label className=\"w6w-field\">\n <span>Key column</span>\n <select value={eligibleKey} onChange={(e) => onKeyColumnChange(e.target.value)}>\n <option value=\"\">(none — rows get generated keys)</option>\n {eligible.map((c) => (\n <option key={c.name} value={c.name}>\n {c.name}\n </option>\n ))}\n </select>\n <span className=\"w6w-hint\">\n Only a required, string or integer column can name a row's key.\n </span>\n </label>\n </div>\n );\n}\n","import type { ChangeEvent } from \"react\";\nimport { CSV_MAX_BYTES, CSV_TOO_LARGE_COPY } from \"../data-stores/data-store-view.ts\";\n\nexport interface CsvPanelProps {\n /** What the panel is telling the operator, and whether it failed. `null` renders nothing. */\n result: { ok: boolean; message: string } | null;\n /** Disables Export while a request is in flight. */\n busy?: boolean;\n /** A file within {@link CSV_MAX_BYTES}. Reading and sending it are the host's. */\n onImport: (file: File) => void;\n /** A file the panel refused before handing it over (too large). */\n onRefuse: (message: string) => void;\n onExport: () => void;\n}\n\n/**\n * CSV import and export for one table store: one file input, one Export button, one result line.\n * Props-only. The panel owns the size check (a file over {@link CSV_MAX_BYTES} is refused here and\n * never reaches `onImport`); it never parses the CSV, because the host is the authority on line\n * and column.\n */\nexport function CsvPanel({ result, busy, onImport, onRefuse, onExport }: CsvPanelProps) {\n function onFile(e: ChangeEvent<HTMLInputElement>) {\n const input = e.target;\n const file = input.files?.[0];\n if (file === undefined) return;\n // Reset the input's own value so choosing the SAME file again re-fires `change`.\n input.value = \"\";\n if (file.size > CSV_MAX_BYTES) {\n onRefuse(CSV_TOO_LARGE_COPY);\n return;\n }\n onImport(file);\n }\n\n return (\n <div className=\"w6w-data-csv-panel\" data-testid=\"csv-panel\">\n <div className=\"w6w-data-csv-panel-actions\">\n <input\n type=\"file\"\n accept=\".csv,text/csv\"\n data-testid=\"csv-file\"\n aria-label=\"Import CSV\"\n onChange={onFile}\n />\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"csv-export\"\n disabled={busy}\n onClick={onExport}\n >\n Export CSV\n </button>\n </div>\n {result !== null && (\n <div className={result.ok ? \"w6w-result\" : \"w6w-result w6w-error\"} data-testid=\"csv-result\">\n {result.message}\n </div>\n )}\n </div>\n );\n}\n","import { type FormEvent, type ReactNode, useState } from \"react\";\nimport { Copyable } from \"./Copyable.tsx\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\n\n/** One row of a kv/doc store's entry list, as the host has already prepared it. */\nexport interface DataEntryListRow {\n key: string;\n version: number;\n /** The short text shown in the Value column. */\n preview: string;\n /** Full value to copy; never use a truncated preview as the clipboard payload. */\n copyText?: string;\n}\n\nexport interface DataEntryListProps {\n rows: readonly DataEntryListRow[];\n /** Shown instead of the table when there are no rows and the list is not `loading`. */\n empty?: ReactNode;\n /** When there are no rows, shows the loading text instead of `empty`. */\n loading?: boolean;\n /** Initial text of the key-prefix box. */\n searchValue?: string;\n /** Renders \"Load more\" when true. */\n hasMore?: boolean;\n /** Fired when a row is opened by mouse or its key button by keyboard. */\n onOpen: (key: string) => void;\n /** Fired with the prefix text when the search form is SUBMITTED (never per keystroke). */\n onSearch: (text: string) => void;\n /** Fired by the \"New entry\" button. */\n onNew: () => void;\n /** Fired by \"Load more\". */\n onLoadMore: () => void;\n}\n\n/**\n * A presentational list of a kv/doc store's entries: view-model rows in, callbacks out. It owns\n * only the text of the search box; the query, the editor and the delete confirmation are the\n * host's. Rows render through {@link DataTable}.\n */\nexport function DataEntryList({\n rows,\n empty,\n loading,\n searchValue,\n hasMore,\n onOpen,\n onSearch,\n onNew,\n onLoadMore,\n}: DataEntryListProps) {\n const [prefix, setPrefix] = useState(searchValue ?? \"\");\n const submit = (e: FormEvent) => {\n e.preventDefault();\n onSearch(prefix);\n };\n const columns: DataTableColumn<DataEntryListRow>[] = [\n {\n key: \"key\",\n header: \"Key\",\n width: \"38%\",\n render: (row) => (\n <button\n type=\"button\"\n className=\"w6w-data-entry-key\"\n title={row.key}\n data-testid=\"entry-key\"\n onClick={(event) => {\n event.stopPropagation();\n onOpen(row.key);\n }}\n >\n {row.key}\n </button>\n ),\n },\n {\n key: \"value\",\n header: \"Value\",\n render: (row) =>\n row.copyText !== undefined ? (\n <Copyable value={row.copyText} label=\"Copy value\" className=\"w6w-copyable--bare\">\n <span className=\"w6w-muted w6w-small w6w-data-entry-preview\">{row.preview}</span>\n </Copyable>\n ) : (\n <span className=\"w6w-muted w6w-small w6w-data-entry-preview\">{row.preview}</span>\n ),\n },\n ];\n return (\n <div>\n <form className=\"w6w-data-entries-toolbar\" data-testid=\"entry-search\" onSubmit={submit}>\n <input\n type=\"search\"\n data-testid=\"entry-prefix\"\n value={prefix}\n placeholder=\"Key prefix\"\n aria-label=\"Key prefix\"\n onChange={(e) => setPrefix(e.target.value)}\n />\n <button className=\"w6w-btn w6w-btn-ghost\" type=\"submit\">\n Search\n </button>\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entry-new\"\n onClick={onNew}\n >\n New entry\n </button>\n </form>\n\n <DataTable\n className=\"w6w-data-entry-list\"\n onRowClick={(row) => onOpen(row.key)}\n columns={columns}\n rows={rows}\n rowKey={(row) => row.key}\n empty={\n // A div, not a <p>: `empty` is any node and callers often pass a <p>.\n <div className=\"w6w-muted w6w-small\">\n {loading ? \"Loading…\" : (empty ?? \"No entries match this key prefix.\")}\n </div>\n }\n />\n\n {hasMore && (\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entries-load-more\"\n onClick={onLoadMore}\n >\n Load more\n </button>\n )}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { JsonEditor } from \"../JsonEditor.tsx\";\nimport { VERSION_CONFLICT_COPY, parseDocText } from \"../data-stores/data-store-view.ts\";\nimport { Copyable } from \"./Copyable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\nimport { Modal } from \"./Modal.tsx\";\n\nexport interface DataEntryEditorProps {\n /** `kv` edits one input; `doc` edits JSON in a {@link JsonEditor}. */\n kind: \"kv\" | \"doc\";\n /** True for a not-yet-created entry: opens directly in edit mode with a key input. */\n isNew: boolean;\n /** The entry's key (existing mode heading). */\n entryKey?: string;\n /** The new entry's key (controlled). */\n newKey?: string;\n /** Concurrency token supplied by the host; never presented as document history. */\n version?: number | null;\n /** Existing mode: ISO expiry, shown when set. */\n expiresAt?: string | null;\n /** The value text (controlled). */\n text: string;\n /** A host-supplied value/save error. */\n error?: string | null;\n /** True after a stale `ifVersion`: shows the conflict copy and Reload, and disables Save. */\n conflict?: boolean;\n /** True while a save is in flight: disables Save. */\n saving?: boolean;\n /** Fired per edit of the value, with the new text. */\n onTextChange: (text: string) => void;\n /** Fired per edit of the new-entry key, with the new text. */\n onKeyChange: (key: string) => void;\n /** Opens the host's delete confirmation for an existing entry. */\n onDelete?: () => void;\n onSave: () => void;\n onCancel: () => void;\n /** Fired by the conflict prompt's Reload. */\n onReload: () => void;\n}\n\n/**\n * Existing entries open for viewing, then Edit enables changes inside the same modal.\n * New entries start in edit mode. Drafts, `ifVersion` and mutations live in the host.\n * Document validity is derived from the controlled text, including initial values and reloads.\n */\nexport function DataEntryEditor({\n kind,\n isNew,\n entryKey,\n newKey,\n expiresAt,\n text,\n error,\n conflict,\n saving,\n onTextChange,\n onKeyChange,\n onDelete,\n onSave,\n onCancel,\n onReload,\n}: DataEntryEditorProps) {\n const [editing, setEditing] = useState(isNew);\n const [showValidation, setShowValidation] = useState(false);\n const closeButton = useRef<HTMLButtonElement>(null);\n useEffect(() => {\n if (!isNew) closeButton.current?.focus();\n }, [isNew]);\n const noun = kind === \"doc\" ? \"document\" : \"entry\";\n const parsedDocument = kind === \"doc\" ? parseDocText(text) : undefined;\n const invalidDocument = parsedDocument !== undefined && !parsedDocument.ok;\n const valueError =\n error ||\n (showValidation && parsedDocument && !parsedDocument.ok ? parsedDocument.message : null);\n const body = (\n <>\n {isNew ? (\n <label className=\"w6w-field\">\n <span>Key</span>\n <input\n data-testid=\"entry-new-key\"\n value={newKey ?? \"\"}\n placeholder=\"Key\"\n aria-label=\"Key\"\n onChange={(e) => onKeyChange(e.target.value)}\n />\n </label>\n ) : expiresAt ? (\n <p className=\"w6w-muted w6w-small\">Expires {expiresAt}</p>\n ) : null}\n\n {kind === \"doc\" ? (\n <JsonEditor\n value={text}\n readOnly={!editing}\n onChange={(next) => {\n setShowValidation(false);\n onTextChange(next);\n }}\n onFocus={() => setShowValidation(false)}\n onBlur={() => setShowValidation(true)}\n showDiagnostics={showValidation}\n minHeight=\"min(50vh, 400px)\"\n maxHeight=\"60vh\"\n />\n ) : (\n <Copyable value={text} label=\"Copy value\">\n <input\n type=\"text\"\n data-testid=\"entry-value\"\n value={text}\n aria-label=\"Value\"\n readOnly={!editing}\n onChange={(e) => onTextChange(e.target.value)}\n />\n </Copyable>\n )}\n\n {valueError && (\n <div className=\"w6w-field-error\" role=\"alert\" data-testid=\"entry-value-error\">\n {valueError}\n </div>\n )}\n {conflict && (\n <div className=\"w6w-error\" data-testid=\"entry-conflict\">\n {VERSION_CONFLICT_COPY}{\" \"}\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entry-reload\"\n onClick={onReload}\n >\n Reload\n </button>\n </div>\n )}\n </>\n );\n return (\n <Modal\n title={\n isNew ? `New ${noun}` : editing ? `Edit ${noun}` : kind === \"doc\" ? \"Document\" : \"Entry\"\n }\n subtitle={isNew ? undefined : entryKey}\n size={kind === \"doc\" ? \"wide\" : \"default\"}\n onClose={saving ? () => {} : onCancel}\n >\n <div className=\"w6w-modal-body\" data-testid=\"entry-editor\">\n {body}\n </div>\n <div className=\"w6w-modal-actions\">\n {!isNew && onDelete && (\n <DeleteButton\n label=\"Delete entry\"\n className=\"w6w-data-entry-delete\"\n disabled={saving}\n onClick={onDelete}\n />\n )}\n <button\n ref={closeButton}\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n disabled={saving}\n onClick={onCancel}\n >\n {editing ? \"Cancel\" : \"Close\"}\n </button>\n {editing ? (\n <button\n className=\"w6w-btn\"\n type=\"button\"\n data-testid=\"entry-save\"\n disabled={\n Boolean(conflict) || Boolean(saving) || invalidDocument || (isNew && !newKey?.trim())\n }\n onClick={onSave}\n >\n Save\n </button>\n ) : (\n <button\n className=\"w6w-btn\"\n type=\"button\"\n disabled={saving}\n onClick={() => setEditing(true)}\n >\n Edit\n </button>\n )}\n </div>\n </Modal>\n );\n}\n","import { type FormEvent, type ReactNode, useState } from \"react\";\nimport { type TableColumn, VERSION_CONFLICT_COPY } from \"../data-stores/data-store-view.ts\";\nimport { DataTable, type DataTableColumn } from \"./DataTable.tsx\";\nimport { DeleteButton } from \"./DeleteButton.tsx\";\n\n/** One grid row as the host has prepared it. `id` is the entry key; the new row is `isNew`. */\nexport interface DataTableGridRow {\n id: string;\n /** True for the unsaved row: its key cell is editable and its `data-row` is `\"new\"`. */\n isNew?: boolean;\n /** Draft cell text by column name. */\n cells: Record<string, string>;\n /** The version the row was loaded at; `null` for a new row. */\n version: number | null;\n /** True when the draft differs from the loaded entry. */\n dirty: boolean;\n /** True after a stale `ifVersion`: shows the conflict copy and Reload, and disables Save. */\n conflict?: boolean;\n /** Per-cell error messages by column name, shown under their own cell. */\n cellErrors?: Record<string, string>;\n}\n\nexport interface DataTableGridProps {\n columns: readonly TableColumn[];\n /** The column whose cell is the row key (read-only on an existing row). */\n keyColumn: string;\n rows: readonly DataTableGridRow[];\n /** A grid-level (not cell) error. */\n error?: string | null;\n loading?: boolean;\n empty?: ReactNode;\n /** Initial text of the key-prefix box. */\n searchValue?: string;\n hasMore?: boolean;\n onCellChange: (rowId: string, column: string, text: string) => void;\n onSave: (rowId: string) => void;\n /** Fired immediately; confirmation is the host's. */\n onDelete: (rowId: string) => void;\n onReload: (rowId: string) => void;\n onAddRow: () => void;\n onLoadMore: () => void;\n /** Fired with the prefix text when the search form is SUBMITTED (never per keystroke). */\n onSearch: (text: string) => void;\n}\n\nconst rowAttr = (row: DataTableGridRow) => (row.isNew ? \"new\" : row.id);\n\n/**\n * A presentational editable grid for a table store: row view-models in, callbacks out. Drafts,\n * dirty tracking, version handling and the delete confirmation are the host's. Rows render through\n * {@link DataTable}.\n */\nexport function DataTableGrid({\n columns,\n keyColumn,\n rows,\n error,\n loading,\n empty,\n searchValue,\n hasMore,\n onCellChange,\n onSave,\n onDelete,\n onReload,\n onAddRow,\n onLoadMore,\n onSearch,\n}: DataTableGridProps) {\n const [prefix, setPrefix] = useState(searchValue ?? \"\");\n const submit = (e: FormEvent) => {\n e.preventDefault();\n onSearch(prefix);\n };\n const tableColumns: DataTableColumn<DataTableGridRow>[] = [\n ...columns.map((column) => ({\n key: column.name,\n header: (\n <>\n {column.name} <span className=\"w6w-muted w6w-small\">{column.type}</span>\n </>\n ),\n render: (row: DataTableGridRow) => {\n const message = row.cellErrors?.[column.name];\n return (\n <div className=\"w6w-data-cell\">\n <input\n data-row={rowAttr(row)}\n data-column={column.name}\n value={row.cells[column.name] ?? \"\"}\n readOnly={column.name === keyColumn && !row.isNew}\n aria-label={`${column.name} (${column.type})`}\n onChange={(e) => onCellChange(row.id, column.name, e.target.value)}\n />\n {message !== undefined && (\n <div\n className=\"w6w-data-cell-error\"\n data-row={rowAttr(row)}\n data-column={column.name}\n >\n {message}\n </div>\n )}\n </div>\n );\n },\n })),\n {\n key: \"actions\",\n header: \"\",\n render: (row: DataTableGridRow) => (\n <div className=\"w6w-data-row-actions\">\n <span className=\"w6w-muted w6w-small\">\n {row.version === null ? \"\" : `v${row.version}`}\n </span>\n <button\n className=\"w6w-btn\"\n type=\"button\"\n data-row={rowAttr(row)}\n data-testid=\"row-save\"\n disabled={(!row.isNew && !row.dirty) || Boolean(row.conflict)}\n onClick={() => onSave(row.id)}\n >\n Save\n </button>\n <DeleteButton label=\"Delete entry\" onClick={() => onDelete(row.id)} />\n {row.conflict && (\n <div className=\"w6w-error\" data-row={rowAttr(row)} data-testid=\"row-conflict\">\n {VERSION_CONFLICT_COPY}{\" \"}\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"row-reload\"\n onClick={() => onReload(row.id)}\n >\n Reload\n </button>\n </div>\n )}\n </div>\n ),\n },\n ];\n return (\n <div>\n {error != null && error !== \"\" && (\n <div className=\"w6w-error\" data-testid=\"grid-error\">\n {error}\n </div>\n )}\n\n <form className=\"w6w-data-entries-toolbar\" data-testid=\"entry-search\" onSubmit={submit}>\n <input\n type=\"search\"\n data-testid=\"entry-prefix\"\n value={prefix}\n placeholder=\"Key prefix\"\n aria-label=\"Key prefix\"\n onChange={(e) => setPrefix(e.target.value)}\n />\n <button className=\"w6w-btn w6w-btn-ghost\" type=\"submit\">\n Search\n </button>\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"grid-add-row\"\n onClick={onAddRow}\n >\n Add row\n </button>\n </form>\n\n <div className=\"w6w-data-grid-scroll\" data-testid=\"data-grid-scroll\">\n <DataTable\n columns={tableColumns}\n rows={rows}\n rowKey={(row) => row.id}\n empty={\n // A div, not a <p>: `empty` is any node and callers often pass a <p>.\n <div className=\"w6w-muted w6w-small\">\n {loading ? \"Loading…\" : (empty ?? \"No rows match this key prefix.\")}\n </div>\n }\n />\n </div>\n\n {hasMore && (\n <button\n className=\"w6w-btn w6w-btn-ghost\"\n type=\"button\"\n data-testid=\"entries-load-more\"\n onClick={onLoadMore}\n >\n Load more\n </button>\n )}\n </div>\n );\n}\n"],"names":["ApiError","status","code","message","body","__publicField","createW6WApi","opts","baseUrl","doFetch","getToken","rawReq","path","init","headers","token","res","e","text","data","err","req","walk","apps","cursor","qs","r","ids","unique","i","id","appId","filter","q","authKey","actionKey","params","connectionId","patch","connId","workflowId","stepId","nodeId","input","inputs","ListItem","title","subtitle","icon","trailing","active","onClick","href","ariaLabel","jsxs","Fragment","jsx","className","relativeTime","iso","then","secs","mins","hours","days","defaultParamsFor","action","out","p","extractProviderMessage","msg","brace","j","m","_b","_a","_c","prefix","isInvokeApiError","describeInvokeError","detail","haystack","apiCallsOf","source","useOverrideJsonField","setText","useState","value","setValue","invalid","setInvalid","next","trimmed","parsed","ActionTestForm","actions","seedValues","onSavedTestsChanged","seedTestId","onDirtyChange","onTestSaved","onDeleted","embedded","api","useW6WApi","sortedActions","useMemo","list","a","b","pickedKey","setPickedKey","selectedAction","running","setRunning","error","setError","result","setResult","apiCalls","setApiCalls","ovBody","ovQuery","ovHeaders","ovTarget","setOvTarget","ovMatch","setOvMatch","overridesInvalid","currentOverrides","viewMode","setViewMode","jsonText","setJsonText","jsonInvalid","setJsonInvalid","modalOpen","setModalOpen","selectedKey","initialValues","valuesByAction","setValuesByAction","editingTestId","setEditingTestId","baseline","setBaseline","fresh","lastSeedTestId","setLastSeedTestId","lastSeed","setLastSeed","structurallyChanged","seeded","values","setValues","dirty","useEffect","enterJsonView","runWith","outcome","overrides","refreshSavedTests","refreshRunHistory","run","savedTests","setSavedTests","savedTestsError","setSavedTestsError","savedTestsNonce","setSavedTestsNonce","nameModalOpen","setNameModalOpen","pendingName","setPendingName","confirmDeleteOpen","setConfirmDeleteOpen","n","canceled","railTests","t","runHistory","setRunHistory","runHistoryNonce","setRunHistoryNonce","load","railRunHistory","openSaveModal","handleSaveClick","submitSaveTest","saved","name","loadSavedTest","loaded","deleteCurrentTest","deletedId","paramsRegion","v","ParamsForm","JsonEditor","valid","overridesRegion","savedTestsRail","deletingTestName","Combobox","errorBox","resultBlock","ResultViewer","paramsAndResult","ApiCallsPanel","actionBar","Modal","ConfirmModal","YamlEditor","props","theme","useEffectiveTheme","copied","copy","useCopyToClipboard","extensions","yaml","EditorView","EDITOR_THEME_SPEC","handleChange","CodeMirror","CheckGlyph","CopyGlyph","MARKER","cropText","chars","crop","head","tail","CopyableText","label","copiedMs","cropped","classes","Copyable","DEFAULT_LABELS","HealthStatusPill","state","STATE_LABELS","UptimeStrip","entry","UNKNOWN","BYTE_UNITS","formatBytes","unit","formatPercent","f","cpuLoadFraction","s","divisor","memoryUsedFraction","memoryTotal","memoryAvailable","clamp","lo","hi","sparklinePoints","width","height","max","points","x","y","SPARK_WIDTH","SPARK_HEIGHT","Sparkline","formatLoad","fractionMax","MetricRow","readings","samples","last","cpuValues","memoryValues","rssValues","ServerResourcesCard","intervalMs","ServerResourcesCardSmall","ServerResourcesRail","onExpand","ServerResourcesBadge","cpu","mem","MIN_BAR_WIDTH_PCT","DAY_MS","placeIncidentBar","window","bar","nowMs","start","startMs","endMs","windowStartMs","windowEndMs","spanMs","clippedStart","clippedEnd","clampedStartMs","clampedEndMs","leftPct","rawWidthPct","widthPct","NO_FEED_LABEL","QUIET_LABEL","barTitle","parts","HistoryTimeline","win","incidents","vendorEmptyLabel","cellWidthPct","emptyLabel","placement","clipClass","InfoTip","children","open","setOpen","useId","IconButton","o","EditButton","disabled","rest","RepoSyncIndicator","branch","shortSha","lastSyncLabel","onSyncNow","syncing","ref","useRef","onDown","onKey","Icon","StepStatusPill","MS_PER_SECOND","MS_PER_MINUTE","formatDurationMs","ms","formatExecutionTime","date","KIND_LABEL","TRIGGER_LABEL","triggerText","item","ExecutionList","items","selectedId","onSelect","showCallable","loading","hasPrev","hasNext","onPrev","onNext","onRerun","rerunningId","pager","describeNode","node","builtin","internalNodeDef","chronologicalSteps","steps","time","step","ExecutionLogPanel","onDismiss","runError","stepErrors","recorded","errors","ExecutionLogErrorBlock","index","inRun","isOffPath","offPath","footer","ExecutionLogOffPath","ExecutionLogRow","SKIP_REASON_LABELS","header","StepTiming","loop","ExecutionLogIterations","hasStateBlock","ExecutionLogState","ExecutionLogConditions","ExecutionLogJson","CodeBlock","iterations","total","failedCount","it","firstFailed","defaultIndex","bodyIds","labels","failedId","ExecutionLogBodyStep","initial","selected","setSelected","record","startedAt","finishedAt","elapsed","formatElapsed","totalSeconds","minutes","seconds","isRecord","conditionTrace","rows","groups","own","route","trace","g","conditionCombinatorLabel","row","conditionOperatorLabel","operandText","STATE_WARNING_LABELS","stateWarningLabel","hasWrites","after","STATE_VALUE_MAX","stateValueText","writes","w","EMPTY","STATUS_OPTIONS","KIND_OPTIONS","ExecutionFilters","onChange","showKind","searchPlaceholder","clearable","option","ExecutionStats","stats","cards","formatSuccessRate","card","rate","toJson","ExecutionDetail","execution","errorMessage","onClose","onOpenInEditor","onBack","rerunning","onOpenExecution","Body","rerunOf","TimingItem","JsonSection","testid","performancePoints","services","needsAttention","service","partitionBoard","uptimeDays","ATTENTION_DISPLAY_CAP","RECENT_DISPLAY_CAP","displayBoard","compact","now","recent","attentionCount","shownNow","shownRecent","shownTable","WIDTH","HEIGHT","PAD","niceMax","magnitude","ticks","count","_","ReliabilityChart","getHref","onOpen","maxCalls","maxP95","maxErrors","plotW","plotH","calls","p95","iconSize","xTicks","yTicks","yAxisTitleX","yAxisTitleY","size","cx","cy","dots","formatDay","d","Target","ExecStatusSignal","ApiStatusSignal","vendor","unreadable","IssueCard","AppIcon","ServiceTableRow","noCalls","ReliabilityList","showChart","limit","showAllHref","onShowAll","slots","windowDays","allClear","hiddenAttentionCount","hiddenTableCount","shouldShowChart","canShowAll","showAllLink","cellValue","col","DataTable","columns","rowKey","onRowClick","getRowHref","empty","testId","c","content","EmptyState","CallableList","description","emptyCopy","newLabel","openRowTitle","testIds","onCreate","creating","onImport","showArchivedProp","onShowArchivedChange","showArchivedState","setShowArchivedState","controlled","showArchived","visible","interactive","setShowArchived","archivedOnly","event","ConnectionList","connections","appsById","onEdit","onDelete","busy","byId","hasActions","app","resolveConnectionAppMeta","DeleteButton","EditConnectionModal","connection","onSaved","update","builtIn","editable","displayName","setDisplayName","setAuthKey","credential","setCredential","auths","setAuths","pending","setPending","bindingVals","setBindingVals","connectionCount","setConnectionCount","credentialContract","setCredentialContract","health","setHealth","authDef","authChanged","authChoices","isOAuth","fields","credentialId","storedCredential","bindingFields","bindingFieldsFor","buildBody","binding","buildBinding","filled","save","hasCredential","missing","parseJsonFields","credentialSaved","updated","checkHealth","enterSubmit","useEnterSubmit","AuthFieldsForm","ConnectionHeader","conn","defaultFormat","pct","clamped","BudgetMeter","used","reserved","format","fmt","hasReserved","usedPct","reservedPct","over","valueText","DATA_STORE_KIND_LABEL","DATA_STORE_KINDS","SCALAR_TYPES","CSV_MAX_BYTES","kvValueTypeOf","store","declared","tableSchemaOf","key","csvFilenameOf","contentDisposition","storeName","quoted","CELL_PROBLEM_COPY","NUMBER_TEXT","INTEGER_TEXT","DATE_TEXT","DATETIME_TEXT","daysInMonth","year","month","readDate","day","refuse","problem","parseCell","type","required","isDateTime","hour","minute","second","zone","serializeCell","json","isCellValue","DATA_STORE_ERROR_FALLBACK","DATA_STORE_NETWORK_ERROR","textOf","rowOf","locatorFromEnvelope","fallbackMessages","locator","envelope","field","column","candidate","locateDataStoreError","shaped","raw","ownMessage","locateRawResponseError","errorPlacement","loc","csvLineOf","NEW_ROW_ID","VERSION_CONFLICT_COPY","DOC_VALUE_COPY","CSV_TOO_LARGE_COPY","rowValueOf","draftFromEntry","cells","newRowDraft","dirtyColumns","draft","base","buildRowValue","remainingTtlSeconds","expiresAt","rowWriteOf","ttlSeconds","write","cellErrorsOf","isVersionConflict","parseDocText","kvValueOf","csvImportMessage","imported","DataStoreList","stores","onArchive","formatSize","eligibleAsKey","withDefault","_old","ColumnsEditor","keyColumn","onKeyColumnChange","columnErrors","drafts","setDrafts","eligible","eligibleKey","addColumn","updateColumn","idx","setDefault","extra","removeColumn","k","CsvPanel","onRefuse","onExport","onFile","file","DataEntryList","searchValue","hasMore","onSearch","onNew","onLoadMore","setPrefix","submit","DataEntryEditor","kind","isNew","entryKey","newKey","conflict","saving","onTextChange","onKeyChange","onSave","onCancel","onReload","editing","setEditing","showValidation","setShowValidation","closeButton","noun","parsedDocument","invalidDocument","valueError","rowAttr","DataTableGrid","onCellChange","onAddRow","tableColumns"],"mappings":"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"}
|