@w6w/embed 0.2.19 → 0.2.21
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/dist/{WorkflowEditor-CmhXHRxi.js → WorkflowEditor-Cgv3Pvsy.js} +194 -186
- package/dist/{WorkflowEditor-CmhXHRxi.js.map → WorkflowEditor-Cgv3Pvsy.js.map} +1 -1
- package/dist/{apps-ItBvnWX3.js → apps-CYUgEfGf.js} +2 -2
- package/dist/{apps-ItBvnWX3.js.map → apps-CYUgEfGf.js.map} +1 -1
- package/dist/editor/types.d.ts +2 -0
- package/dist/{editor-apps-DkkC7wOQ.js → editor-apps-LZmDWMqf.js} +3 -3
- package/dist/{editor-apps-DkkC7wOQ.js.map → editor-apps-LZmDWMqf.js.map} +1 -1
- package/dist/{editor-tools-BR27RGto.js → editor-tools-j3ThBY_4.js} +3 -3
- package/dist/{editor-tools-BR27RGto.js.map → editor-tools-j3ThBY_4.js.map} +1 -1
- package/dist/editor.mjs +1 -1
- package/dist/editors.mjs +7 -7
- package/dist/index.mjs +1 -1
- package/dist/lists.mjs +3 -3
- package/dist/rail.mjs +1 -1
- package/dist/repos/connections.d.ts +1 -0
- package/dist/repos/workflows.d.ts +1 -1
- package/dist/repos.mjs +3 -3
- package/dist/{spec-export-DGy5ijps.js → spec-export-DGigBUsP.js} +2 -2
- package/dist/{spec-export-DGy5ijps.js.map → spec-export-DGigBUsP.js.map} +1 -1
- package/dist/{workflows-BZN4Hyz1.js → workflows-BK6IM4if.js} +3 -3
- package/dist/{workflows-BZN4Hyz1.js.map → workflows-BK6IM4if.js.map} +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows-BZN4Hyz1.js","sources":["../src/lib/workflow-live-run.ts","../src/lib/workflow-poll.ts","../src/lib/history-query.ts","../src/repos/workflows.ts"],"sourcesContent":["/**\n * Pure decision layer for the visual editor's live Run/Stop feature (T2.1.1,\n * A7). Every judgment call this feature makes that is NOT layout — is a run\n * in flight? should polling continue? is the canvas editable right now? what\n * should the Run button say and is it disabled? how does a cancel failure\n * get handled? how does a `RunState`'s steps map to the execution log\n * panel's rows, and what error does each row and the run show? what `input`\n * does the header Run send? — lives here as plain functions of (run state) -> result,\n * with no `.tsx` import and no React import, so `node --test` can load this\n * module directly. Same mechanical reason `workflow-poll.ts` and\n * `repos/reliability-uptime.ts` exist as separate `.ts` modules — read\n * `workflow-poll.ts`'s own header. `WorkflowsPage.tsx` calls these functions\n * rather than restating the conditions inline.\n */\nimport { type StateLogRow, foldStateLog } from \"@w6w/expr\";\nimport { type RunStatus, isTerminalRunStatus } from \"@w6w/sdk\";\n\nexport type { RunStatus };\n\n/**\n * The five states a workflow step's execution can be in — a thin LOCAL copy\n * of `@w6w/ui`'s `StepStatus` (itself a thin local copy of the engine's\n * `StepStatus` — see `run-visuals.ts`'s own header in `packages/ui`, the\n * same house idiom). `@w6w/sdk/console`'s `RunState.steps` is deliberately\n * typed `Record<string, unknown>` — opaque pass-through, by that module's\n * own documented design — so the real per-step shape has to be re-stated\n * here rather than imported.\n */\nexport type StepStatus = \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n\n/** The per-step metadata (which app/version/action/connection ran) — one\n * local structural copy of the pinned `StepMeta`. A `type` alias, not an\n * `interface`, so it stays assignable to index-signature types. */\nexport type StepMetaLike = {\n app: string;\n version: string;\n action: string;\n connectionId: string | null;\n};\n\n/** The slice of a `StepExecution` this module reads, to build one\n * `ExecutionLogPanel` row. */\nexport interface StepExecutionLike {\n status: StepStatus;\n /** Why a `skipped` step did not run (`NodeExecution.skipReason`); read as `unknown` (opaque\n * wire) and carried only when it is one of the four known reasons. */\n skipReason?: unknown;\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n logs?: string[];\n /** `StepExecution.error` — a `StepError` on `failed` per rfcs/workflow.md\n * §StepExecution, but read as `unknown` because `RunState.steps` is opaque\n * on the wire; {@link toLogError} normalises whatever actually arrives. */\n error?: unknown;\n /** Recorded metadata; absent (or null) for steps that recorded none. */\n meta?: StepMetaLike | null;\n /** For each only (I3): per-iteration body records, read as `unknown` (opaque wire). */\n iterations?: unknown;\n iterationsTotal?: unknown;\n iterationsFailed?: unknown;\n iterationsTruncated?: unknown;\n}\n\n/** A step or run error, as the run log panel renders it — field-for-field\n * `@w6w/ui`'s `ExecutionLogError` (rfcs/workflow.md §StepError's\n * `code`/`message`/`phase`/`retryable`), restated locally for the same reason\n * as {@link ExecutionLogStepLike} below. `message` is never empty. */\nexport interface LogErrorLike {\n code?: string;\n message: string;\n phase?: string;\n retryable?: boolean;\n}\n\n/** One `RunState.stepErrors` entry the panel shows at run level — field-for-field\n * `@w6w/ui`'s `ExecutionLogRecordedError`, restated locally (see above). */\nexport interface RecordedLogErrorLike {\n stepId: string;\n label?: string;\n error: LogErrorLike;\n}\n\n/** The slice of a `RunState` {@link runLevelErrors} reads. */\nexport interface RunErrorSourceLike {\n status?: string;\n error?: unknown;\n stepErrors?: ReadonlyArray<{ nodeId?: string; stepId?: string; error: unknown }>;\n}\n\n/** The per-node execution map of a run record, in either shape — `nodes`\n * preferred, else the legacy `steps`. */\nexport function runNodeMap(\n run: { nodes?: unknown; steps?: unknown } | undefined | null,\n): Record<string, StepExecutionLike> | undefined {\n return (run?.nodes ?? run?.steps ?? undefined) as Record<string, StepExecutionLike> | undefined;\n}\n\n/** The slice of a saved step-test fixture (`StepTest`) {@link latestFixtureInput}\n * reads — `with` is what the trigger's Test tab invokes it with. */\nexport interface StepTestFixtureLike {\n with?: unknown;\n}\n\n/** The row-level fallback for a `failed` step that carries no `error` at all. */\nexport const STEP_FAILED_NO_REASON = \"Node failed without reporting a reason.\";\n\n/** The run-level fallback for a `failed` run where nothing carries a reason. */\nexport const RUN_FAILED_NO_REASON = \"Run failed without reporting a reason.\";\n\n/** One `ExecutionLogPanel` row — field-for-field `@w6w/ui`'s\n * `ExecutionLogStep`, restated locally for the same reason as\n * {@link StepExecutionLike} above (no runtime dependency on `@w6w/ui`,\n * which this module must not import — see the file header). */\nexport interface ExecutionLogStepLike {\n id: string;\n status: StepStatus;\n skipReason?: SkipReasonLike;\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n logs?: string[];\n error?: LogErrorLike;\n meta?: StepMetaLike;\n /** For each only (I4) — field-for-field `@w6w/ui`'s `ExecutionLogStep`. */\n iterations?: ExecutionLogIterationLike[];\n iterationsTotal?: number;\n iterationsFailed?: number;\n iterationsTruncated?: boolean;\n /** This node's state writes (`GET /runs/:id/state-writes` rows, in `seq` order) —\n * field-for-field `@w6w/ui`'s `ExecutionLogStep.stateWrites` (plan §2.7). Absent → no State block. */\n stateWrites?: StateWriteEntryLike[] | null;\n /** The state tree right after this node's last write (`foldStateLog`). */\n stateAfter?: Record<string, unknown> | null;\n}\n\n/** One state-write entry on a run-log row — `@w6w/ui`'s `ExecutionLogStep.stateWrites[number]`. */\nexport type StateWriteEntryLike = {\n path: string[];\n item?: number;\n old?: unknown;\n new?: unknown;\n warning?: string;\n};\n\n/** One For each iteration row (I4) — mirrors `@w6w/ui`'s `ExecutionLogIteration`. */\nexport interface ExecutionLogIterationLike {\n index: number;\n status: \"succeeded\" | \"failed\" | \"running\";\n failedNodeId?: string;\n steps: ExecutionLogStepLike[];\n}\n\n/** How a cancel-request failure should be handled (A6). */\nexport type CancelErrorOutcome = \"reconcile\" | \"surface\";\n\n/**\n * A2/M1 — the `refetchInterval` decision: keep polling (`true`) until the\n * run's status is terminal (`false`), including while no run has answered\n * yet (`status === undefined` — the very first poll hasn't landed, or no run\n * is active at all).\n */\nexport function shouldContinuePolling(status: RunStatus | undefined): boolean {\n return status === undefined || !isTerminalRunStatus(status);\n}\n\n/**\n * A4/M2/M3 — is a run currently \"in flight\" from this page's point of view?\n * `true` only while the poll has a live, non-terminal status AND the poll\n * itself hasn't given up/errored — a failed poll unlocks the canvas exactly\n * like reaching a real terminal status does (A4's own named failure case: \"a\n * canvas that stays locked after a cancel\"). Drives the canvas's `readOnly`\n * prop, the Stop button's visibility, and the Run button's disabled state —\n * one function, three call sites, so they can never drift out of sync with\n * each other.\n */\nexport function isRunInFlight(status: RunStatus | undefined, pollFailed: boolean): boolean {\n if (pollFailed) return false;\n if (status === undefined) return false;\n return !isTerminalRunStatus(status);\n}\n\n/**\n * When a run turns terminal, how long after (ms) the editor re-reads the workflow's saved step\n * tests. The server books every step that succeeded in an editor run as its passing saved test\n * (`step-passes.ts`) — the record the publish gate reads — but only AFTER the engine has\n * checkpointed the run's terminal state, so the poll can see `succeeded` a few milliseconds before\n * the pass lands. The immediate read covers the usual case; the later one covers that window.\n */\nexport const STEP_PASS_REFRESH_DELAYS_MS: readonly number[] = [0, 1500];\n\n/**\n * Should the editor re-read this workflow's saved step tests now? Only once the run it polls is\n * terminal and belongs to the open workflow — a run's passes are booked as it finishes, and the\n * step-tests cache never refetches on its own (`refetchOnWindowFocus: false`), so without this\n * the publish gate keeps the pre-run list and a step that just passed still blocks Publish.\n */\nexport function stepPassRefreshDue(\n status: RunStatus | undefined,\n runWorkflowId: string | undefined,\n workflowId: string,\n): boolean {\n return status !== undefined && isTerminalRunStatus(status) && runWorkflowId === workflowId;\n}\n\n/** A1/A6 — what the Run button should read right now. */\nexport function runButtonLabel(status: RunStatus | undefined, pollFailed: boolean): string {\n if (!isRunInFlight(status, pollFailed)) return \"Run\";\n return status === \"queued\" ? \"Queued…\" : \"Running…\";\n}\n\n/**\n * A6/M6 — classify a `cancel()` failure. `run_not_cancelable` (409) means\n * the run already reached a terminal state before the cancel request landed\n * — not a user-facing error, just reconcile to whatever the next poll\n * reports. Everything else (`unknown_run`, a network failure, …) is a real\n * failure the page's existing error affordance must show.\n */\nexport function classifyCancelError(code: string): CancelErrorOutcome {\n return code === \"run_not_cancelable\" ? \"reconcile\" : \"surface\";\n}\n\n/**\n * G5 — map a `RunState`'s opaque `steps` record onto `ExecutionLogPanel`'s\n * row shape, preserving its keys and timestamps. Record key order is not\n * execution order; `ExecutionLogPanel` sorts the rows chronologically for\n * both live runs and saved history.\n */\nexport function mapRunStateToLogSteps(\n steps: Record<string, StepExecutionLike> | undefined,\n stateLog?: readonly StateLogRow[],\n): ExecutionLogStepLike[] {\n if (!steps) return [];\n const state = stateLog ? stateFieldsByNode(stateLog) : undefined;\n return Object.entries(steps).map(([id, step]) => ({\n ...mapStep(id, step),\n ...iterationFields(step),\n ...(state?.get(id) ?? {}),\n }));\n}\n\n/**\n * The run's state-write log (`GET /runs/:id/state-writes`) grouped by node, in `seq`\n * order whatever order the rows arrive in: each node's entries (only `path` plus the\n * `item`/`old`/`new`/`warning` a row has — never `seq`/`nodeId`/`step`) and the tree\n * right after its last row, folded by `@w6w/expr`'s `foldStateLog` (one fold for the\n * whole product, R18). Rows with a null `nodeId` (the base row) attach to no node but\n * still seed every fold.\n */\nfunction stateFieldsByNode(\n log: readonly StateLogRow[],\n): Map<string, Pick<ExecutionLogStepLike, \"stateWrites\" | \"stateAfter\">> {\n const rows = [...log].sort((a, b) => a.seq - b.seq);\n const byNode = new Map<string, { writes: StateWriteEntryLike[]; lastSeq: number }>();\n for (const row of rows) {\n if (row.nodeId === null || row.nodeId === undefined) continue;\n const entry: StateWriteEntryLike = { path: row.path };\n if (row.item !== undefined) entry.item = row.item;\n if (row.old !== undefined) entry.old = row.old;\n if (row.new !== undefined) entry.new = row.new;\n if (row.warning !== undefined) entry.warning = row.warning;\n const group = byNode.get(row.nodeId) ?? { writes: [], lastSeq: row.seq };\n group.writes.push(entry);\n group.lastSeq = row.seq;\n byNode.set(row.nodeId, group);\n }\n const out = new Map<string, Pick<ExecutionLogStepLike, \"stateWrites\" | \"stateAfter\">>();\n for (const [id, { writes, lastSeq }] of byNode) {\n out.set(id, { stateWrites: writes, stateAfter: foldStateLog(rows, lastSeq) });\n }\n return out;\n}\n\n/** `@w6w/ui`'s `SkipReason`, restated locally (see {@link ExecutionLogStepLike}). */\nexport type SkipReasonLike = \"not_on_path\" | \"condition\" | \"stopped\" | \"disabled\";\n\nconst SKIP_REASONS: ReadonlySet<unknown> = new Set([\n \"not_on_path\",\n \"condition\",\n \"stopped\",\n \"disabled\",\n]);\n\n/** One wire record -> one row (shared by top-level rows and iteration body steps). */\nfunction mapStep(id: string, step: StepExecutionLike): ExecutionLogStepLike {\n return {\n id,\n status: step.status,\n ...(step.status === \"skipped\" && SKIP_REASONS.has(step.skipReason)\n ? { skipReason: step.skipReason as SkipReasonLike }\n : {}),\n startedAt: step.startedAt,\n finishedAt: step.finishedAt,\n input: step.input,\n output: step.output,\n ...(Array.isArray(step.logs) && step.logs.length\n ? { logs: step.logs.filter((line): line is string => typeof line === \"string\") }\n : {}),\n ...(step.meta !== undefined && step.meta !== null ? { meta: step.meta } : {}),\n ...rowError(step),\n };\n}\n\nconst ITERATION_STATUSES: ReadonlySet<unknown> = new Set([\"succeeded\", \"failed\", \"running\"]);\n\n/** The I4 `iterations*` keys for a For each record (I3) — empty (no own keys) when\n * `iterations` is not an array. */\nfunction iterationFields(\n step: StepExecutionLike,\n): Pick<\n ExecutionLogStepLike,\n \"iterations\" | \"iterationsTotal\" | \"iterationsFailed\" | \"iterationsTruncated\"\n> {\n if (!step || !Array.isArray(step.iterations)) return {};\n const iterations = (step.iterations as Array<Record<string, unknown> | null>)\n .filter((it): it is Record<string, unknown> => it !== null && typeof it === \"object\")\n .map((it) => {\n const nodes =\n it.nodes !== null && typeof it.nodes === \"object\"\n ? (it.nodes as Record<string, StepExecutionLike>)\n : {};\n const steps = Object.entries(nodes).map(([id, s]) => mapStep(id, s));\n const failedNodeId =\n typeof it.failedNodeId === \"string\" && it.failedNodeId !== \"\"\n ? it.failedNodeId\n : steps.find((s) => s.status === \"failed\")?.id;\n const status = ITERATION_STATUSES.has(it.status)\n ? (it.status as ExecutionLogIterationLike[\"status\"])\n : steps.some((s) => s.status === \"failed\")\n ? \"failed\"\n : steps.some((s) => s.status === \"running\")\n ? \"running\"\n : \"succeeded\";\n return {\n index: it.index as number,\n status,\n ...(failedNodeId !== undefined ? { failedNodeId } : {}),\n steps,\n };\n })\n .sort((a, b) => a.index - b.index);\n const finite = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n);\n return {\n iterations,\n ...(finite(step.iterationsTotal) ? { iterationsTotal: step.iterationsTotal } : {}),\n ...(finite(step.iterationsFailed) ? { iterationsFailed: step.iterationsFailed } : {}),\n ...(typeof step.iterationsTruncated === \"boolean\"\n ? { iterationsTruncated: step.iterationsTruncated }\n : {}),\n };\n}\n\n/** The `error` key for one row — present ONLY when the step reports an error\n * or is `failed` (then with {@link STEP_FAILED_NO_REASON}), so a healthy row\n * keeps exactly the shape it had before errors were carried. */\nfunction rowError(step: StepExecutionLike): { error?: LogErrorLike } {\n const error = toLogError(step.error);\n if (error) return { error };\n if (step.status === \"failed\") return { error: { message: STEP_FAILED_NO_REASON } };\n return {};\n}\n\n/**\n * Normalise whatever a step or run reported as its error into the panel's\n * {@link LogErrorLike}. `null`/`undefined` mean \"no error\". A non-empty string\n * is the message. An object contributes `code` (string), `message` (its own\n * non-empty `message`, else a non-empty `code`, else its JSON), `phase`\n * (string) and `retryable` (boolean). Anything else is stringified. The\n * returned `message` is never empty.\n */\nexport function toLogError(raw: unknown): LogErrorLike | undefined {\n if (raw === null || raw === undefined) return undefined;\n if (typeof raw === \"string\" && raw !== \"\") return { message: raw };\n if (typeof raw === \"object\") {\n const o = raw as Record<string, unknown>;\n const code = typeof o.code === \"string\" ? o.code : undefined;\n const message =\n typeof o.message === \"string\" && o.message !== \"\" ? o.message : code || safeJson(raw);\n return {\n ...(code !== undefined ? { code } : {}),\n message: message || \"Unknown error.\",\n ...(typeof o.phase === \"string\" ? { phase: o.phase } : {}),\n ...(typeof o.retryable === \"boolean\" ? { retryable: o.retryable } : {}),\n };\n }\n return { message: String(raw) || \"Unknown error.\" };\n}\n\n/** `JSON.stringify` that answers `\"\"` instead of throwing (a cycle, a BigInt)\n * or returning `undefined` (a `toJSON` that yields nothing). */\nfunction safeJson(raw: unknown): string {\n try {\n return JSON.stringify(raw) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/**\n * The run-level half of the run log: `RunState.error` as `runError`, plus the\n * `RunState.stepErrors` entries whose step has NO row already carrying an\n * error (a `continue-record` failure is usually also on its own row — showing\n * it twice would read as two failures), in their given order. A row showing\n * only {@link STEP_FAILED_NO_REASON} does not count as carrying an error here,\n * so the reason recorded for that step is still surfaced. A `failed` run where\n * nothing — run, rows or surfaced step errors — carries a reason gets\n * {@link RUN_FAILED_NO_REASON}. `runError` is omitted when it duplicates a\n * row's error (equal `message` and equal `code`), since the step failure that\n * stopped the run is already shown on its row. It is likewise omitted when it\n * duplicates a surfaced `stepErrors` entry's error, by the same equality.\n * Keys are omitted when empty.\n */\nexport function runLevelErrors(\n run: RunErrorSourceLike | undefined,\n rows: ReadonlyArray<ExecutionLogStepLike>,\n): { runError?: LogErrorLike; stepErrors?: RecordedLogErrorLike[] } {\n if (!run) return {};\n const carried = new Set(rows.filter((r) => r.error !== undefined).map((r) => r.id));\n const reasoned = new Set(\n rows\n .filter((r) => r.error !== undefined && r.error.message !== STEP_FAILED_NO_REASON)\n .map((r) => r.id),\n );\n const stepErrors = (run.stepErrors ?? [])\n .map((e) => ({ e, id: e.nodeId ?? e.stepId ?? \"\" }))\n .filter(({ id }) => !reasoned.has(id))\n .map(({ e, id }) => ({\n stepId: id,\n error: toLogError(e.error) ?? { message: STEP_FAILED_NO_REASON },\n }));\n const own = toLogError(run.error);\n const sameAsOwn = (e: LogErrorLike | undefined) =>\n own !== undefined && e?.message === own.message && e?.code === own.code;\n const shown = rows.some((r) => sameAsOwn(r.error)) || stepErrors.some((e) => sameAsOwn(e.error));\n let runError = shown ? undefined : own;\n if (!runError && run.status === \"failed\" && carried.size === 0 && stepErrors.length === 0) {\n runError = { message: RUN_FAILED_NO_REASON };\n }\n return {\n ...(runError ? { runError } : {}),\n ...(stepErrors.length > 0 ? { stepErrors } : {}),\n };\n}\n\n/**\n * The header Run's `input`: the LAST saved fixture's `with` (`listStepTests`\n * answers oldest-first — the same \"last is latest\" reading\n * `@w6w/ui`'s `TriggerFillForm` seeds from), when it is a plain object.\n * Sent verbatim — `{type:\"expr\",…}` values included.\n */\nexport function latestFixtureInput(\n tests: ReadonlyArray<StepTestFixtureLike> | undefined,\n): Record<string, unknown> | undefined {\n const last = tests?.[tests.length - 1]?.with;\n if (last === null || typeof last !== \"object\" || Array.isArray(last)) return undefined;\n return last as Record<string, unknown>;\n}\n\n/**\n * Resolve the header Run's `input` for the manual trigger `triggerStepId`.\n * No trigger id → `undefined` without fetching. A fetch that throws or\n * rejects → `undefined`: a missing fixture never blocks the run. Fetched at\n * click time on purpose — a cached `stepTestsKey` query can be stale, since\n * saving a fixture does not invalidate it.\n */\nexport async function resolveHeaderRunInput(\n triggerStepId: string | undefined,\n list: (stepId: string) => Promise<ReadonlyArray<StepTestFixtureLike> | undefined>,\n remembered?: () => Promise<ReadonlyArray<{ nodeId: string; input: unknown }> | undefined>,\n): Promise<Record<string, unknown> | undefined> {\n if (!triggerStepId) return undefined;\n // The REMEMBERED test input (`node_test_inputs`) is what the trigger last ran with on any\n // editor surface, so it wins; a `{}` row was cleared (no `input`, no fixture fallback). No row\n // (or a failed read) falls back to the latest fixture, exactly as before.\n if (remembered) {\n try {\n const row = (await remembered())?.find((r) => r.nodeId === triggerStepId);\n if (row) {\n const input = row.input;\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) return undefined;\n return Object.keys(input).length > 0 ? (input as Record<string, unknown>) : undefined;\n }\n } catch {\n // fall through to the fixture\n }\n }\n try {\n return latestFixtureInput(await list(triggerStepId));\n } catch {\n return undefined;\n }\n}\n\n/** The trigger the header Run starts at, and whether it is the Manual trigger. */\nexport interface HeaderRunEntry {\n id: string;\n manual: boolean;\n}\n\n/**\n * The trigger the header Run starts at, and so whose remembered sample payload it runs with: the\n * FIRST Manual trigger (a run's own default entry), else the first other entry trigger — a\n * webhook, a schedule or an app trigger. Before, only a Manual trigger was looked up, so a\n * webhook-started workflow's header Run sent no payload at all. `undefined` when nothing in\n * `steps` is a trigger. The predicates are injected (`@w6w/ui/flow`), as in `trigger-preview.ts`.\n */\nexport function headerRunEntry(\n steps: ReadonlyArray<{ id: string; uses?: { app?: string; trigger?: unknown } }>,\n isManualTrigger: (app: string) => boolean,\n isEntryTrigger: (uses: { app: string; trigger?: true }) => boolean,\n): HeaderRunEntry | undefined {\n const manual = steps.find((s) => !!s.uses?.app && isManualTrigger(s.uses.app));\n if (manual) return { id: manual.id, manual: true };\n const other = steps.find(\n (s) =>\n !!s.uses?.app &&\n isEntryTrigger({ app: s.uses.app, ...(s.uses.trigger === true ? { trigger: true } : {}) }),\n );\n return other ? { id: other.id, manual: false } : undefined;\n}\n","/**\n * The run-polling loop, split out of `api/client.ts`'s original `runWorkflow`\n * into its own PURE module — for the SAME mechanical reason\n * `repos/reliability-uptime.ts` exists (read that file's own header comment in\n * full): a `.ts` module that would otherwise transitively import\n * `../api/apiClient.tsx` (a `.tsx` file Node's type-stripping cannot load at\n * all) must be split out to stay reachable by `node --test`.\n *\n * Ported field-for-field from `api/client.ts`'s original `runWorkflow` (same\n * 500 ms interval, same 600-iteration cap, same \"one more fetch after the\n * loop\" shape) — the ONLY change is the injected `getRun`/`sleep` parameters,\n * which is what makes this loop testable on a fake clock instead of a real\n * 5-minute wait. See `../repos/workflows.ts` for the caller.\n */\nimport type { RunState } from \"@w6w/sdk/console\";\n\nconst TERMINAL = new Set([\"succeeded\", \"failed\", \"canceled\"]);\n\nfunction realSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll `getRun` until the run reaches a terminal status, or 600 polls (~5\n * minutes at the default 500ms interval) elapse — whichever comes first.\n * Ported verbatim from `api/client.ts`'s `runWorkflow`; see\n * `../repos/workflows.ts` for the caller.\n */\nexport async function pollRunToTerminal(\n getRun: () => Promise<RunState>,\n sleep: (ms: number) => Promise<void> = realSleep,\n): Promise<RunState> {\n for (let i = 0; i < 600; i++) {\n const run = await getRun();\n if (TERMINAL.has(run.status)) return run;\n await sleep(500);\n }\n return getRun();\n}\n","// Run: node --test src/lib/__tests__/history-query.test.ts (Node 24, type-stripped)\n//\n// T2.3.1 — the pure data layer behind the project-wide and per-callable\n// History page (T2.4.1) and the Function/Endpoint/Workflow header's History\n// button (T2.4.2). Everything that is a judgment call rather than React\n// plumbing lives here: how a URL's search string becomes a `HistoryFilters`\n// (and back), how a filter set becomes the wire's own query params, the\n// query keys every hook in `repos/history.ts` shares, and how a summary row\n// is expanded into a full detail view for one of the three callable kinds.\n//\n// Zero runtime imports other than `./workflow-live-run.ts` and\n// `./workflow-poll.ts` (A1) — every other import here is `import type`, erased\n// at build time, so `node --test` can load this module directly with no React,\n// no SDK runtime, no JSX. The first reuses `mapRunStateToLogSteps`, the same\n// step mapper the visual editor's live-run overlay already uses, so a\n// workflow's historical detail view renders steps identically to its live\n// one; the second is the same run-polling loop the editor's own Run uses, so a\n// re-run waits for its workflow exactly as a run started there does.\n//\n// The wire shape (`ExecutionKind`, `ExecutionStatus`, `ExecutionSummary`,\n// `ExecutionStats`) is pinned verbatim against T2.1.1's own contract — do not\n// drift it; T2.4.1/T2.4.2 are written against this file's exports exactly.\n\nimport type { W6WClient } from \"@w6w/sdk\";\nimport { mapRunStateToLogSteps, runNodeMap } from \"./workflow-live-run.ts\";\nimport { pollRunToTerminal } from \"./workflow-poll.ts\";\n\n// ── wire types (pinned, identical to T2.1.1 §Wire) ──────────────────────\n\nexport type ExecutionKind = \"function\" | \"endpoint\" | \"workflow\";\nexport type ExecutionStatus = \"queued\" | \"running\" | \"succeeded\" | \"failed\" | \"canceled\";\n\nexport interface ExecutionSummary {\n id: string;\n kind: ExecutionKind;\n callableId: string;\n callableName: string;\n status: ExecutionStatus;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n workflowRunId: string | null;\n /** The execution this one RE-RUNS (History's Re-run), or `null`. Absent from an older server. */\n rerunOf?: string | null;\n /** How a workflow run was started (manual, schedule, webhook, event, replay); `null` for a\n * Function/Endpoint call. Absent from an older server. */\n trigger?: string | null;\n /** The trigger node a workflow run entered through. Absent from an older server. */\n triggerNodeId?: string | null;\n /** The start of the input as JSON text. Absent from an older server. */\n inputPreview?: string | null;\n}\n\nexport interface ExecutionStats {\n total: number;\n succeeded: number;\n failed: number;\n canceled: number;\n inFlight: number;\n successRate: number | null;\n avgDurationMs: number | null;\n}\n\n// ── scope + filters ───────────────────────────────────────────────────────\n\n/** Either the project-wide view or one callable's own history — mutually\n * exclusive, never both, mirroring the wire's own `project`|`callable`\n * params (exactly one). */\nexport type HistoryScope = { project: string } | { callable: string };\n\n/** Everything the History page's filter chrome can set, already parsed out\n * of the URL. `status`/`kind` are `\"\"` for \"any\"; `from`/`to` are the\n * `YYYY-MM-DD` the date pickers hand back, or `\"\"` for unset; `offset` is\n * always a non-negative integer (0 for \"first page\"). */\nexport interface HistoryFilters {\n status: ExecutionStatus | \"\";\n kind: ExecutionKind | \"\";\n from: string;\n to: string;\n q: string;\n offset: number;\n}\n\nexport const EMPTY_HISTORY_FILTERS: HistoryFilters = {\n status: \"\",\n kind: \"\",\n from: \"\",\n to: \"\",\n q: \"\",\n offset: 0,\n};\n\nexport const HISTORY_PAGE_SIZE = 25;\n\nconst VALID_STATUSES: ReadonlySet<string> = new Set([\n \"queued\",\n \"running\",\n \"succeeded\",\n \"failed\",\n \"canceled\",\n]);\nconst VALID_KINDS: ReadonlySet<string> = new Set([\"function\", \"endpoint\", \"workflow\"]);\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** True when `YYYY-MM-DD` names a real calendar day (`2026-02-30` rolls into\n * March through `new Date`, so a round-trip comparison rejects it). */\nfunction isRealDate(s: string): boolean {\n if (!DATE_RE.test(s)) return false;\n const { y, m, d } = dateParts(s);\n const dt = new Date(y, m - 1, d);\n return dt.getFullYear() === y && dt.getMonth() === m - 1 && dt.getDate() === d;\n}\n\n/** Parse a validated `YYYY-MM-DD` string into its three numeric parts. */\nfunction dateParts(value: string): { y: number; m: number; d: number } {\n const [y, m, d] = value.split(\"-\").map(Number);\n return { y, m, d };\n}\n\n/**\n * URL search string → `HistoryFilters`. An unrecognised `status`/`kind`, a\n * `from`/`to` not matching `YYYY-MM-DD`, or a non-integer/negative `offset`\n * all fall back to their empty/zero default rather than carrying a bogus\n * value forward into a request — a stale or hand-edited URL degrades to \"no\n * filter\" instead of erroring.\n */\nexport function filtersFromSearch(search: string): HistoryFilters {\n const params = new URLSearchParams(search);\n const status = params.get(\"status\") ?? \"\";\n const kind = params.get(\"kind\") ?? \"\";\n const from = params.get(\"from\") ?? \"\";\n const to = params.get(\"to\") ?? \"\";\n const q = params.get(\"q\") ?? \"\";\n const offsetRaw = params.get(\"offset\");\n let offset = 0;\n if (offsetRaw !== null) {\n const n = Number(offsetRaw);\n if (Number.isInteger(n) && n >= 0) offset = n;\n }\n return {\n status: VALID_STATUSES.has(status) ? (status as ExecutionStatus) : \"\",\n kind: VALID_KINDS.has(kind) ? (kind as ExecutionKind) : \"\",\n from: isRealDate(from) ? from : \"\",\n to: isRealDate(to) ? to : \"\",\n q,\n offset,\n };\n}\n\n/**\n * `HistoryFilters` → URL search string. `\"\"` when every field is at its\n * default, else a leading-`?` string with only the non-default fields, in\n * the pinned key order `status,kind,from,to,q,offset` (so two renders of the\n * same filters always produce byte-identical URLs — stable for bookmarking\n * and for `filtersFromSearch` round-tripping).\n */\nexport function filtersToSearch(f: HistoryFilters): string {\n const params = new URLSearchParams();\n if (f.status !== \"\") params.set(\"status\", f.status);\n if (f.kind !== \"\") params.set(\"kind\", f.kind);\n if (f.from !== \"\") params.set(\"from\", f.from);\n if (f.to !== \"\") params.set(\"to\", f.to);\n if (f.q !== \"\") params.set(\"q\", f.q);\n if (f.offset > 0) params.set(\"offset\", String(f.offset));\n const s = params.toString();\n return s === \"\" ? \"\" : `?${s}`;\n}\n\n/**\n * `HistoryFilters` + a scope → the wire's own query params (D3/pinned rules).\n * `kind` is sent only for a project scope with a non-empty kind — a\n * per-callable view already knows its one kind, and the server's `kind`\n * param is project-mode-only. `from`/`to` are expanded from the picked\n * calendar day into the half-open `[from, to)` ISO instant range the wire\n * wants — `to` is the NEXT day's midnight so the picked day itself is fully\n * inclusive. `q` is trimmed and omitted when blank (server-side id/name\n * search, D3 — never a payload scan). Paging params are added only when\n * `opts.paged`: `limit` always (defaulting to `HISTORY_PAGE_SIZE`), `offset`\n * only when it would change anything (`> 0`).\n */\nexport function historyRequestQuery(\n scope: HistoryScope,\n f: HistoryFilters,\n opts: { paged: boolean; limit?: number },\n): Record<string, string> {\n const query: Record<string, string> = {};\n\n if (\"project\" in scope) {\n query.project = scope.project;\n if (f.kind !== \"\") query.kind = f.kind;\n } else {\n query.callable = scope.callable;\n }\n\n if (f.status !== \"\") query.status = f.status;\n\n if (f.from !== \"\" && isRealDate(f.from)) {\n const { y, m, d } = dateParts(f.from);\n query.from = new Date(y, m - 1, d).toISOString();\n }\n if (f.to !== \"\" && isRealDate(f.to)) {\n const { y, m, d } = dateParts(f.to);\n query.to = new Date(y, m - 1, d + 1).toISOString();\n }\n\n const q = f.q.trim();\n if (q !== \"\") query.q = q;\n\n if (opts.paged) {\n query.limit = String(opts.limit ?? HISTORY_PAGE_SIZE);\n if (f.offset > 0) query.offset = String(f.offset);\n }\n\n return query;\n}\n\n// ── cache keys (ship from here, never from a caller — mirrors `repos/dashboard.ts`) ──\n\n/**\n * Every key this domain reads or invalidates. `list`/`stats` carry the full\n * scope and filters object so two distinct filter sets never collide on the\n * same cache entry (and the identical pair always do) — react-query's own\n * structural key hashing does the rest.\n */\nexport const historyKeys = {\n root: [\"history\"] as const,\n list(scope: HistoryScope, f: HistoryFilters, limit: number): readonly unknown[] {\n return [\"history\", \"list\", scope, f, limit];\n },\n stats(scope: HistoryScope, f: HistoryFilters): readonly unknown[] {\n return [\"history\", \"stats\", scope, f];\n },\n exists(callableId: string): readonly [\"history\", \"exists\", string] {\n return [\"history\", \"exists\", callableId];\n },\n detail(kind: ExecutionKind, id: string): readonly [\"history\", \"detail\", ExecutionKind, string] {\n return [\"history\", \"detail\", kind, id];\n },\n};\n\n// ── fetchers ─────────────────────────────────────────────────────────────\n\n/** `GET /history` — paged. */\nexport function getHistory(\n client: W6WClient,\n scope: HistoryScope,\n f: HistoryFilters,\n limit: number = HISTORY_PAGE_SIZE,\n): Promise<{ executions: ExecutionSummary[]; hasMore: boolean }> {\n return client\n .request<{ executions: ExecutionSummary[]; hasMore: boolean }>({\n method: \"GET\",\n path: \"/history\",\n query: historyRequestQuery(scope, f, { paged: true, limit }),\n })\n .then((response) => response.body);\n}\n\n/** `GET /history/stats` — unpaged (no `limit`/`offset`). */\nexport function getHistoryStats(\n client: W6WClient,\n scope: HistoryScope,\n f: HistoryFilters,\n): Promise<ExecutionStats> {\n return client\n .request<{ stats: ExecutionStats }>({\n method: \"GET\",\n path: \"/history/stats\",\n query: historyRequestQuery(scope, f, { paged: false }),\n })\n .then((response) => response.body.stats);\n}\n\n/** One execution's full detail — the shape `ExecutionDetail` (`@w6w/ui`,\n * T2.2.2) renders. `steps` is present only for a workflow run; a\n * function/endpoint invocation has none. */\nexport interface ExecutionDetailData {\n id: string;\n kind: ExecutionKind;\n callableName: string;\n status: ExecutionStatus;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n /** The execution this one re-runs, carried from its summary row. */\n rerunOf?: string | null;\n steps?: Array<{\n id: string;\n status: \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n skipReason?: \"not_on_path\" | \"condition\" | \"stopped\" | \"disabled\";\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n node?: StepNode;\n }>;\n}\n\n/** What a workflow step IS (`@w6w/ui`'s `ExecutionLogNode`, restated locally — A1): the app and\n * action it uses, whether it is a trigger, and the app's display names when it is a registered app.\n * A built-in `@w6w/*` node carries ids only; the panel names those from its own catalog. */\nexport interface StepNode {\n app: string;\n action: string;\n trigger?: boolean;\n appName?: string;\n actionName?: string;\n}\n\n/** The slice of a definition node this module reads. */\ninterface DefinitionNode {\n id?: unknown;\n uses?: { app?: unknown; action?: unknown; trigger?: unknown };\n}\n\n/**\n * Every node of the workflow's CURRENT definition, keyed by id, as a {@link StepNode} — with the\n * display names of each registered app (`GET /apps/:id`'s `displayName` and action titles, plus\n * `GET /apps/:id/triggers` for an app a trigger node uses). Best-effort throughout: a definition\n * that cannot be read yields an empty map, and an app that cannot be read keeps its raw ids.\n */\nexport async function describeWorkflowNodes(\n client: W6WClient,\n workflowId: string,\n): Promise<Map<string, StepNode>> {\n const out = new Map<string, StepNode>();\n let nodes: DefinitionNode[];\n try {\n const { workflow } = await client.console.workflows.get(workflowId);\n nodes = Array.isArray(workflow.nodes) ? (workflow.nodes as DefinitionNode[]) : [];\n } catch {\n return out;\n }\n for (const n of nodes) {\n const app = n.uses?.app;\n const action = n.uses?.action;\n if (typeof n.id !== \"string\" || typeof app !== \"string\" || typeof action !== \"string\") continue;\n out.set(n.id, { app, action, ...(n.uses?.trigger === true ? { trigger: true } : {}) });\n }\n\n // Built-in `@w6w/*` ids are not served by `/apps/:id`; the panel names those itself.\n const registered = [...new Set([...out.values()].map((n) => n.app))].filter(\n (app) => !app.startsWith(\"@w6w/\"),\n );\n const names = await Promise.all(\n registered.map(async (app) => {\n const wantsTriggers = [...out.values()].some((n) => n.app === app && n.trigger);\n const [detail, triggers] = await Promise.all([\n client.console.apps.get(app).catch(() => null),\n wantsTriggers ? client.console.apps.getTriggers(app).catch(() => []) : Promise.resolve([]),\n ]);\n const titles = new Map<string, string>();\n for (const a of detail?.actions ?? []) titles.set(`a:${a.key}`, a.title);\n for (const t of triggers) titles.set(`t:${t.key}`, t.title);\n return { app, displayName: detail?.app.displayName, titles };\n }),\n );\n for (const node of out.values()) {\n const named = names.find((n) => n.app === node.app);\n if (!named) continue;\n if (named.displayName) node.appName = named.displayName;\n const title = named.titles.get(`${node.trigger ? \"t\" : \"a\"}:${node.action}`);\n if (title) node.actionName = title;\n }\n return out;\n}\n\n/** The `GET /invocations/:id` response body's shape this module reads\n * (context notes: server `db/repos/invocations.ts` `InvocationRow`). */\ninterface InvocationDetailBody {\n status: ExecutionStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n durationMs: number | null;\n startedAt: string;\n finishedAt: string | null;\n}\n\n/**\n * Expand a list row into its full detail. Function/Endpoint invocations are\n * synchronous calls recorded one row per call (`.claude/docs/invocations.md`)\n * — `GET /invocations/:id` by the escape-hatch `client.request` (no typed SDK\n * method exists for this internal route, same reasoning as\n * `repos/callables.ts`'s `archiveCallable`/`deleteCallable` split; A1: no\n * other runtime import needed). A workflow run instead reuses\n * `client.console.workflows.getRun` (`repos/workflows.ts`'s own\n * `getRunState`) — its `variables` become the detail's `input`, and its\n * opaque `steps` map through the SAME `mapRunStateToLogSteps` the live-run\n * overlay uses, so a historical run's step list renders identically to a\n * live one. `callableName` always comes from the summary — neither read\n * carries a human-readable callable name of its own.\n */\nexport async function getExecutionDetail(\n client: W6WClient,\n summary: ExecutionSummary,\n): Promise<ExecutionDetailData> {\n if (summary.kind === \"workflow\") {\n const [run, described] = await Promise.all([\n client.console.workflows.getRun(summary.id),\n describeWorkflowNodes(client, summary.callableId),\n ]);\n // What STARTED the run: the start payload (`input`), else the trigger's delivered `event` —\n // both ride `GET /runs/:id` beside the SDK's typed fields — else, for a run that had\n // neither, its variables.\n const started = run as unknown as { input?: unknown; event?: unknown };\n return {\n id: summary.id,\n kind: \"workflow\",\n callableName: summary.callableName,\n status: run.status,\n startedAt: summary.startedAt,\n finishedAt: summary.finishedAt,\n durationMs: summary.durationMs,\n input: started.input ?? started.event ?? run.variables,\n output: run.output,\n error: run.error,\n rerunOf: summary.rerunOf ?? null,\n steps: mapRunStateToLogSteps(runNodeMap(run)).map((step) => {\n const node = described.get(step.id);\n return node ? { ...step, node } : step;\n }),\n };\n }\n\n const response = await client.request<{ invocation: InvocationDetailBody }>({\n method: \"GET\",\n path: `/invocations/${encodeURIComponent(summary.id)}`,\n });\n const invocation = response.body.invocation;\n return {\n id: summary.id,\n kind: summary.kind,\n callableName: summary.callableName,\n status: invocation.status,\n startedAt: invocation.startedAt,\n finishedAt: invocation.finishedAt,\n durationMs: invocation.durationMs,\n input: invocation.input,\n output: invocation.output,\n error: invocation.error,\n rerunOf: summary.rerunOf ?? null,\n };\n}\n\n// ── re-run ───────────────────────────────────────────────────────────────\n\n/** The invocation id a FAILED invoke still minted: the server stamps its frame\n * onto the error body (`withInvocationFrame`), and `@w6w/sdk`'s `ApiError`\n * keeps that body as `raw`. Duck-typed so this module stays SDK-runtime-free. */\nfunction invocationIdOf(err: unknown): string | undefined {\n const raw = (err as { raw?: unknown } | null)?.raw;\n const id = (raw as { invocationId?: unknown } | null)?.invocationId;\n return typeof id === \"string\" ? id : undefined;\n}\n\n/** A plain object, or `{}` — a stored input that is not an object (or is\n * absent) cannot be an invoke body. */\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\n/** Start the new execution and return its id: the run id for a workflow (once\n * the run is terminal), the invocation id for a function/endpoint — also when\n * the call itself failed, since a failed call is still a recorded execution. */\nasync function startRerun(\n client: W6WClient,\n summary: ExecutionSummary,\n sleep?: (ms: number) => Promise<void>,\n): Promise<string> {\n const callable = encodeURIComponent(summary.callableId);\n\n if (summary.kind === \"workflow\") {\n // The SERVER replays the stored seed — trigger type, variables, start input, the trigger's\n // delivered `event`, entry node, partial-run spec. A client-side replay through\n // `POST /workflows/:id/run` cannot: that route has no slot for `event`, which is where an app\n // or webhook trigger's payload lives.\n const res = await client.request<{ runId: string }>({\n method: \"POST\",\n path: `/runs/${encodeURIComponent(summary.id)}/rerun`,\n body: { allowUnpublished: true },\n });\n const runId = res.body.runId;\n await pollRunToTerminal(() => client.console.workflows.getRun(runId), sleep);\n return runId;\n }\n\n const past = await client.request<{ invocation: InvocationDetailBody }>({\n method: \"GET\",\n path: `/invocations/${encodeURIComponent(summary.id)}`,\n });\n const input = asRecord(past.body.invocation.input);\n // `rerunOf` marks the new invocation as a re-run of this one (`invocations.rerun_of`).\n const body: Record<string, unknown> =\n summary.kind === \"function\"\n ? { inputs: input, allowUnpublished: true, rerunOf: summary.id }\n : { input, allowUnpublished: true, rerunOf: summary.id };\n try {\n const res = await client.request<{ invocationId?: string }>({\n method: \"POST\",\n path: `/${summary.kind === \"function\" ? \"functions\" : \"endpoints\"}/${callable}/invoke`,\n body,\n });\n const id = res.body.invocationId;\n if (typeof id !== \"string\") throw new Error(\"The server did not return an invocation id.\");\n return id;\n } catch (err) {\n const id = invocationIdOf(err);\n if (id === undefined) throw err;\n return id;\n }\n}\n\n/**\n * Run a past execution again with the input it had, against the callable's\n * CURRENT definition (the stored draft — `allowUnpublished`, as the editor's\n * own Run and Test do), and return the new execution's summary row so the\n * host can open it. A workflow is replayed by the server from its stored seed\n * (`POST /runs/:id/rerun`, trigger payload included); a function replays its\n * `inputs`; an endpoint its `input`. `null` when the new row is not yet listed (the host then just\n * shows the refreshed list).\n */\nexport async function rerunExecution(\n client: W6WClient,\n summary: ExecutionSummary,\n opts: { sleep?: (ms: number) => Promise<void> } = {},\n): Promise<ExecutionSummary | null> {\n const id = await startRerun(client, summary, opts.sleep);\n return findExecution(client, summary.callableId, id);\n}\n\n/** One callable's execution by id, as its summary row (`GET /history`'s id search), or `null`\n * when it is not listed — e.g. the original a re-run names, once retention removed it. */\nexport async function findExecution(\n client: W6WClient,\n callableId: string,\n id: string,\n): Promise<ExecutionSummary | null> {\n const found = await getHistory(\n client,\n { callable: callableId },\n { ...EMPTY_HISTORY_FILTERS, q: id },\n 1,\n );\n return found.executions.find((row) => row.id === id) ?? null;\n}\n","import {\n type UseMutationResult,\n useMutation,\n useQuery,\n useQueryClient,\n} from \"@tanstack/react-query\";\nimport type { StateLogRow } from \"@w6w/expr\";\nimport { path } from \"@w6w/sdk\";\nimport type { RunStatus, W6WClient, WorkflowRunResult } from \"@w6w/sdk\";\nimport type { RunState } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport { historyKeys } from \"../lib/history-query.ts\";\nimport { shouldContinuePolling } from \"../lib/workflow-live-run.ts\";\nimport { pollRunToTerminal } from \"../lib/workflow-poll.ts\";\n\nexport type { RunState, RunSummary } from \"@w6w/sdk/console\";\nexport type { WorkflowStatus, WorkflowSummary } from \"@w6w/sdk\";\n\n// `project` distinguishes a project-scoped entry (WorkflowsPage.tsx) from the\n// unscoped one (TargetSelector.tsx, SubscriptionsPage.tsx) — genuinely DIFFERENT\n// queries (not a spelling split to unify like T2.2.2's appActions fix). Keep them\n// as distinct cache entries.\nexport const workflowsKey = (project?: string) => [\"workflows\", project] as const;\n\nexport function listWorkflows(client: W6WClient, project?: string) {\n return client.workflows.list({ project });\n}\n\nexport function useWorkflowsQuery(project?: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: workflowsKey(project),\n queryFn: () => listWorkflows(apiClient, project),\n enabled,\n });\n}\n\nexport const workflowKey = (id: string) => [\"workflow\", id] as const;\n\nexport function getWorkflow(client: W6WClient, id: string) {\n return client.workflows.get(id);\n}\n\nexport function useWorkflowQuery(id: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: workflowKey(id),\n queryFn: () => getWorkflow(apiClient, id),\n enabled,\n });\n}\n\n/**\n * A missing `project` here is not \"unscoped\" the way a read can legitimately\n * be — the write would silently land in the account's default project\n * instead of the one the caller is looking at. Both mutations refuse rather\n * than risk that; `WorkflowsPage.tsx`'s own `projectId != null` gate on\n * `useWorkflowsQuery` should mean `project` is always set by the time either\n * of these can actually be invoked from the UI, but the guard costs nothing.\n */\nexport function useCreateWorkflowMutation(project?: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (definition: unknown) => {\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return apiClient.console.workflows.upsert(definition, { project });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useSaveWorkflowMutation(project?: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { definition: unknown; ifUnmodifiedSince: string | null }) => {\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return apiClient.console.workflows.upsert(vars.definition, {\n project,\n ifUnmodifiedSince: vars.ifUnmodifiedSince,\n });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useArchiveWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.workflows.archive(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useDeleteWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.workflows.delete(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport const runsKey = (workflowId: string) => [\"runs\", workflowId] as const;\n\nexport function useRunsQuery(workflowId: string) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: runsKey(workflowId),\n queryFn: () => apiClient.console.workflows.listRuns(workflowId),\n });\n}\n\n/**\n * Start a run and poll it to a terminal state.\n *\n * `input` is the run's START PAYLOAD, and it is a different thing from\n * `variables`: the server hands it to the entry `@w6w/trigger` node as that\n * node's own output, which is what makes `{{ steps.<trigger>.output.<field> }}`\n * resolve in a real run. Omitted, that node outputs `{}` and every reference to\n * a trigger field resolves to the empty string — the failure mode filed as\n * `.ai/projects/backlog/26-07-29-01-trigger-run-payload.md`, where a step tests\n * green and then does nothing in production. `variables` seeds `var.*` and\n * reaches the trigger node not at all.\n *\n * Goes through the typed `client.workflows.run()` with\n * `allowUnpublished: true`: this call site always runs the STORED draft, and\n * the server exempts a caller that sets the flag from the publish gate\n * (`packages/api/run-workflow.ts`'s `enqueueRun`). The SDK's result is the flat\n * run body, so the `runId` used to poll comes off `res.runId`.\n */\nexport function runWorkflow(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n): Promise<RunState> {\n return client.workflows\n .run(id, { variables, input, allowUnpublished: true })\n .then((res) => pollRunToTerminal(() => client.console.workflows.getRun(res.runId)));\n}\n\nexport function useRunWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n variables: Record<string, unknown>;\n input?: Record<string, unknown>;\n }) => runWorkflow(apiClient, vars.id, vars.variables, vars.input),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\n/**\n * Run a Workflow SYNCHRONOUSLY — the `W6WApi.runWorkflow` facade member's\n * backing function (the Workflows tab's Test stage, D-11/D-15(c)). A sibling\n * of {@link runWorkflow}, NOT a replacement: that function's enqueue-then-poll\n * shape is the studio-wide \"Run this workflow\" action and stays exactly as it\n * is. This one instead sends `wait: true` on the SAME base `client.workflows\n * .run` call already published (`?wait=true` — the server polls internally,\n * up to its own timeout) — zero new server code, and no second poll loop:\n * there is no `pollRunToTerminal` here at all. `terminal`/`httpStatus` on the\n * result distinguish \"finished in time\" (`200`) from \"still going when the\n * server's own wait timed out\" (`202`, a legitimate outcome, not an error).\n */\nexport function runWorkflowSync(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n): Promise<WorkflowRunResult> {\n return client.workflows.run(id, { variables, input, wait: true });\n}\n\n/**\n * T2.1.1 — the ENQUEUE half only: starts a run and returns its handle\n * immediately, without polling it to terminal. A genuine sibling of\n * {@link runWorkflow}, NOT a replacement — that function's \"enqueue, then\n * block to a terminal result\" shape is what `WorkflowDetailPage.tsx`'s \"Run\n * now\" panel is built on and stays exactly as it is. This one is for a host\n * that wants the `runId` right away so it can poll it live itself (the\n * visual editor's canvas + execution log panel) — see {@link useLiveRunQuery}.\n *\n * Like {@link runWorkflow}, this calls `client.workflows.run()` with\n * `allowUnpublished: true` unconditionally. Only `{ runId }` is returned, so\n * callers keep reading `runId` off the resolved value exactly as before.\n */\nexport function startWorkflowRun(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n) {\n return client.workflows\n .run(id, { variables, input, allowUnpublished: true })\n .then((res) => ({ runId: res.runId }));\n}\n\n/** What {@link startRunFromNode} sends: the paused nodes to stop before, and the start seed. */\nexport interface RunFromNodeBody {\n /** Node ids the run stops BEFORE (they do not execute) — the editor's paused nodes. */\n stopAt: string[];\n /** Upstream outputs keyed by node id, seeded from saved step tests / the last run. */\n nodes?: Record<string, { output?: unknown; meta?: unknown }>;\n /** The trigger's filled values, when the run starts at a trigger node. */\n input?: Record<string, unknown>;\n}\n\n/**\n * Run from a node — `POST /workflows/:id/nodes/:nodeId/run` with `continue: true`: a REAL run\n * that executes `nodeId`, continues through every node downstream of it the way a run follows\n * its edges, and stops before each `stopAt` node. Answers `202 { runId }` at once, like\n * {@link startWorkflowRun}, so the caller polls it live ({@link useLiveRunQuery}). The run\n * executes the STORED definition, so a caller flushes its draft first.\n *\n * The plain `client.request()` escape hatch, not a typed `@w6w/sdk` method: the route is a\n * console authoring aid, and a typed method would pull `packages/wrappers` (every language, in\n * lockstep) into an editor-only change.\n */\nexport async function startRunFromNode(\n client: W6WClient,\n id: string,\n nodeId: string,\n body: RunFromNodeBody,\n): Promise<{ runId: string }> {\n const res = await client.request<{ runId: string }>({\n method: \"POST\",\n path: path`/workflows/${id}/nodes/${nodeId}/run`,\n body: {\n continue: true,\n stopAt: body.stopAt,\n ...(body.nodes ? { state: { nodes: body.nodes } } : {}),\n ...(body.input ? { input: body.input } : {}),\n },\n });\n return { runId: res.body.runId };\n}\n\n/** A node output's structural shape, as the server records it (structural mirror of `@w6w/ui`'s). */\nexport type NodeSampleShape =\n | { type: \"string\" | \"number\" | \"boolean\" | \"null\" | \"unknown\" }\n | { type: \"object\"; fields: Record<string, NodeSampleShape> }\n | { type: \"array\"; items?: NodeSampleShape };\n\n/**\n * One persisted node sample — structural mirror of `@w6w/ui`'s `NodeSample` (this barrel may not\n * import `@w6w/ui`; the facade/UiBridge assignment typechecks against `W6WApi` structurally).\n */\nexport interface NodeSample {\n nodeId: string;\n shape: NodeSampleShape;\n sample?: unknown;\n sampleOmitted?: true;\n source: \"step_test\" | \"node_run\" | \"run\";\n runId?: string;\n updatedAt: string;\n}\n\n/**\n * The workflow's persisted node samples — `GET /workflows/:id/node-samples` → `{ nodeSamples }`:\n * each node's last output shape (and value, when kept), written server-side on every Test, node\n * run and run. Backs `W6WApi.loadNodeSamples`, so the editor's picker keeps upstream keys across a\n * reload. The plain `client.request()` escape hatch, for the same reason as {@link startRunFromNode}.\n */\nexport function listNodeSamples(client: W6WClient, id: string): Promise<NodeSample[]> {\n return client\n .request<{ nodeSamples?: NodeSample[] }>({\n method: \"GET\",\n path: path`/workflows/${id}/node-samples`,\n })\n .then((res) => res.body.nodeSamples ?? []);\n}\n\n/** One remembered node test input — structural mirror of `@w6w/ui`'s `NodeTestInput`. */\nexport interface NodeTestInput {\n nodeId: string;\n input: Record<string, unknown>;\n updatedAt: string;\n}\n\n/**\n * The test input each node of the workflow last ran with in the editor —\n * `GET /workflows/:id/test-inputs` → `{ testInputs }` (`node_test_inputs`, 0160). Backs\n * `W6WApi.loadTestInputs`, so the Run node modal, the Test tabs and the header Run reopen\n * prefilled. The plain `client.request()` escape hatch, for the same reason as {@link startRunFromNode}.\n */\nexport function listTestInputs(client: W6WClient, id: string): Promise<NodeTestInput[]> {\n return client\n .request<{ testInputs?: NodeTestInput[] }>({\n method: \"GET\",\n path: path`/workflows/${id}/test-inputs`,\n })\n .then((res) => res.body.testInputs ?? []);\n}\n\n/**\n * Remember a node's test input (`{}` clears it) — `PUT /workflows/:id/nodes/:nodeId/test-input`.\n * Backs `W6WApi.saveTestInput`; the server drops sealed envelopes before the write.\n */\nexport function saveTestInput(\n client: W6WClient,\n id: string,\n nodeId: string,\n input: Record<string, unknown>,\n): Promise<void> {\n return client\n .request<{ ok: boolean }>({\n method: \"PUT\",\n path: path`/workflows/${id}/nodes/${nodeId}/test-input`,\n body: { input },\n })\n .then(() => undefined);\n}\n\nexport function useRunFromNodeMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; nodeId: string; body: RunFromNodeBody }) =>\n startRunFromNode(apiClient, vars.id, vars.nodeId, vars.body),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\nexport function useStartRunMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n variables: Record<string, unknown>;\n input?: Record<string, unknown>;\n }) => startWorkflowRun(apiClient, vars.id, vars.variables, vars.input),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\n/** What `client.workflows.cancel` resolves to. Named here because the SDK's root entry does not\n * export its `WorkflowCancelResult`: an inferred return type would name it and `vite-plugin-dts`\n * would skip this whole file (TS2742), leaving every `./repos` declaration out of the tarball. */\nexport type WorkflowCancelResult = Awaited<ReturnType<W6WClient[\"workflows\"][\"cancel\"]>>;\n\n/**\n * T2.1.1/A6 — cancel a queued or running run. `client.workflows.cancel`\n * itself never claims the run has stopped (its own doc comment: a `202`\n * means the request was RECORDED, not that the run finished) — the caller\n * keeps polling {@link useLiveRunQuery} until the run actually reaches a\n * terminal status. See `../lib/workflow-live-run.ts`'s `classifyCancelError`\n * for how a `409 run_not_cancelable` (the run beat the cancel to the finish\n * line) is told apart from a real failure.\n */\nexport function cancelWorkflowRun(client: W6WClient, runId: string): Promise<WorkflowCancelResult> {\n return client.workflows.cancel(runId);\n}\n\nexport function useCancelRunMutation(): UseMutationResult<WorkflowCancelResult, Error, string> {\n const apiClient = useEmbedClient();\n return useMutation({\n mutationFn: (runId: string) => cancelWorkflowRun(apiClient, runId),\n });\n}\n\n/** The single-shot half of {@link useLiveRunQuery} — a thin, directly\n * testable wrapper around `client.console.workflows.getRun`, so the polling\n * config below can be pinned without needing to render a hook. */\nexport function getRunState(client: W6WClient, runId: string): Promise<RunState> {\n return client.console.workflows.getRun(runId);\n}\n\n/** Query key for one run's live state — distinct from {@link runsKey}, which\n * is the workflow's run LIST. */\nexport const runStateKey = (runId: string) => [\"run\", runId] as const;\n\n/**\n * T2.1.1/A2/A3 — poll one run's live state at a fixed 500ms interval,\n * stopping once it reaches a terminal status ({@link shouldContinuePolling},\n * `../lib/workflow-live-run.ts`). A genuine sibling of `pollRunToTerminal`\n * (`../lib/workflow-poll.ts`) using the SAME underlying SDK call\n * (`client.console.workflows.getRun`), but publishing every intermediate\n * `RunState` to its caller via TanStack Query's own `data` — unlike\n * `pollRunToTerminal`, which discards every non-terminal result and hands\n * back only the last one. `runId === null` disables the query entirely (no\n * run started yet, or the page navigated to a different workflow).\n */\nexport function useLiveRunQuery(runId: string | null) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: runStateKey(runId ?? \"\"),\n queryFn: () => getRunState(apiClient, runId as string),\n enabled: runId != null,\n refetchInterval: (query) => (shouldContinuePolling(query.state.data?.status) ? 500 : false),\n });\n}\n\n/** `GET /runs/:id/state-writes` — the run's state-write log (plan §2.4). */\nexport interface RunStateWrites {\n writes: StateLogRow[];\n truncated: boolean;\n}\n\n/**\n * One run's state-write log, read for the run log's State block (\"state after this\n * step\"). The plain `client.request()` escape hatch, for the same reason as\n * {@link listNodeSamples}: the route has no typed `@w6w/sdk` method.\n */\nexport function getRunStateWrites(client: W6WClient, runId: string): Promise<RunStateWrites> {\n return client\n .request<{ writes?: StateLogRow[]; truncated?: boolean }>({\n method: \"GET\",\n path: path`/runs/${runId}/state-writes`,\n })\n .then((res) => ({ writes: res.body.writes ?? [], truncated: res.body.truncated === true }));\n}\n\n/** Query key for one run's state-write log. The last segment flips from `\"live\"` to\n * `\"final\"` when the run turns terminal, so the final log is fetched exactly once more. */\nexport function runStateWritesKey(runId: string, status: RunStatus | undefined) {\n return [\"run\", runId, \"state-writes\", shouldContinuePolling(status) ? \"live\" : \"final\"] as const;\n}\n\n/**\n * Poll one run's state-write log beside {@link useLiveRunQuery}: the same 500ms cadence\n * while the run (as `status`, the live run query's answer) is in flight, no polling once\n * terminal. `retry: false` — a failed read only leaves the run log without its State\n * block; it never touches the run poll.\n */\nexport function useRunStateWritesQuery(runId: string | null, status: RunStatus | undefined) {\n const apiClient = useEmbedClient();\n const live = shouldContinuePolling(status);\n return useQuery({\n queryKey: runStateWritesKey(runId ?? \"\", status),\n queryFn: () => getRunStateWrites(apiClient, runId as string),\n enabled: runId != null,\n refetchInterval: live ? 500 : false,\n retry: false,\n });\n}\n"],"names":["runNodeMap","run","STEP_FAILED_NO_REASON","RUN_FAILED_NO_REASON","shouldContinuePolling","status","isTerminalRunStatus","isRunInFlight","pollFailed","STEP_PASS_REFRESH_DELAYS_MS","stepPassRefreshDue","runWorkflowId","workflowId","runButtonLabel","classifyCancelError","code","mapRunStateToLogSteps","steps","stateLog","state","stateFieldsByNode","id","step","mapStep","iterationFields","log","rows","a","b","byNode","row","entry","group","out","writes","lastSeq","foldStateLog","SKIP_REASONS","line","rowError","ITERATION_STATUSES","iterations","it","nodes","s","failedNodeId","_a","finite","n","error","toLogError","raw","o","message","safeJson","runLevelErrors","carried","r","reasoned","stepErrors","e","own","sameAsOwn","runError","latestFixtureInput","tests","last","resolveHeaderRunInput","triggerStepId","list","remembered","input","headerRunEntry","isManualTrigger","isEntryTrigger","manual","other","TERMINAL","realSleep","ms","resolve","pollRunToTerminal","getRun","sleep","i","EMPTY_HISTORY_FILTERS","HISTORY_PAGE_SIZE","VALID_STATUSES","VALID_KINDS","DATE_RE","isRealDate","y","m","d","dateParts","dt","value","filtersFromSearch","search","params","kind","from","to","q","offsetRaw","offset","filtersToSearch","f","historyRequestQuery","scope","opts","query","historyKeys","limit","callableId","getHistory","client","response","getHistoryStats","describeWorkflowNodes","workflow","app","action","_b","_c","registered","names","wantsTriggers","detail","triggers","titles","t","node","named","title","getExecutionDetail","summary","described","started","invocation","invocationIdOf","err","asRecord","startRerun","callable","runId","past","body","rerunExecution","findExecution","workflowsKey","project","listWorkflows","useWorkflowsQuery","enabled","apiClient","useEmbedClient","useQuery","workflowKey","getWorkflow","useWorkflowQuery","useCreateWorkflowMutation","qc","useQueryClient","useMutation","definition","useSaveWorkflowMutation","vars","useArchiveWorkflowMutation","useDeleteWorkflowMutation","runsKey","useRunsQuery","runWorkflow","variables","res","useRunWorkflowMutation","_res","runWorkflowSync","startWorkflowRun","startRunFromNode","nodeId","path","listNodeSamples","listTestInputs","saveTestInput","useRunFromNodeMutation","useStartRunMutation","cancelWorkflowRun","useCancelRunMutation","getRunState","runStateKey","useLiveRunQuery","getRunStateWrites","runStateWritesKey","useRunStateWritesQuery","live"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflows-BK6IM4if.js","sources":["../src/lib/workflow-live-run.ts","../src/lib/workflow-poll.ts","../src/lib/history-query.ts","../src/repos/workflows.ts"],"sourcesContent":["/**\n * Pure decision layer for the visual editor's live Run/Stop feature (T2.1.1,\n * A7). Every judgment call this feature makes that is NOT layout — is a run\n * in flight? should polling continue? is the canvas editable right now? what\n * should the Run button say and is it disabled? how does a cancel failure\n * get handled? how does a `RunState`'s steps map to the execution log\n * panel's rows, and what error does each row and the run show? what `input`\n * does the header Run send? — lives here as plain functions of (run state) -> result,\n * with no `.tsx` import and no React import, so `node --test` can load this\n * module directly. Same mechanical reason `workflow-poll.ts` and\n * `repos/reliability-uptime.ts` exist as separate `.ts` modules — read\n * `workflow-poll.ts`'s own header. `WorkflowsPage.tsx` calls these functions\n * rather than restating the conditions inline.\n */\nimport { type StateLogRow, foldStateLog } from \"@w6w/expr\";\nimport { type RunStatus, isTerminalRunStatus } from \"@w6w/sdk\";\n\nexport type { RunStatus };\n\n/**\n * The five states a workflow step's execution can be in — a thin LOCAL copy\n * of `@w6w/ui`'s `StepStatus` (itself a thin local copy of the engine's\n * `StepStatus` — see `run-visuals.ts`'s own header in `packages/ui`, the\n * same house idiom). `@w6w/sdk/console`'s `RunState.steps` is deliberately\n * typed `Record<string, unknown>` — opaque pass-through, by that module's\n * own documented design — so the real per-step shape has to be re-stated\n * here rather than imported.\n */\nexport type StepStatus = \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n\n/** The per-step metadata (which app/version/action/connection ran) — one\n * local structural copy of the pinned `StepMeta`. A `type` alias, not an\n * `interface`, so it stays assignable to index-signature types. */\nexport type StepMetaLike = {\n app: string;\n version: string;\n action: string;\n connectionId: string | null;\n};\n\n/** The slice of a `StepExecution` this module reads, to build one\n * `ExecutionLogPanel` row. */\nexport interface StepExecutionLike {\n status: StepStatus;\n /** Why a `skipped` step did not run (`NodeExecution.skipReason`); read as `unknown` (opaque\n * wire) and carried only when it is one of the four known reasons. */\n skipReason?: unknown;\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n logs?: string[];\n /** `StepExecution.error` — a `StepError` on `failed` per rfcs/workflow.md\n * §StepExecution, but read as `unknown` because `RunState.steps` is opaque\n * on the wire; {@link toLogError} normalises whatever actually arrives. */\n error?: unknown;\n /** Recorded metadata; absent (or null) for steps that recorded none. */\n meta?: StepMetaLike | null;\n /** For each only (I3): per-iteration body records, read as `unknown` (opaque wire). */\n iterations?: unknown;\n iterationsTotal?: unknown;\n iterationsFailed?: unknown;\n iterationsTruncated?: unknown;\n}\n\n/** A step or run error, as the run log panel renders it — field-for-field\n * `@w6w/ui`'s `ExecutionLogError` (rfcs/workflow.md §StepError's\n * `code`/`message`/`phase`/`retryable`), restated locally for the same reason\n * as {@link ExecutionLogStepLike} below. `message` is never empty. */\nexport interface LogErrorLike {\n code?: string;\n message: string;\n phase?: string;\n retryable?: boolean;\n}\n\n/** One `RunState.stepErrors` entry the panel shows at run level — field-for-field\n * `@w6w/ui`'s `ExecutionLogRecordedError`, restated locally (see above). */\nexport interface RecordedLogErrorLike {\n stepId: string;\n label?: string;\n error: LogErrorLike;\n}\n\n/** The slice of a `RunState` {@link runLevelErrors} reads. */\nexport interface RunErrorSourceLike {\n status?: string;\n error?: unknown;\n stepErrors?: ReadonlyArray<{ nodeId?: string; stepId?: string; error: unknown }>;\n}\n\n/** The per-node execution map of a run record, in either shape — `nodes`\n * preferred, else the legacy `steps`. */\nexport function runNodeMap(\n run: { nodes?: unknown; steps?: unknown } | undefined | null,\n): Record<string, StepExecutionLike> | undefined {\n return (run?.nodes ?? run?.steps ?? undefined) as Record<string, StepExecutionLike> | undefined;\n}\n\n/** The slice of a saved step-test fixture (`StepTest`) {@link latestFixtureInput}\n * reads — `with` is what the trigger's Test tab invokes it with. */\nexport interface StepTestFixtureLike {\n with?: unknown;\n}\n\n/** The row-level fallback for a `failed` step that carries no `error` at all. */\nexport const STEP_FAILED_NO_REASON = \"Node failed without reporting a reason.\";\n\n/** The run-level fallback for a `failed` run where nothing carries a reason. */\nexport const RUN_FAILED_NO_REASON = \"Run failed without reporting a reason.\";\n\n/** One `ExecutionLogPanel` row — field-for-field `@w6w/ui`'s\n * `ExecutionLogStep`, restated locally for the same reason as\n * {@link StepExecutionLike} above (no runtime dependency on `@w6w/ui`,\n * which this module must not import — see the file header). */\nexport interface ExecutionLogStepLike {\n id: string;\n status: StepStatus;\n skipReason?: SkipReasonLike;\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n logs?: string[];\n error?: LogErrorLike;\n meta?: StepMetaLike;\n /** For each only (I4) — field-for-field `@w6w/ui`'s `ExecutionLogStep`. */\n iterations?: ExecutionLogIterationLike[];\n iterationsTotal?: number;\n iterationsFailed?: number;\n iterationsTruncated?: boolean;\n /** This node's state writes (`GET /runs/:id/state-writes` rows, in `seq` order) —\n * field-for-field `@w6w/ui`'s `ExecutionLogStep.stateWrites` (plan §2.7). Absent → no State block. */\n stateWrites?: StateWriteEntryLike[] | null;\n /** The state tree right after this node's last write (`foldStateLog`). */\n stateAfter?: Record<string, unknown> | null;\n}\n\n/** One state-write entry on a run-log row — `@w6w/ui`'s `ExecutionLogStep.stateWrites[number]`. */\nexport type StateWriteEntryLike = {\n path: string[];\n item?: number;\n old?: unknown;\n new?: unknown;\n warning?: string;\n};\n\n/** One For each iteration row (I4) — mirrors `@w6w/ui`'s `ExecutionLogIteration`. */\nexport interface ExecutionLogIterationLike {\n index: number;\n status: \"succeeded\" | \"failed\" | \"running\";\n failedNodeId?: string;\n steps: ExecutionLogStepLike[];\n}\n\n/** How a cancel-request failure should be handled (A6). */\nexport type CancelErrorOutcome = \"reconcile\" | \"surface\";\n\n/**\n * A2/M1 — the `refetchInterval` decision: keep polling (`true`) until the\n * run's status is terminal (`false`), including while no run has answered\n * yet (`status === undefined` — the very first poll hasn't landed, or no run\n * is active at all).\n */\nexport function shouldContinuePolling(status: RunStatus | undefined): boolean {\n return status === undefined || !isTerminalRunStatus(status);\n}\n\n/**\n * A4/M2/M3 — is a run currently \"in flight\" from this page's point of view?\n * `true` only while the poll has a live, non-terminal status AND the poll\n * itself hasn't given up/errored — a failed poll unlocks the canvas exactly\n * like reaching a real terminal status does (A4's own named failure case: \"a\n * canvas that stays locked after a cancel\"). Drives the canvas's `readOnly`\n * prop, the Stop button's visibility, and the Run button's disabled state —\n * one function, three call sites, so they can never drift out of sync with\n * each other.\n */\nexport function isRunInFlight(status: RunStatus | undefined, pollFailed: boolean): boolean {\n if (pollFailed) return false;\n if (status === undefined) return false;\n return !isTerminalRunStatus(status);\n}\n\n/**\n * When a run turns terminal, how long after (ms) the editor re-reads the workflow's saved step\n * tests. The server books every step that succeeded in an editor run as its passing saved test\n * (`step-passes.ts`) — the record the publish gate reads — but only AFTER the engine has\n * checkpointed the run's terminal state, so the poll can see `succeeded` a few milliseconds before\n * the pass lands. The immediate read covers the usual case; the later one covers that window.\n */\nexport const STEP_PASS_REFRESH_DELAYS_MS: readonly number[] = [0, 1500];\n\n/**\n * Should the editor re-read this workflow's saved step tests now? Only once the run it polls is\n * terminal and belongs to the open workflow — a run's passes are booked as it finishes, and the\n * step-tests cache never refetches on its own (`refetchOnWindowFocus: false`), so without this\n * the publish gate keeps the pre-run list and a step that just passed still blocks Publish.\n */\nexport function stepPassRefreshDue(\n status: RunStatus | undefined,\n runWorkflowId: string | undefined,\n workflowId: string,\n): boolean {\n return status !== undefined && isTerminalRunStatus(status) && runWorkflowId === workflowId;\n}\n\n/** A1/A6 — what the Run button should read right now. */\nexport function runButtonLabel(status: RunStatus | undefined, pollFailed: boolean): string {\n if (!isRunInFlight(status, pollFailed)) return \"Run\";\n return status === \"queued\" ? \"Queued…\" : \"Running…\";\n}\n\n/**\n * A6/M6 — classify a `cancel()` failure. `run_not_cancelable` (409) means\n * the run already reached a terminal state before the cancel request landed\n * — not a user-facing error, just reconcile to whatever the next poll\n * reports. Everything else (`unknown_run`, a network failure, …) is a real\n * failure the page's existing error affordance must show.\n */\nexport function classifyCancelError(code: string): CancelErrorOutcome {\n return code === \"run_not_cancelable\" ? \"reconcile\" : \"surface\";\n}\n\n/**\n * G5 — map a `RunState`'s opaque `steps` record onto `ExecutionLogPanel`'s\n * row shape, preserving its keys and timestamps. Record key order is not\n * execution order; `ExecutionLogPanel` sorts the rows chronologically for\n * both live runs and saved history.\n */\nexport function mapRunStateToLogSteps(\n steps: Record<string, StepExecutionLike> | undefined,\n stateLog?: readonly StateLogRow[],\n): ExecutionLogStepLike[] {\n if (!steps) return [];\n const state = stateLog ? stateFieldsByNode(stateLog) : undefined;\n return Object.entries(steps).map(([id, step]) => ({\n ...mapStep(id, step),\n ...iterationFields(step),\n ...(state?.get(id) ?? {}),\n }));\n}\n\n/**\n * The run's state-write log (`GET /runs/:id/state-writes`) grouped by node, in `seq`\n * order whatever order the rows arrive in: each node's entries (only `path` plus the\n * `item`/`old`/`new`/`warning` a row has — never `seq`/`nodeId`/`step`) and the tree\n * right after its last row, folded by `@w6w/expr`'s `foldStateLog` (one fold for the\n * whole product, R18). Rows with a null `nodeId` (the base row) attach to no node but\n * still seed every fold.\n */\nfunction stateFieldsByNode(\n log: readonly StateLogRow[],\n): Map<string, Pick<ExecutionLogStepLike, \"stateWrites\" | \"stateAfter\">> {\n const rows = [...log].sort((a, b) => a.seq - b.seq);\n const byNode = new Map<string, { writes: StateWriteEntryLike[]; lastSeq: number }>();\n for (const row of rows) {\n if (row.nodeId === null || row.nodeId === undefined) continue;\n const entry: StateWriteEntryLike = { path: row.path };\n if (row.item !== undefined) entry.item = row.item;\n if (row.old !== undefined) entry.old = row.old;\n if (row.new !== undefined) entry.new = row.new;\n if (row.warning !== undefined) entry.warning = row.warning;\n const group = byNode.get(row.nodeId) ?? { writes: [], lastSeq: row.seq };\n group.writes.push(entry);\n group.lastSeq = row.seq;\n byNode.set(row.nodeId, group);\n }\n const out = new Map<string, Pick<ExecutionLogStepLike, \"stateWrites\" | \"stateAfter\">>();\n for (const [id, { writes, lastSeq }] of byNode) {\n out.set(id, { stateWrites: writes, stateAfter: foldStateLog(rows, lastSeq) });\n }\n return out;\n}\n\n/** `@w6w/ui`'s `SkipReason`, restated locally (see {@link ExecutionLogStepLike}). */\nexport type SkipReasonLike = \"not_on_path\" | \"condition\" | \"stopped\" | \"disabled\";\n\nconst SKIP_REASONS: ReadonlySet<unknown> = new Set([\n \"not_on_path\",\n \"condition\",\n \"stopped\",\n \"disabled\",\n]);\n\n/** One wire record -> one row (shared by top-level rows and iteration body steps). */\nfunction mapStep(id: string, step: StepExecutionLike): ExecutionLogStepLike {\n return {\n id,\n status: step.status,\n ...(step.status === \"skipped\" && SKIP_REASONS.has(step.skipReason)\n ? { skipReason: step.skipReason as SkipReasonLike }\n : {}),\n startedAt: step.startedAt,\n finishedAt: step.finishedAt,\n input: step.input,\n output: step.output,\n ...(Array.isArray(step.logs) && step.logs.length\n ? { logs: step.logs.filter((line): line is string => typeof line === \"string\") }\n : {}),\n ...(step.meta !== undefined && step.meta !== null ? { meta: step.meta } : {}),\n ...rowError(step),\n };\n}\n\nconst ITERATION_STATUSES: ReadonlySet<unknown> = new Set([\"succeeded\", \"failed\", \"running\"]);\n\n/** The I4 `iterations*` keys for a For each record (I3) — empty (no own keys) when\n * `iterations` is not an array. */\nfunction iterationFields(\n step: StepExecutionLike,\n): Pick<\n ExecutionLogStepLike,\n \"iterations\" | \"iterationsTotal\" | \"iterationsFailed\" | \"iterationsTruncated\"\n> {\n if (!step || !Array.isArray(step.iterations)) return {};\n const iterations = (step.iterations as Array<Record<string, unknown> | null>)\n .filter((it): it is Record<string, unknown> => it !== null && typeof it === \"object\")\n .map((it) => {\n const nodes =\n it.nodes !== null && typeof it.nodes === \"object\"\n ? (it.nodes as Record<string, StepExecutionLike>)\n : {};\n const steps = Object.entries(nodes).map(([id, s]) => mapStep(id, s));\n const failedNodeId =\n typeof it.failedNodeId === \"string\" && it.failedNodeId !== \"\"\n ? it.failedNodeId\n : steps.find((s) => s.status === \"failed\")?.id;\n const status = ITERATION_STATUSES.has(it.status)\n ? (it.status as ExecutionLogIterationLike[\"status\"])\n : steps.some((s) => s.status === \"failed\")\n ? \"failed\"\n : steps.some((s) => s.status === \"running\")\n ? \"running\"\n : \"succeeded\";\n return {\n index: it.index as number,\n status,\n ...(failedNodeId !== undefined ? { failedNodeId } : {}),\n steps,\n };\n })\n .sort((a, b) => a.index - b.index);\n const finite = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n);\n return {\n iterations,\n ...(finite(step.iterationsTotal) ? { iterationsTotal: step.iterationsTotal } : {}),\n ...(finite(step.iterationsFailed) ? { iterationsFailed: step.iterationsFailed } : {}),\n ...(typeof step.iterationsTruncated === \"boolean\"\n ? { iterationsTruncated: step.iterationsTruncated }\n : {}),\n };\n}\n\n/** The `error` key for one row — present ONLY when the step reports an error\n * or is `failed` (then with {@link STEP_FAILED_NO_REASON}), so a healthy row\n * keeps exactly the shape it had before errors were carried. */\nfunction rowError(step: StepExecutionLike): { error?: LogErrorLike } {\n const error = toLogError(step.error);\n if (error) return { error };\n if (step.status === \"failed\") return { error: { message: STEP_FAILED_NO_REASON } };\n return {};\n}\n\n/**\n * Normalise whatever a step or run reported as its error into the panel's\n * {@link LogErrorLike}. `null`/`undefined` mean \"no error\". A non-empty string\n * is the message. An object contributes `code` (string), `message` (its own\n * non-empty `message`, else a non-empty `code`, else its JSON), `phase`\n * (string) and `retryable` (boolean). Anything else is stringified. The\n * returned `message` is never empty.\n */\nexport function toLogError(raw: unknown): LogErrorLike | undefined {\n if (raw === null || raw === undefined) return undefined;\n if (typeof raw === \"string\" && raw !== \"\") return { message: raw };\n if (typeof raw === \"object\") {\n const o = raw as Record<string, unknown>;\n const code = typeof o.code === \"string\" ? o.code : undefined;\n const message =\n typeof o.message === \"string\" && o.message !== \"\" ? o.message : code || safeJson(raw);\n return {\n ...(code !== undefined ? { code } : {}),\n message: message || \"Unknown error.\",\n ...(typeof o.phase === \"string\" ? { phase: o.phase } : {}),\n ...(typeof o.retryable === \"boolean\" ? { retryable: o.retryable } : {}),\n };\n }\n return { message: String(raw) || \"Unknown error.\" };\n}\n\n/** `JSON.stringify` that answers `\"\"` instead of throwing (a cycle, a BigInt)\n * or returning `undefined` (a `toJSON` that yields nothing). */\nfunction safeJson(raw: unknown): string {\n try {\n return JSON.stringify(raw) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/**\n * The run-level half of the run log: `RunState.error` as `runError`, plus the\n * `RunState.stepErrors` entries whose step has NO row already carrying an\n * error (a `continue-record` failure is usually also on its own row — showing\n * it twice would read as two failures), in their given order. A row showing\n * only {@link STEP_FAILED_NO_REASON} does not count as carrying an error here,\n * so the reason recorded for that step is still surfaced. A `failed` run where\n * nothing — run, rows or surfaced step errors — carries a reason gets\n * {@link RUN_FAILED_NO_REASON}. `runError` is omitted when it duplicates a\n * row's error (equal `message` and equal `code`), since the step failure that\n * stopped the run is already shown on its row. It is likewise omitted when it\n * duplicates a surfaced `stepErrors` entry's error, by the same equality.\n * Keys are omitted when empty.\n */\nexport function runLevelErrors(\n run: RunErrorSourceLike | undefined,\n rows: ReadonlyArray<ExecutionLogStepLike>,\n): { runError?: LogErrorLike; stepErrors?: RecordedLogErrorLike[] } {\n if (!run) return {};\n const carried = new Set(rows.filter((r) => r.error !== undefined).map((r) => r.id));\n const reasoned = new Set(\n rows\n .filter((r) => r.error !== undefined && r.error.message !== STEP_FAILED_NO_REASON)\n .map((r) => r.id),\n );\n const stepErrors = (run.stepErrors ?? [])\n .map((e) => ({ e, id: e.nodeId ?? e.stepId ?? \"\" }))\n .filter(({ id }) => !reasoned.has(id))\n .map(({ e, id }) => ({\n stepId: id,\n error: toLogError(e.error) ?? { message: STEP_FAILED_NO_REASON },\n }));\n const own = toLogError(run.error);\n const sameAsOwn = (e: LogErrorLike | undefined) =>\n own !== undefined && e?.message === own.message && e?.code === own.code;\n const shown = rows.some((r) => sameAsOwn(r.error)) || stepErrors.some((e) => sameAsOwn(e.error));\n let runError = shown ? undefined : own;\n if (!runError && run.status === \"failed\" && carried.size === 0 && stepErrors.length === 0) {\n runError = { message: RUN_FAILED_NO_REASON };\n }\n return {\n ...(runError ? { runError } : {}),\n ...(stepErrors.length > 0 ? { stepErrors } : {}),\n };\n}\n\n/**\n * The header Run's `input`: the LAST saved fixture's `with` (`listStepTests`\n * answers oldest-first — the same \"last is latest\" reading\n * `@w6w/ui`'s `TriggerFillForm` seeds from), when it is a plain object.\n * Sent verbatim — `{type:\"expr\",…}` values included.\n */\nexport function latestFixtureInput(\n tests: ReadonlyArray<StepTestFixtureLike> | undefined,\n): Record<string, unknown> | undefined {\n const last = tests?.[tests.length - 1]?.with;\n if (last === null || typeof last !== \"object\" || Array.isArray(last)) return undefined;\n return last as Record<string, unknown>;\n}\n\n/**\n * Resolve the header Run's `input` for the manual trigger `triggerStepId`.\n * No trigger id → `undefined` without fetching. A fetch that throws or\n * rejects → `undefined`: a missing fixture never blocks the run. Fetched at\n * click time on purpose — a cached `stepTestsKey` query can be stale, since\n * saving a fixture does not invalidate it.\n */\nexport async function resolveHeaderRunInput(\n triggerStepId: string | undefined,\n list: (stepId: string) => Promise<ReadonlyArray<StepTestFixtureLike> | undefined>,\n remembered?: () => Promise<ReadonlyArray<{ nodeId: string; input: unknown }> | undefined>,\n): Promise<Record<string, unknown> | undefined> {\n if (!triggerStepId) return undefined;\n // The REMEMBERED test input (`node_test_inputs`) is what the trigger last ran with on any\n // editor surface, so it wins; a `{}` row was cleared (no `input`, no fixture fallback). No row\n // (or a failed read) falls back to the latest fixture, exactly as before.\n if (remembered) {\n try {\n const row = (await remembered())?.find((r) => r.nodeId === triggerStepId);\n if (row) {\n const input = row.input;\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) return undefined;\n return Object.keys(input).length > 0 ? (input as Record<string, unknown>) : undefined;\n }\n } catch {\n // fall through to the fixture\n }\n }\n try {\n return latestFixtureInput(await list(triggerStepId));\n } catch {\n return undefined;\n }\n}\n\n/** The trigger the header Run starts at, and whether it is the Manual trigger. */\nexport interface HeaderRunEntry {\n id: string;\n manual: boolean;\n}\n\n/**\n * The trigger the header Run starts at, and so whose remembered sample payload it runs with: the\n * FIRST Manual trigger (a run's own default entry), else the first other entry trigger — a\n * webhook, a schedule or an app trigger. Before, only a Manual trigger was looked up, so a\n * webhook-started workflow's header Run sent no payload at all. `undefined` when nothing in\n * `steps` is a trigger. The predicates are injected (`@w6w/ui/flow`), as in `trigger-preview.ts`.\n */\nexport function headerRunEntry(\n steps: ReadonlyArray<{ id: string; uses?: { app?: string; trigger?: unknown } }>,\n isManualTrigger: (app: string) => boolean,\n isEntryTrigger: (uses: { app: string; trigger?: true }) => boolean,\n): HeaderRunEntry | undefined {\n const manual = steps.find((s) => !!s.uses?.app && isManualTrigger(s.uses.app));\n if (manual) return { id: manual.id, manual: true };\n const other = steps.find(\n (s) =>\n !!s.uses?.app &&\n isEntryTrigger({ app: s.uses.app, ...(s.uses.trigger === true ? { trigger: true } : {}) }),\n );\n return other ? { id: other.id, manual: false } : undefined;\n}\n","/**\n * The run-polling loop, split out of `api/client.ts`'s original `runWorkflow`\n * into its own PURE module — for the SAME mechanical reason\n * `repos/reliability-uptime.ts` exists (read that file's own header comment in\n * full): a `.ts` module that would otherwise transitively import\n * `../api/apiClient.tsx` (a `.tsx` file Node's type-stripping cannot load at\n * all) must be split out to stay reachable by `node --test`.\n *\n * Ported field-for-field from `api/client.ts`'s original `runWorkflow` (same\n * 500 ms interval, same 600-iteration cap, same \"one more fetch after the\n * loop\" shape) — the ONLY change is the injected `getRun`/`sleep` parameters,\n * which is what makes this loop testable on a fake clock instead of a real\n * 5-minute wait. See `../repos/workflows.ts` for the caller.\n */\nimport type { RunState } from \"@w6w/sdk/console\";\n\nconst TERMINAL = new Set([\"succeeded\", \"failed\", \"canceled\"]);\n\nfunction realSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll `getRun` until the run reaches a terminal status, or 600 polls (~5\n * minutes at the default 500ms interval) elapse — whichever comes first.\n * Ported verbatim from `api/client.ts`'s `runWorkflow`; see\n * `../repos/workflows.ts` for the caller.\n */\nexport async function pollRunToTerminal(\n getRun: () => Promise<RunState>,\n sleep: (ms: number) => Promise<void> = realSleep,\n): Promise<RunState> {\n for (let i = 0; i < 600; i++) {\n const run = await getRun();\n if (TERMINAL.has(run.status)) return run;\n await sleep(500);\n }\n return getRun();\n}\n","// Run: node --test src/lib/__tests__/history-query.test.ts (Node 24, type-stripped)\n//\n// T2.3.1 — the pure data layer behind the project-wide and per-callable\n// History page (T2.4.1) and the Function/Endpoint/Workflow header's History\n// button (T2.4.2). Everything that is a judgment call rather than React\n// plumbing lives here: how a URL's search string becomes a `HistoryFilters`\n// (and back), how a filter set becomes the wire's own query params, the\n// query keys every hook in `repos/history.ts` shares, and how a summary row\n// is expanded into a full detail view for one of the three callable kinds.\n//\n// Zero runtime imports other than `./workflow-live-run.ts` and\n// `./workflow-poll.ts` (A1) — every other import here is `import type`, erased\n// at build time, so `node --test` can load this module directly with no React,\n// no SDK runtime, no JSX. The first reuses `mapRunStateToLogSteps`, the same\n// step mapper the visual editor's live-run overlay already uses, so a\n// workflow's historical detail view renders steps identically to its live\n// one; the second is the same run-polling loop the editor's own Run uses, so a\n// re-run waits for its workflow exactly as a run started there does.\n//\n// The wire shape (`ExecutionKind`, `ExecutionStatus`, `ExecutionSummary`,\n// `ExecutionStats`) is pinned verbatim against T2.1.1's own contract — do not\n// drift it; T2.4.1/T2.4.2 are written against this file's exports exactly.\n\nimport type { W6WClient } from \"@w6w/sdk\";\nimport { mapRunStateToLogSteps, runNodeMap } from \"./workflow-live-run.ts\";\nimport { pollRunToTerminal } from \"./workflow-poll.ts\";\n\n// ── wire types (pinned, identical to T2.1.1 §Wire) ──────────────────────\n\nexport type ExecutionKind = \"function\" | \"endpoint\" | \"workflow\";\nexport type ExecutionStatus = \"queued\" | \"running\" | \"succeeded\" | \"failed\" | \"canceled\";\n\nexport interface ExecutionSummary {\n id: string;\n kind: ExecutionKind;\n callableId: string;\n callableName: string;\n status: ExecutionStatus;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n workflowRunId: string | null;\n /** The execution this one RE-RUNS (History's Re-run), or `null`. Absent from an older server. */\n rerunOf?: string | null;\n /** How a workflow run was started (manual, schedule, webhook, event, replay); `null` for a\n * Function/Endpoint call. Absent from an older server. */\n trigger?: string | null;\n /** The trigger node a workflow run entered through. Absent from an older server. */\n triggerNodeId?: string | null;\n /** The start of the input as JSON text. Absent from an older server. */\n inputPreview?: string | null;\n}\n\nexport interface ExecutionStats {\n total: number;\n succeeded: number;\n failed: number;\n canceled: number;\n inFlight: number;\n successRate: number | null;\n avgDurationMs: number | null;\n}\n\n// ── scope + filters ───────────────────────────────────────────────────────\n\n/** Either the project-wide view or one callable's own history — mutually\n * exclusive, never both, mirroring the wire's own `project`|`callable`\n * params (exactly one). */\nexport type HistoryScope = { project: string } | { callable: string };\n\n/** Everything the History page's filter chrome can set, already parsed out\n * of the URL. `status`/`kind` are `\"\"` for \"any\"; `from`/`to` are the\n * `YYYY-MM-DD` the date pickers hand back, or `\"\"` for unset; `offset` is\n * always a non-negative integer (0 for \"first page\"). */\nexport interface HistoryFilters {\n status: ExecutionStatus | \"\";\n kind: ExecutionKind | \"\";\n from: string;\n to: string;\n q: string;\n offset: number;\n}\n\nexport const EMPTY_HISTORY_FILTERS: HistoryFilters = {\n status: \"\",\n kind: \"\",\n from: \"\",\n to: \"\",\n q: \"\",\n offset: 0,\n};\n\nexport const HISTORY_PAGE_SIZE = 25;\n\nconst VALID_STATUSES: ReadonlySet<string> = new Set([\n \"queued\",\n \"running\",\n \"succeeded\",\n \"failed\",\n \"canceled\",\n]);\nconst VALID_KINDS: ReadonlySet<string> = new Set([\"function\", \"endpoint\", \"workflow\"]);\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** True when `YYYY-MM-DD` names a real calendar day (`2026-02-30` rolls into\n * March through `new Date`, so a round-trip comparison rejects it). */\nfunction isRealDate(s: string): boolean {\n if (!DATE_RE.test(s)) return false;\n const { y, m, d } = dateParts(s);\n const dt = new Date(y, m - 1, d);\n return dt.getFullYear() === y && dt.getMonth() === m - 1 && dt.getDate() === d;\n}\n\n/** Parse a validated `YYYY-MM-DD` string into its three numeric parts. */\nfunction dateParts(value: string): { y: number; m: number; d: number } {\n const [y, m, d] = value.split(\"-\").map(Number);\n return { y, m, d };\n}\n\n/**\n * URL search string → `HistoryFilters`. An unrecognised `status`/`kind`, a\n * `from`/`to` not matching `YYYY-MM-DD`, or a non-integer/negative `offset`\n * all fall back to their empty/zero default rather than carrying a bogus\n * value forward into a request — a stale or hand-edited URL degrades to \"no\n * filter\" instead of erroring.\n */\nexport function filtersFromSearch(search: string): HistoryFilters {\n const params = new URLSearchParams(search);\n const status = params.get(\"status\") ?? \"\";\n const kind = params.get(\"kind\") ?? \"\";\n const from = params.get(\"from\") ?? \"\";\n const to = params.get(\"to\") ?? \"\";\n const q = params.get(\"q\") ?? \"\";\n const offsetRaw = params.get(\"offset\");\n let offset = 0;\n if (offsetRaw !== null) {\n const n = Number(offsetRaw);\n if (Number.isInteger(n) && n >= 0) offset = n;\n }\n return {\n status: VALID_STATUSES.has(status) ? (status as ExecutionStatus) : \"\",\n kind: VALID_KINDS.has(kind) ? (kind as ExecutionKind) : \"\",\n from: isRealDate(from) ? from : \"\",\n to: isRealDate(to) ? to : \"\",\n q,\n offset,\n };\n}\n\n/**\n * `HistoryFilters` → URL search string. `\"\"` when every field is at its\n * default, else a leading-`?` string with only the non-default fields, in\n * the pinned key order `status,kind,from,to,q,offset` (so two renders of the\n * same filters always produce byte-identical URLs — stable for bookmarking\n * and for `filtersFromSearch` round-tripping).\n */\nexport function filtersToSearch(f: HistoryFilters): string {\n const params = new URLSearchParams();\n if (f.status !== \"\") params.set(\"status\", f.status);\n if (f.kind !== \"\") params.set(\"kind\", f.kind);\n if (f.from !== \"\") params.set(\"from\", f.from);\n if (f.to !== \"\") params.set(\"to\", f.to);\n if (f.q !== \"\") params.set(\"q\", f.q);\n if (f.offset > 0) params.set(\"offset\", String(f.offset));\n const s = params.toString();\n return s === \"\" ? \"\" : `?${s}`;\n}\n\n/**\n * `HistoryFilters` + a scope → the wire's own query params (D3/pinned rules).\n * `kind` is sent only for a project scope with a non-empty kind — a\n * per-callable view already knows its one kind, and the server's `kind`\n * param is project-mode-only. `from`/`to` are expanded from the picked\n * calendar day into the half-open `[from, to)` ISO instant range the wire\n * wants — `to` is the NEXT day's midnight so the picked day itself is fully\n * inclusive. `q` is trimmed and omitted when blank (server-side id/name\n * search, D3 — never a payload scan). Paging params are added only when\n * `opts.paged`: `limit` always (defaulting to `HISTORY_PAGE_SIZE`), `offset`\n * only when it would change anything (`> 0`).\n */\nexport function historyRequestQuery(\n scope: HistoryScope,\n f: HistoryFilters,\n opts: { paged: boolean; limit?: number },\n): Record<string, string> {\n const query: Record<string, string> = {};\n\n if (\"project\" in scope) {\n query.project = scope.project;\n if (f.kind !== \"\") query.kind = f.kind;\n } else {\n query.callable = scope.callable;\n }\n\n if (f.status !== \"\") query.status = f.status;\n\n if (f.from !== \"\" && isRealDate(f.from)) {\n const { y, m, d } = dateParts(f.from);\n query.from = new Date(y, m - 1, d).toISOString();\n }\n if (f.to !== \"\" && isRealDate(f.to)) {\n const { y, m, d } = dateParts(f.to);\n query.to = new Date(y, m - 1, d + 1).toISOString();\n }\n\n const q = f.q.trim();\n if (q !== \"\") query.q = q;\n\n if (opts.paged) {\n query.limit = String(opts.limit ?? HISTORY_PAGE_SIZE);\n if (f.offset > 0) query.offset = String(f.offset);\n }\n\n return query;\n}\n\n// ── cache keys (ship from here, never from a caller — mirrors `repos/dashboard.ts`) ──\n\n/**\n * Every key this domain reads or invalidates. `list`/`stats` carry the full\n * scope and filters object so two distinct filter sets never collide on the\n * same cache entry (and the identical pair always do) — react-query's own\n * structural key hashing does the rest.\n */\nexport const historyKeys = {\n root: [\"history\"] as const,\n list(scope: HistoryScope, f: HistoryFilters, limit: number): readonly unknown[] {\n return [\"history\", \"list\", scope, f, limit];\n },\n stats(scope: HistoryScope, f: HistoryFilters): readonly unknown[] {\n return [\"history\", \"stats\", scope, f];\n },\n exists(callableId: string): readonly [\"history\", \"exists\", string] {\n return [\"history\", \"exists\", callableId];\n },\n detail(kind: ExecutionKind, id: string): readonly [\"history\", \"detail\", ExecutionKind, string] {\n return [\"history\", \"detail\", kind, id];\n },\n};\n\n// ── fetchers ─────────────────────────────────────────────────────────────\n\n/** `GET /history` — paged. */\nexport function getHistory(\n client: W6WClient,\n scope: HistoryScope,\n f: HistoryFilters,\n limit: number = HISTORY_PAGE_SIZE,\n): Promise<{ executions: ExecutionSummary[]; hasMore: boolean }> {\n return client\n .request<{ executions: ExecutionSummary[]; hasMore: boolean }>({\n method: \"GET\",\n path: \"/history\",\n query: historyRequestQuery(scope, f, { paged: true, limit }),\n })\n .then((response) => response.body);\n}\n\n/** `GET /history/stats` — unpaged (no `limit`/`offset`). */\nexport function getHistoryStats(\n client: W6WClient,\n scope: HistoryScope,\n f: HistoryFilters,\n): Promise<ExecutionStats> {\n return client\n .request<{ stats: ExecutionStats }>({\n method: \"GET\",\n path: \"/history/stats\",\n query: historyRequestQuery(scope, f, { paged: false }),\n })\n .then((response) => response.body.stats);\n}\n\n/** One execution's full detail — the shape `ExecutionDetail` (`@w6w/ui`,\n * T2.2.2) renders. `steps` is present only for a workflow run; a\n * function/endpoint invocation has none. */\nexport interface ExecutionDetailData {\n id: string;\n kind: ExecutionKind;\n callableName: string;\n status: ExecutionStatus;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n /** The execution this one re-runs, carried from its summary row. */\n rerunOf?: string | null;\n steps?: Array<{\n id: string;\n status: \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n skipReason?: \"not_on_path\" | \"condition\" | \"stopped\" | \"disabled\";\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n node?: StepNode;\n }>;\n}\n\n/** What a workflow step IS (`@w6w/ui`'s `ExecutionLogNode`, restated locally — A1): the app and\n * action it uses, whether it is a trigger, and the app's display names when it is a registered app.\n * A built-in `@w6w/*` node carries ids only; the panel names those from its own catalog. */\nexport interface StepNode {\n app: string;\n action: string;\n trigger?: boolean;\n appName?: string;\n actionName?: string;\n}\n\n/** The slice of a definition node this module reads. */\ninterface DefinitionNode {\n id?: unknown;\n uses?: { app?: unknown; action?: unknown; trigger?: unknown };\n}\n\n/**\n * Every node of the workflow's CURRENT definition, keyed by id, as a {@link StepNode} — with the\n * display names of each registered app (`GET /apps/:id`'s `displayName` and action titles, plus\n * `GET /apps/:id/triggers` for an app a trigger node uses). Best-effort throughout: a definition\n * that cannot be read yields an empty map, and an app that cannot be read keeps its raw ids.\n */\nexport async function describeWorkflowNodes(\n client: W6WClient,\n workflowId: string,\n): Promise<Map<string, StepNode>> {\n const out = new Map<string, StepNode>();\n let nodes: DefinitionNode[];\n try {\n const { workflow } = await client.console.workflows.get(workflowId);\n nodes = Array.isArray(workflow.nodes) ? (workflow.nodes as DefinitionNode[]) : [];\n } catch {\n return out;\n }\n for (const n of nodes) {\n const app = n.uses?.app;\n const action = n.uses?.action;\n if (typeof n.id !== \"string\" || typeof app !== \"string\" || typeof action !== \"string\") continue;\n out.set(n.id, { app, action, ...(n.uses?.trigger === true ? { trigger: true } : {}) });\n }\n\n // Built-in `@w6w/*` ids are not served by `/apps/:id`; the panel names those itself.\n const registered = [...new Set([...out.values()].map((n) => n.app))].filter(\n (app) => !app.startsWith(\"@w6w/\"),\n );\n const names = await Promise.all(\n registered.map(async (app) => {\n const wantsTriggers = [...out.values()].some((n) => n.app === app && n.trigger);\n const [detail, triggers] = await Promise.all([\n client.console.apps.get(app).catch(() => null),\n wantsTriggers ? client.console.apps.getTriggers(app).catch(() => []) : Promise.resolve([]),\n ]);\n const titles = new Map<string, string>();\n for (const a of detail?.actions ?? []) titles.set(`a:${a.key}`, a.title);\n for (const t of triggers) titles.set(`t:${t.key}`, t.title);\n return { app, displayName: detail?.app.displayName, titles };\n }),\n );\n for (const node of out.values()) {\n const named = names.find((n) => n.app === node.app);\n if (!named) continue;\n if (named.displayName) node.appName = named.displayName;\n const title = named.titles.get(`${node.trigger ? \"t\" : \"a\"}:${node.action}`);\n if (title) node.actionName = title;\n }\n return out;\n}\n\n/** The `GET /invocations/:id` response body's shape this module reads\n * (context notes: server `db/repos/invocations.ts` `InvocationRow`). */\ninterface InvocationDetailBody {\n status: ExecutionStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n durationMs: number | null;\n startedAt: string;\n finishedAt: string | null;\n}\n\n/**\n * Expand a list row into its full detail. Function/Endpoint invocations are\n * synchronous calls recorded one row per call (`.claude/docs/invocations.md`)\n * — `GET /invocations/:id` by the escape-hatch `client.request` (no typed SDK\n * method exists for this internal route, same reasoning as\n * `repos/callables.ts`'s `archiveCallable`/`deleteCallable` split; A1: no\n * other runtime import needed). A workflow run instead reuses\n * `client.console.workflows.getRun` (`repos/workflows.ts`'s own\n * `getRunState`) — its `variables` become the detail's `input`, and its\n * opaque `steps` map through the SAME `mapRunStateToLogSteps` the live-run\n * overlay uses, so a historical run's step list renders identically to a\n * live one. `callableName` always comes from the summary — neither read\n * carries a human-readable callable name of its own.\n */\nexport async function getExecutionDetail(\n client: W6WClient,\n summary: ExecutionSummary,\n): Promise<ExecutionDetailData> {\n if (summary.kind === \"workflow\") {\n const [run, described] = await Promise.all([\n client.console.workflows.getRun(summary.id),\n describeWorkflowNodes(client, summary.callableId),\n ]);\n // What STARTED the run: the start payload (`input`), else the trigger's delivered `event` —\n // both ride `GET /runs/:id` beside the SDK's typed fields — else, for a run that had\n // neither, its variables.\n const started = run as unknown as { input?: unknown; event?: unknown };\n return {\n id: summary.id,\n kind: \"workflow\",\n callableName: summary.callableName,\n status: run.status,\n startedAt: summary.startedAt,\n finishedAt: summary.finishedAt,\n durationMs: summary.durationMs,\n input: started.input ?? started.event ?? run.variables,\n output: run.output,\n error: run.error,\n rerunOf: summary.rerunOf ?? null,\n steps: mapRunStateToLogSteps(runNodeMap(run)).map((step) => {\n const node = described.get(step.id);\n return node ? { ...step, node } : step;\n }),\n };\n }\n\n const response = await client.request<{ invocation: InvocationDetailBody }>({\n method: \"GET\",\n path: `/invocations/${encodeURIComponent(summary.id)}`,\n });\n const invocation = response.body.invocation;\n return {\n id: summary.id,\n kind: summary.kind,\n callableName: summary.callableName,\n status: invocation.status,\n startedAt: invocation.startedAt,\n finishedAt: invocation.finishedAt,\n durationMs: invocation.durationMs,\n input: invocation.input,\n output: invocation.output,\n error: invocation.error,\n rerunOf: summary.rerunOf ?? null,\n };\n}\n\n// ── re-run ───────────────────────────────────────────────────────────────\n\n/** The invocation id a FAILED invoke still minted: the server stamps its frame\n * onto the error body (`withInvocationFrame`), and `@w6w/sdk`'s `ApiError`\n * keeps that body as `raw`. Duck-typed so this module stays SDK-runtime-free. */\nfunction invocationIdOf(err: unknown): string | undefined {\n const raw = (err as { raw?: unknown } | null)?.raw;\n const id = (raw as { invocationId?: unknown } | null)?.invocationId;\n return typeof id === \"string\" ? id : undefined;\n}\n\n/** A plain object, or `{}` — a stored input that is not an object (or is\n * absent) cannot be an invoke body. */\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\n/** Start the new execution and return its id: the run id for a workflow (once\n * the run is terminal), the invocation id for a function/endpoint — also when\n * the call itself failed, since a failed call is still a recorded execution. */\nasync function startRerun(\n client: W6WClient,\n summary: ExecutionSummary,\n sleep?: (ms: number) => Promise<void>,\n): Promise<string> {\n const callable = encodeURIComponent(summary.callableId);\n\n if (summary.kind === \"workflow\") {\n // The SERVER replays the stored seed — trigger type, variables, start input, the trigger's\n // delivered `event`, entry node, partial-run spec. A client-side replay through\n // `POST /workflows/:id/run` cannot: that route has no slot for `event`, which is where an app\n // or webhook trigger's payload lives.\n const res = await client.request<{ runId: string }>({\n method: \"POST\",\n path: `/runs/${encodeURIComponent(summary.id)}/rerun`,\n body: { allowUnpublished: true },\n });\n const runId = res.body.runId;\n await pollRunToTerminal(() => client.console.workflows.getRun(runId), sleep);\n return runId;\n }\n\n const past = await client.request<{ invocation: InvocationDetailBody }>({\n method: \"GET\",\n path: `/invocations/${encodeURIComponent(summary.id)}`,\n });\n const input = asRecord(past.body.invocation.input);\n // `rerunOf` marks the new invocation as a re-run of this one (`invocations.rerun_of`).\n const body: Record<string, unknown> =\n summary.kind === \"function\"\n ? { inputs: input, allowUnpublished: true, rerunOf: summary.id }\n : { input, allowUnpublished: true, rerunOf: summary.id };\n try {\n const res = await client.request<{ invocationId?: string }>({\n method: \"POST\",\n path: `/${summary.kind === \"function\" ? \"functions\" : \"endpoints\"}/${callable}/invoke`,\n body,\n });\n const id = res.body.invocationId;\n if (typeof id !== \"string\") throw new Error(\"The server did not return an invocation id.\");\n return id;\n } catch (err) {\n const id = invocationIdOf(err);\n if (id === undefined) throw err;\n return id;\n }\n}\n\n/**\n * Run a past execution again with the input it had, against the callable's\n * CURRENT definition (the stored draft — `allowUnpublished`, as the editor's\n * own Run and Test do), and return the new execution's summary row so the\n * host can open it. A workflow is replayed by the server from its stored seed\n * (`POST /runs/:id/rerun`, trigger payload included); a function replays its\n * `inputs`; an endpoint its `input`. `null` when the new row is not yet listed (the host then just\n * shows the refreshed list).\n */\nexport async function rerunExecution(\n client: W6WClient,\n summary: ExecutionSummary,\n opts: { sleep?: (ms: number) => Promise<void> } = {},\n): Promise<ExecutionSummary | null> {\n const id = await startRerun(client, summary, opts.sleep);\n return findExecution(client, summary.callableId, id);\n}\n\n/** One callable's execution by id, as its summary row (`GET /history`'s id search), or `null`\n * when it is not listed — e.g. the original a re-run names, once retention removed it. */\nexport async function findExecution(\n client: W6WClient,\n callableId: string,\n id: string,\n): Promise<ExecutionSummary | null> {\n const found = await getHistory(\n client,\n { callable: callableId },\n { ...EMPTY_HISTORY_FILTERS, q: id },\n 1,\n );\n return found.executions.find((row) => row.id === id) ?? null;\n}\n","import {\n type UseMutationResult,\n useMutation,\n useQuery,\n useQueryClient,\n} from \"@tanstack/react-query\";\nimport type { StateLogRow } from \"@w6w/expr\";\nimport { path } from \"@w6w/sdk\";\nimport type { RunStatus, W6WClient, WorkflowRunResult } from \"@w6w/sdk\";\nimport type { RunState } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport { historyKeys } from \"../lib/history-query.ts\";\nimport { shouldContinuePolling } from \"../lib/workflow-live-run.ts\";\nimport { pollRunToTerminal } from \"../lib/workflow-poll.ts\";\n\nexport type { RunState, RunSummary } from \"@w6w/sdk/console\";\nexport type { WorkflowStatus, WorkflowSummary } from \"@w6w/sdk\";\n\n// `project` distinguishes a project-scoped entry (WorkflowsPage.tsx) from the\n// unscoped one (TargetSelector.tsx, SubscriptionsPage.tsx) — genuinely DIFFERENT\n// queries (not a spelling split to unify like T2.2.2's appActions fix). Keep them\n// as distinct cache entries.\nexport const workflowsKey = (project?: string) => [\"workflows\", project] as const;\n\nexport function listWorkflows(client: W6WClient, project?: string) {\n return client.workflows.list({ project });\n}\n\nexport function useWorkflowsQuery(project?: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: workflowsKey(project),\n queryFn: () => listWorkflows(apiClient, project),\n enabled,\n });\n}\n\nexport const workflowKey = (id: string) => [\"workflow\", id] as const;\n\nexport function getWorkflow(client: W6WClient, id: string) {\n return client.workflows.get(id);\n}\n\nexport function useWorkflowQuery(id: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: workflowKey(id),\n queryFn: () => getWorkflow(apiClient, id),\n enabled,\n });\n}\n\n/**\n * A missing `project` here is not \"unscoped\" the way a read can legitimately\n * be — the write would silently land in the account's default project\n * instead of the one the caller is looking at. Both mutations refuse rather\n * than risk that; `WorkflowsPage.tsx`'s own `projectId != null` gate on\n * `useWorkflowsQuery` should mean `project` is always set by the time either\n * of these can actually be invoked from the UI, but the guard costs nothing.\n */\nexport function useCreateWorkflowMutation(project?: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (definition: unknown) => {\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return apiClient.console.workflows.upsert(definition, { project });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useSaveWorkflowMutation(project?: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { definition: unknown; ifUnmodifiedSince: string | null }) => {\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return apiClient.console.workflows.upsert(vars.definition, {\n project,\n ifUnmodifiedSince: vars.ifUnmodifiedSince,\n });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useArchiveWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.workflows.archive(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useDeleteWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.workflows.delete(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport const runsKey = (workflowId: string) => [\"runs\", workflowId] as const;\n\nexport function useRunsQuery(workflowId: string) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: runsKey(workflowId),\n queryFn: () => apiClient.console.workflows.listRuns(workflowId),\n });\n}\n\n/**\n * Start a run and poll it to a terminal state.\n *\n * `input` is the run's START PAYLOAD, and it is a different thing from\n * `variables`: the server hands it to the entry `@w6w/trigger` node as that\n * node's own output, which is what makes `{{ steps.<trigger>.output.<field> }}`\n * resolve in a real run. Omitted, that node outputs `{}` and every reference to\n * a trigger field resolves to the empty string — the failure mode filed as\n * `.ai/projects/backlog/26-07-29-01-trigger-run-payload.md`, where a step tests\n * green and then does nothing in production. `variables` seeds `var.*` and\n * reaches the trigger node not at all.\n *\n * Goes through the typed `client.workflows.run()` with\n * `allowUnpublished: true`: this call site always runs the STORED draft, and\n * the server exempts a caller that sets the flag from the publish gate\n * (`packages/api/run-workflow.ts`'s `enqueueRun`). The SDK's result is the flat\n * run body, so the `runId` used to poll comes off `res.runId`.\n */\nexport function runWorkflow(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n): Promise<RunState> {\n return client.workflows\n .run(id, { variables, input, allowUnpublished: true })\n .then((res) => pollRunToTerminal(() => client.console.workflows.getRun(res.runId)));\n}\n\nexport function useRunWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n variables: Record<string, unknown>;\n input?: Record<string, unknown>;\n }) => runWorkflow(apiClient, vars.id, vars.variables, vars.input),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\n/**\n * Run a Workflow SYNCHRONOUSLY — the `W6WApi.runWorkflow` facade member's\n * backing function (the Workflows tab's Test stage, D-11/D-15(c)). A sibling\n * of {@link runWorkflow}, NOT a replacement: that function's enqueue-then-poll\n * shape is the studio-wide \"Run this workflow\" action and stays exactly as it\n * is. This one instead sends `wait: true` on the SAME base `client.workflows\n * .run` call already published (`?wait=true` — the server polls internally,\n * up to its own timeout) — zero new server code, and no second poll loop:\n * there is no `pollRunToTerminal` here at all. `terminal`/`httpStatus` on the\n * result distinguish \"finished in time\" (`200`) from \"still going when the\n * server's own wait timed out\" (`202`, a legitimate outcome, not an error).\n */\nexport function runWorkflowSync(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n entry?: string,\n): Promise<WorkflowRunResult> {\n return client.workflows.run(id, { variables, input, entry, wait: true });\n}\n\n/**\n * T2.1.1 — the ENQUEUE half only: starts a run and returns its handle\n * immediately, without polling it to terminal. A genuine sibling of\n * {@link runWorkflow}, NOT a replacement — that function's \"enqueue, then\n * block to a terminal result\" shape is what `WorkflowDetailPage.tsx`'s \"Run\n * now\" panel is built on and stays exactly as it is. This one is for a host\n * that wants the `runId` right away so it can poll it live itself (the\n * visual editor's canvas + execution log panel) — see {@link useLiveRunQuery}.\n *\n * Like {@link runWorkflow}, this calls `client.workflows.run()` with\n * `allowUnpublished: true` unconditionally. Only `{ runId }` is returned, so\n * callers keep reading `runId` off the resolved value exactly as before.\n */\nexport function startWorkflowRun(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n) {\n return client.workflows\n .run(id, { variables, input, allowUnpublished: true })\n .then((res) => ({ runId: res.runId }));\n}\n\n/** What {@link startRunFromNode} sends: the paused nodes to stop before, and the start seed. */\nexport interface RunFromNodeBody {\n /** Node ids the run stops BEFORE (they do not execute) — the editor's paused nodes. */\n stopAt: string[];\n /** Upstream outputs keyed by node id, seeded from saved step tests / the last run. */\n nodes?: Record<string, { output?: unknown; meta?: unknown }>;\n /** The trigger's filled values, when the run starts at a trigger node. */\n input?: Record<string, unknown>;\n}\n\n/**\n * Run from a node — `POST /workflows/:id/nodes/:nodeId/run` with `continue: true`: a REAL run\n * that executes `nodeId`, continues through every node downstream of it the way a run follows\n * its edges, and stops before each `stopAt` node. Answers `202 { runId }` at once, like\n * {@link startWorkflowRun}, so the caller polls it live ({@link useLiveRunQuery}). The run\n * executes the STORED definition, so a caller flushes its draft first.\n *\n * The plain `client.request()` escape hatch, not a typed `@w6w/sdk` method: the route is a\n * console authoring aid, and a typed method would pull `packages/wrappers` (every language, in\n * lockstep) into an editor-only change.\n */\nexport async function startRunFromNode(\n client: W6WClient,\n id: string,\n nodeId: string,\n body: RunFromNodeBody,\n): Promise<{ runId: string }> {\n const res = await client.request<{ runId: string }>({\n method: \"POST\",\n path: path`/workflows/${id}/nodes/${nodeId}/run`,\n body: {\n continue: true,\n stopAt: body.stopAt,\n ...(body.nodes ? { state: { nodes: body.nodes } } : {}),\n ...(body.input ? { input: body.input } : {}),\n },\n });\n return { runId: res.body.runId };\n}\n\n/** A node output's structural shape, as the server records it (structural mirror of `@w6w/ui`'s). */\nexport type NodeSampleShape =\n | { type: \"string\" | \"number\" | \"boolean\" | \"null\" | \"unknown\" }\n | { type: \"object\"; fields: Record<string, NodeSampleShape> }\n | { type: \"array\"; items?: NodeSampleShape };\n\n/**\n * One persisted node sample — structural mirror of `@w6w/ui`'s `NodeSample` (this barrel may not\n * import `@w6w/ui`; the facade/UiBridge assignment typechecks against `W6WApi` structurally).\n */\nexport interface NodeSample {\n nodeId: string;\n shape: NodeSampleShape;\n sample?: unknown;\n sampleOmitted?: true;\n source: \"step_test\" | \"node_run\" | \"run\";\n runId?: string;\n updatedAt: string;\n}\n\n/**\n * The workflow's persisted node samples — `GET /workflows/:id/node-samples` → `{ nodeSamples }`:\n * each node's last output shape (and value, when kept), written server-side on every Test, node\n * run and run. Backs `W6WApi.loadNodeSamples`, so the editor's picker keeps upstream keys across a\n * reload. The plain `client.request()` escape hatch, for the same reason as {@link startRunFromNode}.\n */\nexport function listNodeSamples(client: W6WClient, id: string): Promise<NodeSample[]> {\n return client\n .request<{ nodeSamples?: NodeSample[] }>({\n method: \"GET\",\n path: path`/workflows/${id}/node-samples`,\n })\n .then((res) => res.body.nodeSamples ?? []);\n}\n\n/** One remembered node test input — structural mirror of `@w6w/ui`'s `NodeTestInput`. */\nexport interface NodeTestInput {\n nodeId: string;\n input: Record<string, unknown>;\n updatedAt: string;\n}\n\n/**\n * The test input each node of the workflow last ran with in the editor —\n * `GET /workflows/:id/test-inputs` → `{ testInputs }` (`node_test_inputs`, 0160). Backs\n * `W6WApi.loadTestInputs`, so the Run node modal, the Test tabs and the header Run reopen\n * prefilled. The plain `client.request()` escape hatch, for the same reason as {@link startRunFromNode}.\n */\nexport function listTestInputs(client: W6WClient, id: string): Promise<NodeTestInput[]> {\n return client\n .request<{ testInputs?: NodeTestInput[] }>({\n method: \"GET\",\n path: path`/workflows/${id}/test-inputs`,\n })\n .then((res) => res.body.testInputs ?? []);\n}\n\n/**\n * Remember a node's test input (`{}` clears it) — `PUT /workflows/:id/nodes/:nodeId/test-input`.\n * Backs `W6WApi.saveTestInput`; the server drops sealed envelopes before the write.\n */\nexport function saveTestInput(\n client: W6WClient,\n id: string,\n nodeId: string,\n input: Record<string, unknown>,\n): Promise<void> {\n return client\n .request<{ ok: boolean }>({\n method: \"PUT\",\n path: path`/workflows/${id}/nodes/${nodeId}/test-input`,\n body: { input },\n })\n .then(() => undefined);\n}\n\nexport function useRunFromNodeMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; nodeId: string; body: RunFromNodeBody }) =>\n startRunFromNode(apiClient, vars.id, vars.nodeId, vars.body),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\nexport function useStartRunMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n variables: Record<string, unknown>;\n input?: Record<string, unknown>;\n }) => startWorkflowRun(apiClient, vars.id, vars.variables, vars.input),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\n/** What `client.workflows.cancel` resolves to. Named here because the SDK's root entry does not\n * export its `WorkflowCancelResult`: an inferred return type would name it and `vite-plugin-dts`\n * would skip this whole file (TS2742), leaving every `./repos` declaration out of the tarball. */\nexport type WorkflowCancelResult = Awaited<ReturnType<W6WClient[\"workflows\"][\"cancel\"]>>;\n\n/**\n * T2.1.1/A6 — cancel a queued or running run. `client.workflows.cancel`\n * itself never claims the run has stopped (its own doc comment: a `202`\n * means the request was RECORDED, not that the run finished) — the caller\n * keeps polling {@link useLiveRunQuery} until the run actually reaches a\n * terminal status. See `../lib/workflow-live-run.ts`'s `classifyCancelError`\n * for how a `409 run_not_cancelable` (the run beat the cancel to the finish\n * line) is told apart from a real failure.\n */\nexport function cancelWorkflowRun(client: W6WClient, runId: string): Promise<WorkflowCancelResult> {\n return client.workflows.cancel(runId);\n}\n\nexport function useCancelRunMutation(): UseMutationResult<WorkflowCancelResult, Error, string> {\n const apiClient = useEmbedClient();\n return useMutation({\n mutationFn: (runId: string) => cancelWorkflowRun(apiClient, runId),\n });\n}\n\n/** The single-shot half of {@link useLiveRunQuery} — a thin, directly\n * testable wrapper around `client.console.workflows.getRun`, so the polling\n * config below can be pinned without needing to render a hook. */\nexport function getRunState(client: W6WClient, runId: string): Promise<RunState> {\n return client.console.workflows.getRun(runId);\n}\n\n/** Query key for one run's live state — distinct from {@link runsKey}, which\n * is the workflow's run LIST. */\nexport const runStateKey = (runId: string) => [\"run\", runId] as const;\n\n/**\n * T2.1.1/A2/A3 — poll one run's live state at a fixed 500ms interval,\n * stopping once it reaches a terminal status ({@link shouldContinuePolling},\n * `../lib/workflow-live-run.ts`). A genuine sibling of `pollRunToTerminal`\n * (`../lib/workflow-poll.ts`) using the SAME underlying SDK call\n * (`client.console.workflows.getRun`), but publishing every intermediate\n * `RunState` to its caller via TanStack Query's own `data` — unlike\n * `pollRunToTerminal`, which discards every non-terminal result and hands\n * back only the last one. `runId === null` disables the query entirely (no\n * run started yet, or the page navigated to a different workflow).\n */\nexport function useLiveRunQuery(runId: string | null) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: runStateKey(runId ?? \"\"),\n queryFn: () => getRunState(apiClient, runId as string),\n enabled: runId != null,\n refetchInterval: (query) => (shouldContinuePolling(query.state.data?.status) ? 500 : false),\n });\n}\n\n/** `GET /runs/:id/state-writes` — the run's state-write log (plan §2.4). */\nexport interface RunStateWrites {\n writes: StateLogRow[];\n truncated: boolean;\n}\n\n/**\n * One run's state-write log, read for the run log's State block (\"state after this\n * step\"). The plain `client.request()` escape hatch, for the same reason as\n * {@link listNodeSamples}: the route has no typed `@w6w/sdk` method.\n */\nexport function getRunStateWrites(client: W6WClient, runId: string): Promise<RunStateWrites> {\n return client\n .request<{ writes?: StateLogRow[]; truncated?: boolean }>({\n method: \"GET\",\n path: path`/runs/${runId}/state-writes`,\n })\n .then((res) => ({ writes: res.body.writes ?? [], truncated: res.body.truncated === true }));\n}\n\n/** Query key for one run's state-write log. The last segment flips from `\"live\"` to\n * `\"final\"` when the run turns terminal, so the final log is fetched exactly once more. */\nexport function runStateWritesKey(runId: string, status: RunStatus | undefined) {\n return [\"run\", runId, \"state-writes\", shouldContinuePolling(status) ? \"live\" : \"final\"] as const;\n}\n\n/**\n * Poll one run's state-write log beside {@link useLiveRunQuery}: the same 500ms cadence\n * while the run (as `status`, the live run query's answer) is in flight, no polling once\n * terminal. `retry: false` — a failed read only leaves the run log without its State\n * block; it never touches the run poll.\n */\nexport function useRunStateWritesQuery(runId: string | null, status: RunStatus | undefined) {\n const apiClient = useEmbedClient();\n const live = shouldContinuePolling(status);\n return useQuery({\n queryKey: runStateWritesKey(runId ?? \"\", status),\n queryFn: () => getRunStateWrites(apiClient, runId as string),\n enabled: runId != null,\n refetchInterval: live ? 500 : false,\n retry: false,\n });\n}\n"],"names":["runNodeMap","run","STEP_FAILED_NO_REASON","RUN_FAILED_NO_REASON","shouldContinuePolling","status","isTerminalRunStatus","isRunInFlight","pollFailed","STEP_PASS_REFRESH_DELAYS_MS","stepPassRefreshDue","runWorkflowId","workflowId","runButtonLabel","classifyCancelError","code","mapRunStateToLogSteps","steps","stateLog","state","stateFieldsByNode","id","step","mapStep","iterationFields","log","rows","a","b","byNode","row","entry","group","out","writes","lastSeq","foldStateLog","SKIP_REASONS","line","rowError","ITERATION_STATUSES","iterations","it","nodes","s","failedNodeId","_a","finite","n","error","toLogError","raw","o","message","safeJson","runLevelErrors","carried","r","reasoned","stepErrors","e","own","sameAsOwn","runError","latestFixtureInput","tests","last","resolveHeaderRunInput","triggerStepId","list","remembered","input","headerRunEntry","isManualTrigger","isEntryTrigger","manual","other","TERMINAL","realSleep","ms","resolve","pollRunToTerminal","getRun","sleep","i","EMPTY_HISTORY_FILTERS","HISTORY_PAGE_SIZE","VALID_STATUSES","VALID_KINDS","DATE_RE","isRealDate","y","m","d","dateParts","dt","value","filtersFromSearch","search","params","kind","from","to","q","offsetRaw","offset","filtersToSearch","f","historyRequestQuery","scope","opts","query","historyKeys","limit","callableId","getHistory","client","response","getHistoryStats","describeWorkflowNodes","workflow","app","action","_b","_c","registered","names","wantsTriggers","detail","triggers","titles","t","node","named","title","getExecutionDetail","summary","described","started","invocation","invocationIdOf","err","asRecord","startRerun","callable","runId","past","body","rerunExecution","findExecution","workflowsKey","project","listWorkflows","useWorkflowsQuery","enabled","apiClient","useEmbedClient","useQuery","workflowKey","getWorkflow","useWorkflowQuery","useCreateWorkflowMutation","qc","useQueryClient","useMutation","definition","useSaveWorkflowMutation","vars","useArchiveWorkflowMutation","useDeleteWorkflowMutation","runsKey","useRunsQuery","runWorkflow","variables","res","useRunWorkflowMutation","_res","runWorkflowSync","startWorkflowRun","startRunFromNode","nodeId","path","listNodeSamples","listTestInputs","saveTestInput","useRunFromNodeMutation","useStartRunMutation","cancelWorkflowRun","useCancelRunMutation","getRunState","runStateKey","useLiveRunQuery","getRunStateWrites","runStateWritesKey","useRunStateWritesQuery","live"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@w6w/embed",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.21",
|
|
4
4
|
"description": "Embed w6w's managed editor and providers in a host React app.",
|
|
5
5
|
"license": "FSL-1.1-ALv2",
|
|
6
6
|
"repository": {
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@tanstack/react-query": "^5.62.7",
|
|
76
76
|
"@w6w/react": "^0.9.15",
|
|
77
|
-
"@w6w/sdk": "^0.9.
|
|
77
|
+
"@w6w/sdk": "^0.9.30",
|
|
78
78
|
"@w6w/expr": "^0.1.2",
|
|
79
|
-
"@w6w/ui": "^0.2.
|
|
79
|
+
"@w6w/ui": "^0.2.57",
|
|
80
80
|
"yaml": "^2.4.2"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|