@w6w/embed 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +105 -0
- package/README.md +166 -2
- package/dist/W6WEmbedProvider.d.ts +29 -0
- package/dist/chrome/CallFromCodeButton.d.ts +155 -0
- package/dist/chrome/CallableSettingsModal.d.ts +17 -0
- package/dist/chrome/ConfirmModal.d.ts +20 -0
- package/dist/chrome/DangerZone.d.ts +19 -0
- package/dist/chrome/ExecutionProfileHeader.d.ts +69 -0
- package/dist/chrome/HistoryButton.d.ts +8 -0
- package/dist/chrome/HistoryModal.d.ts +9 -0
- package/dist/chrome/HistoryView.d.ts +15 -0
- package/dist/chrome/ImportSpecModal.d.ts +40 -0
- package/dist/chrome/JsonToggle.d.ts +51 -0
- package/dist/chrome/Modal.d.ts +20 -0
- package/dist/chrome/RightRail.d.ts +24 -0
- package/dist/chrome/TagEditor.d.ts +23 -0
- package/dist/chrome/VersionHistoryModal.d.ts +38 -0
- package/dist/chrome/history-open-run.d.ts +7 -0
- package/dist/chrome/index.d.ts +36 -0
- package/dist/chrome/workspace.d.ts +67 -0
- package/dist/client-context-CX61Bgw-.js +16 -0
- package/dist/client-context-CX61Bgw-.js.map +1 -0
- package/dist/draft/autosave-flush.d.ts +63 -0
- package/dist/draft/autosave.d.ts +68 -0
- package/dist/draft/client-context.d.ts +8 -0
- package/dist/draft/draft-registry.d.ts +14 -0
- package/dist/draft/index.d.ts +15 -0
- package/dist/draft/use-workflow-draft.d.ts +67 -0
- package/dist/draft/workflow-save.d.ts +48 -0
- package/dist/draft-registry-YF0tqNN0.js +49 -0
- package/dist/draft-registry-YF0tqNN0.js.map +1 -0
- package/dist/draft.d.ts +2 -0
- package/dist/draft.mjs +18 -0
- package/dist/draft.mjs.map +1 -0
- package/dist/editor/WorkflowEditor.d.ts +12 -0
- package/dist/editor/WorkflowSettingsModal.d.ts +17 -0
- package/dist/editor/definition.d.ts +31 -0
- package/dist/editor/editor-apps.d.ts +7 -0
- package/dist/editor/types.d.ts +34 -0
- package/dist/editor.d.ts +9 -0
- package/dist/editor.mjs +2170 -0
- package/dist/editor.mjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +67 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/callable-descriptors.d.ts +77 -0
- package/dist/lib/callable-kind.d.ts +13 -0
- package/dist/lib/code-rail.d.ts +45 -0
- package/dist/lib/document-sources.d.ts +26 -0
- package/dist/lib/error-handler-self.d.ts +25 -0
- package/dist/lib/history-query.d.ts +135 -0
- package/dist/lib/import-paste.d.ts +41 -0
- package/dist/lib/index.d.ts +17 -0
- package/dist/lib/new-id.d.ts +10 -0
- package/dist/lib/rail-settings.d.ts +196 -0
- package/dist/lib/save-invalidation.d.ts +24 -0
- package/dist/lib/sdk-snippets.d.ts +96 -0
- package/dist/lib/settings-rail.d.ts +68 -0
- package/dist/lib/slug.d.ts +69 -0
- package/dist/lib/spec-import-invalidation.d.ts +48 -0
- package/dist/lib/tag-editor.d.ts +36 -0
- package/dist/lib/trigger-preview.d.ts +89 -0
- package/dist/lib/workflow-live-run.d.ts +165 -0
- package/dist/lib/workflow-poll.d.ts +8 -0
- package/dist/lib/workflow-route.d.ts +26 -0
- package/dist/lib/workflow-settings.d.ts +72 -0
- package/dist/lib/workflow-validity.d.ts +92 -0
- package/dist/lib/workflow-variables.d.ts +106 -0
- package/dist/lib.d.ts +2 -0
- package/dist/lib.mjs +62 -0
- package/dist/lib.mjs.map +1 -0
- package/dist/project-context-Dbk0Gr1K.js +16 -0
- package/dist/project-context-Dbk0Gr1K.js.map +1 -0
- package/dist/project-context.d.ts +11 -0
- package/dist/rail/CodeTool.d.ts +2 -0
- package/dist/rail/ErrorHandlingTool.d.ts +22 -0
- package/dist/rail/ExpressionScope.d.ts +21 -0
- package/dist/rail/SettingsTool.d.ts +27 -0
- package/dist/rail/editor-tools.d.ts +2 -0
- package/dist/rail/rail-env.d.ts +18 -0
- package/dist/rail/settings-sections.d.ts +93 -0
- package/dist/repos/documents.d.ts +102 -0
- package/dist/repos/history.d.ts +24 -0
- package/dist/repos/index.d.ts +22 -0
- package/dist/repos/spec-import.d.ts +44 -0
- package/dist/repos/step-tests.d.ts +19 -0
- package/dist/repos/vars.d.ts +25 -0
- package/dist/repos/vault.d.ts +24 -0
- package/dist/repos/versions.d.ts +112 -0
- package/dist/repos.d.ts +2 -0
- package/dist/repos.mjs +94 -0
- package/dist/repos.mjs.map +1 -0
- package/dist/slug-ByKQgxrf.js +642 -0
- package/dist/slug-ByKQgxrf.js.map +1 -0
- package/dist/spec-import-HgO7ZkLZ.js +898 -0
- package/dist/spec-import-HgO7ZkLZ.js.map +1 -0
- package/dist/spec-import-invalidation-D3retX4Q.js +18 -0
- package/dist/spec-import-invalidation-D3retX4Q.js.map +1 -0
- package/dist/use-workflow-draft-oI02dsP-.js +314 -0
- package/dist/use-workflow-draft-oI02dsP-.js.map +1 -0
- package/package.json +84 -3
- package/src/styles.css +829 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug-ByKQgxrf.js","sources":["../src/lib/workflow-validity.ts","../src/lib/workflow-variables.ts","../src/lib/workflow-settings.ts","../src/lib/code-rail.ts","../src/lib/import-paste.ts","../src/lib/error-handler-self.ts","../src/lib/document-sources.ts","../src/lib/rail-settings.ts","../src/lib/settings-rail.ts","../src/lib/trigger-preview.ts","../src/lib/sdk-snippets.ts","../src/lib/slug.ts"],"sourcesContent":["/**\n * The publish-time validity gate (`logs/decisions.jsonl` row 9, verbatim):\n *\n * > a step is valid iff (app+action set, or function id set) and all its\n * > required params are filled (reuse `requiredParamsFilled`,\n * > `StepBuilderModal.tsx:577-590`) and, where `testRequired` is set for the\n * > app, its saved test has passed. The workflow is valid iff a trigger exists\n * > and every step is valid. Graph well-formedness (orphaned/unreachable\n * > nodes, dangling edges) is explicitly OUT of scope for this project.\n *\n * Pure and testable by design: `WorkflowsPage.tsx` is JSX, which Node 24's\n * type-stripping cannot parse, so nothing in it can be loaded by `node --test`\n * (same shape as `src/lib/workflow-save.ts` + its `.test.ts`). This module\n * cannot import `@w6w/ui`/`@w6w/ui/flow` either way: `@w6w/ui`'s\n * `package.json` `exports[\".\"]` resolves to raw `./src/index.ts`, which\n * re-exports `StepBuilderModal.tsx` — a `.tsx` file — so `node --test` throws\n * `ERR_UNKNOWN_FILE_EXTENSION` the moment anything here imports it. Instead,\n * the two functions the pinned predicate reuses\n * (`requiredParamsFilled`/`isTestRequired`) are **caller-injected** on\n * `ValidityContext` — `WorkflowsPage.tsx` (unaffected by the JSX constraint)\n * imports the real ones from `@w6w/ui` and passes them in. Same for \"a\n * trigger exists\": that reads a graph STEP whose `INTERNAL_NODES` entry has\n * `group === \"trigger\"` (`@w6w/ui/flow`), never the workflow's top-level\n * `trigger` field (`rfcs/workflow.md:114`, \"Absent means manual-only\" — always\n * present, so it can't gate anything) — so `hasTrigger` is caller-computed too.\n *\n * `ActionParamLike`/`WorkflowStepLike`/`WorkflowLike` below are this file's\n * own minimal local types (see `rfcs/workflow.md` §\"Step\" for the real shape,\n * `rfcs/function.md` for the `uses.function` arm).\n */\n\n/** A declared action/internal-node param, just enough of it for this gate. */\nexport interface ActionParamLike {\n key: string;\n type: string;\n required?: boolean;\n default?: unknown;\n children?: ActionParamLike[];\n}\n\n/** A workflow graph step, just enough of it for this gate. */\nexport interface WorkflowStepLike {\n id: string;\n uses?: {\n app?: string;\n action?: string;\n /** The \"or a function id\" arm (`rfcs/function.md:49,260`) — `Step.uses.function`. */\n function?: string;\n };\n with?: Record<string, unknown>;\n}\n\n/** A workflow definition, just enough of it for this gate. */\nexport interface WorkflowLike {\n steps?: WorkflowStepLike[];\n /**\n * Present on real definitions, never read here — graph well-formedness\n * (orphaned/unreachable nodes, dangling edges) is explicitly out of scope\n * for the publish gate (`logs/decisions.jsonl` row 9).\n */\n edges?: unknown;\n}\n\n/**\n * Everything `stepValid`/`workflowValid`/`invalidReason` need that this pure\n * module cannot compute or import itself — see the module docstring for why\n * each field is caller-built rather than derived in here.\n */\nexport interface ValidityContext {\n /** Does the graph contain a step whose (app, action) is a trigger node? */\n hasTrigger: boolean;\n /** Declared params for a step's target, keyed `` `${app}::${action}` ``. */\n actionParamsByKey: Record<string, ActionParamLike[]>;\n /** The fetched apps list, keyed by app id — only a key present here is test-gated. */\n appsById: Record<string, unknown>;\n /** Whether the given step id has a saved test that last ran successfully. */\n testStatus: Record<string, boolean>;\n /** `@w6w/ui`'s `requiredParamsFilled`, injected (see module docstring). */\n requiredParamsFilled: (params: ActionParamLike[], values: Record<string, unknown>) => boolean;\n /** `@w6w/ui`'s `isTestRequired`, injected (see module docstring). */\n isTestRequired: (app: unknown) => boolean;\n}\n\n/** Which of the pinned predicate's checks a step fails, or `null` when it's valid. */\ntype StepFailure = \"target missing\" | \"required params\" | \"saved test\";\n\n/**\n * The single place the pinned predicate's branching lives — `stepValid` and\n * `invalidReason` both read this rather than re-deriving the same checks.\n */\nfunction stepFailure(step: WorkflowStepLike, ctx: ValidityContext): StepFailure | null {\n const uses = step.uses;\n // A function-targeted step is valid on presence alone (T5.1.1 owns a\n // Function's own runnability separately — not duplicated here).\n if (uses?.function) return null;\n if (!uses?.app || !uses?.action) return \"target missing\";\n const params = ctx.actionParamsByKey[`${uses.app}::${uses.action}`] ?? [];\n const values = step.with ?? {};\n if (!ctx.requiredParamsFilled(params, values)) return \"required params\";\n // The testRequired/saved-test branch applies only when `uses.app` is a real,\n // fetched app — an internal/trigger/control step's app is never a key in\n // `appsById`, so it is never gated on a saved test.\n if (uses.app in ctx.appsById && ctx.isTestRequired(ctx.appsById[uses.app])) {\n if (!ctx.testStatus[step.id]) return \"saved test\";\n }\n return null;\n}\n\n/** Is this one step valid, per the pinned predicate? */\nexport function stepValid(step: WorkflowStepLike, ctx: ValidityContext): boolean {\n return stepFailure(step, ctx) === null;\n}\n\n/**\n * Is the whole workflow valid? A trigger step must exist and every step must\n * be individually valid — nothing about graph well-formedness (this never\n * reads `workflow.edges`, even when present).\n */\nexport function workflowValid(workflow: WorkflowLike, ctx: ValidityContext): boolean {\n if (!ctx.hasTrigger) return false;\n return (workflow.steps ?? []).every((step) => stepValid(step, ctx));\n}\n\n/**\n * `null` when the workflow is valid; otherwise names the cause — `\"no trigger\n * step\"`, or the id of the first invalid step in declared order plus which\n * check it fails.\n */\nexport function invalidReason(workflow: WorkflowLike, ctx: ValidityContext): string | null {\n if (!ctx.hasTrigger) return \"no trigger step\";\n for (const step of workflow.steps ?? []) {\n const failure = stepFailure(step, ctx);\n if (failure) return `${step.id}: ${failure}`;\n }\n return null;\n}\n","/**\n * The pure decisions behind a workflow's `variables` list (T1.1.5) — the\n * Variables tab's authoring surface and the run page's generated-form\n * projection. `variables` rides inside the workflow **definition**\n * (`w6w-workflow/packages/types/mod.ts:170`), the same JSON document that\n * already carries `steps`, so there is no column, no migration and no server\n * change behind it.\n *\n * Pure, React-free, `.ts`, **no value import of `@w6w/ui`** — studio's\n * `test:unit` is a bare `node --test` with no jsx loader\n * (`studio/package.json:17`), so a value import of the barrel (which\n * re-exports `.tsx`) kills the test. Same shape as `workflow-settings.ts`'s\n * reader/writer discipline and `input-seeding.ts`'s pure-module docstring\n * rule.\n *\n * The row type is defined **locally**, structurally identical to\n * `WorkflowVariable` (`w6w-workflow/packages/types/mod.ts:40-45`: `key`,\n * `type?`, `required?`, `default?`), so no cast is needed at the `.tsx`\n * boundary in either direction.\n */\n\n/** One row of a workflow's declared `variables` list. */\nexport interface WorkflowVariableRow {\n key: string;\n type?: \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\";\n required?: boolean;\n default?: unknown;\n}\n\n/** The declared type union `WorkflowVariable.type` accepts. */\nconst VARIABLE_TYPES = new Set([\"string\", \"number\", \"boolean\", \"object\", \"array\"]);\n\n/**\n * Read a workflow definition's `variables` field as an array of rows.\n *\n * Takes `unknown` because the source is `JSON.parse`d and the `</>` editor\n * lets an author type anything: a non-array reads as no variables, and a\n * non-object array entry is dropped rather than crashing the tab. **Never\n * sorts, never de-dups, never re-orders** — declaration order *is*\n * resolution order (D-5) and `resolveVariables` iterates the array in order\n * (`w6w-workflow/packages/engine/src/run.ts:70-83`), so two rows sharing a\n * key both survive, in the order they were declared.\n */\nexport function readVariables(raw: unknown): WorkflowVariableRow[] {\n if (!Array.isArray(raw)) return [];\n const out: WorkflowVariableRow[] = [];\n for (const entry of raw) {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) continue;\n const e = entry as Record<string, unknown>;\n const row: WorkflowVariableRow = { key: typeof e.key === \"string\" ? e.key : \"\" };\n if (typeof e.type === \"string\" && VARIABLE_TYPES.has(e.type)) {\n row.type = e.type as WorkflowVariableRow[\"type\"];\n }\n if (typeof e.required === \"boolean\") row.required = e.required;\n if (e.default !== undefined) row.default = e.default;\n out.push(row);\n }\n return out;\n}\n\n/**\n * The rows ready to write back into the definition's `variables` field.\n *\n * Mirrors `workflow-settings.ts`'s \"default written as absent\" rule, but here\n * it applies to a row's **optional flags, not the value**: `required` is\n * omitted when `false` and `type` is omitted when unset, so opening the tab\n * and touching nothing does not rewrite a legacy definition into\n * `{required:false,type:undefined}` rows. `default` is user data and is kept\n * **verbatim** — including `false`, `0`, `\"\"` and `null` — never dropped as\n * an optimisation (a \"drop falsy\" implementation would lose a `false`\n * default, which is exactly the case the tests pin).\n *\n * Returns `undefined` for an empty array (never `[]`) so the caller\n * (`patchMeta`, via `JSON.stringify`) drops the key entirely — which matters\n * beyond hygiene here: `draftFromWorkflowVariables`\n * (`server/packages/api/mcp/tool-schema.ts:310-326`) treats `undefined` and\n * `length === 0` identically (pass-through), so `[]` and absent already agree\n * on the wire; this just keeps the definition itself from growing an empty\n * `\"variables\": []` on the first open of the tab.\n */\nexport function variablesForSave(rows: WorkflowVariableRow[]): WorkflowVariableRow[] | undefined {\n if (rows.length === 0) return undefined;\n return rows.map((r) => {\n const out: WorkflowVariableRow = { key: r.key };\n if (r.type !== undefined) out.type = r.type;\n if (r.required) out.required = true;\n if (r.default !== undefined) out.default = r.default;\n return out;\n });\n}\n\n/**\n * Every index whose `key` repeats an earlier row's key. `resolveVariables`\n * writes `vars[v.key]` in a loop with no duplicate check (`run.ts:74-80`), so\n * a later row silently wins — this is informational only (the tab marks the\n * row; nothing here blocks a save), never de-duping or rejecting.\n */\nexport function duplicateKeyIndexes(rows: WorkflowVariableRow[]): number[] {\n const seen = new Set<string>();\n const out: number[] = [];\n rows.forEach((r, i) => {\n if (seen.has(r.key)) out.push(i);\n else seen.add(r.key);\n });\n return out;\n}\n\n/**\n * The `vars.*` names to offer row `index`'s expression rail: the keys of\n * rows **strictly above** it, then `projectVars`, deduped, with blanks\n * dropped. Declaration order is resolution order (D-5), so a row can only\n * reference a variable declared earlier than itself — offering a row at or\n * below `index` would suggest a forward reference the engine rejects\n * (T2.1.1). This is the offered rail only; it is not validation.\n */\nexport function varsRailFor(\n rows: WorkflowVariableRow[],\n index: number,\n projectVars: string[],\n): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const k of [...rows.slice(0, index).map((r) => r.key), ...projectVars]) {\n if (k === \"\" || seen.has(k)) continue;\n seen.add(k);\n out.push(k);\n }\n return out;\n}\n\n/** `true` if `v` is an `ExprValue` envelope — the two-key check `@w6w/ui`'s\n * `isExprValue` (`ui/src/types.ts:301-309`) makes, re-implemented locally\n * because this module cannot import `@w6w/ui` at value level (see the\n * module docstring). Mirrors `trigger-preview.ts:102-119`'s sanctioned\n * pattern for the same constraint — this is not duplication. */\nexport function isExprDefault(v: unknown): boolean {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n (v as { type?: unknown }).type === \"expr\" &&\n Array.isArray((v as { parts?: unknown }).parts)\n );\n}\n\n/** One field the run page's generated form fills — structurally assignable\n * to `@w6w/ui/flow`'s `TriggerFieldDef` (all fields optional) with no cast. */\nexport interface RunFormField {\n key: string;\n type?: WorkflowVariableRow[\"type\"];\n default?: unknown;\n required?: boolean;\n}\n\n/**\n * Project a workflow's declared variables into the run page's form fields.\n *\n * A row whose `default` is an `ExprValue` envelope is a server-side\n * computation (its value is resolved at run time, not authored on the\n * client), so it is emitted with **`default` dropped and `required: false`**\n * — never as a value `ui`'s `seedValues` would `String(...)` the envelope\n * into — and its key is listed in `computed` so the host can label the field\n * \"computed at run time\" and post nothing for it. A row with a blank/missing\n * key is dropped, mirroring `@w6w/ui`'s `fieldsToParams`, which does the same\n * before turning field definitions into a fillable form.\n */\nexport function runFormFields(rows: WorkflowVariableRow[]): {\n fields: RunFormField[];\n computed: string[];\n} {\n const fields: RunFormField[] = [];\n const computed: string[] = [];\n for (const r of rows) {\n if (r.key.trim() === \"\") continue;\n if (isExprDefault(r.default)) {\n fields.push({ key: r.key, type: r.type, required: false });\n computed.push(r.key);\n continue;\n }\n fields.push({ key: r.key, type: r.type, default: r.default, required: r.required });\n }\n return { fields, computed };\n}\n","/**\n * The two pure decisions behind a workflow's authoring settings\n * (`rfcs/workflow.md` — \"Amendment — 2026-07-29: authoring presentation\").\n *\n * `settings` rides inside the workflow **definition** — the same JSON document\n * that already carries `steps` — so there is no column, no migration and no\n * server change behind it. What needs pinning is not the storage but the two\n * readings that can silently corrupt a definition, and both live here rather\n * than in `WorkflowsPage.tsx` so they are executable: that file is JSX, which\n * Node 24's type-stripping cannot parse, so nothing in it can be loaded by\n * `node --test`. Same shape as `src/lib/workflow-save.ts` + its `.test.ts`.\n */\nimport type { WorkflowStatus } from \"@w6w/sdk\";\n\n/**\n * Read a workflow definition's `status` field as the real three-state value.\n *\n * `WorkflowsPage.tsx` used to coerce this with `status === \"active\" ? \"active\" :\n * \"draft\"` — a two-way ternary that silently collapsed a freshly-archived\n * workflow back down to `\"draft\"`, which would have reproduced the same bug one\n * layer up in the archive/delete button-swap (an archived workflow would render\n * Archive again instead of Delete). `unknown` because the source is parsed JSON,\n * not a validated value — anything that isn't exactly `\"active\"` or `\"archived\"`\n * reads as `\"draft\"`, same fallback the old coercion used for a missing/garbage\n * status.\n */\nexport function readWorkflowStatus(status: unknown): WorkflowStatus {\n if (status === \"active\" || status === \"archived\") return status;\n return \"draft\";\n}\n\n/** Authoring presentation for one workflow. Declarative only — the engine ignores it. */\nexport type WorkflowSettings = {\n /** Persist edits without an explicit save. Omitted ⇒ **true**. */\n autoSave?: boolean;\n /** Persist step coordinates and `viewport` on save. Omitted ⇒ **true**. */\n savePosition?: boolean;\n /** The canvas camera, written by the editor — never by the settings modal. */\n viewport?: { x: number; y: number; zoom: number };\n};\n\n/** Both flags resolved against their defaults. */\nexport type EffectiveWorkflowSettings = {\n autoSave: boolean;\n savePosition: boolean;\n};\n\n/**\n * The effective flags for a workflow, applying the **true-by-default** rule.\n *\n * ⚠️ Both flags are `true` when omitted. That is deliberately *unlike* the house\n * convention `ports` and `onError` follow, where an absent field reproduces\n * prior behaviour: here the product requires both features on by default, so an\n * absent `settings` object means auto-save **on** and positions **persisted**.\n * The RFC states it three ways and names `?? false` as a contradiction. Only an\n * explicit `false` turns a feature off — hence `!== false`, which also refuses\n * to read `null`, `0` or `\"false\"` out of a hand-edited definition as \"off\".\n *\n * Takes `unknown` because the caller's source is parsed JSON, not a validated\n * value; every non-object reads as \"no flags set\", i.e. both on.\n */\nexport function readSettings(settings: unknown): EffectiveWorkflowSettings {\n const s = settings as WorkflowSettings | undefined;\n return {\n autoSave: s?.autoSave !== false,\n savePosition: s?.savePosition !== false,\n };\n}\n\n/**\n * Set one flag, returning the `settings` object to store.\n *\n * Two rules, both about *not* writing more than was asked:\n *\n * 1. **The default is written as absent.** `true` deletes the key instead of\n * storing `autoSave: true` (the same idiom as an omitted `onError: \"fail\"`).\n * Otherwise merely opening this modal on a legacy workflow and toggling\n * something back would rewrite the definition of every workflow ever\n * authored — and with auto-save on, that write happens by itself.\n * 2. **Everything else survives verbatim**, `viewport` above all: it is the\n * author's saved camera, written by the editor, and a whole-object replace\n * here would silently discard it on the next toggle.\n *\n * Returns `undefined` when nothing is left to store, so the caller drops the\n * key entirely rather than persisting an empty object.\n *\n * The input is `unknown` for the same reason `readSettings`' is — it comes straight\n * out of `JSON.parse`, and the `</>` editor in the very same header lets an author\n * write `\"settings\": \"hello\"`. Spreading that would persist `{\"0\":\"h\",\"1\":\"e\",…}`,\n * and with auto-save on the rewrite would repeat on a debounce, without anyone\n * clicking anything. So anything that is not a plain object reads as \"no flags\n * set\", exactly as it does in `readSettings`.\n */\nexport function writeSetting(\n settings: unknown,\n key: \"autoSave\" | \"savePosition\",\n value: boolean,\n): WorkflowSettings | undefined {\n const prev: WorkflowSettings | undefined =\n typeof settings === \"object\" && settings !== null && !Array.isArray(settings)\n ? (settings as WorkflowSettings)\n : undefined;\n // The copy is load-bearing: a debounced saver keeps payloads across ticks, so a\n // function that mutated `prev` in place would leave a \"has this actually changed?\"\n // comparison looking at one object twice. Never simplify this to `prev ?? {}`.\n const next: WorkflowSettings = { ...prev };\n if (value) delete next[key];\n else next[key] = false;\n return Object.keys(next).length === 0 ? undefined : next;\n}\n","/**\n * Pure decisions behind the right rail's Code tool (`src/ui/rail/CodeTool.tsx`).\n * Split out so `node --test` can gate them directly — mirrors\n * `src/lib/alias-rail.ts`'s own reason for existing: `node --test` throws\n * `ERR_UNKNOWN_FILE_EXTENSION` on any `@w6w/ui`-adjacent import, and\n * `src/ui/workspace.tsx` sits one hop from that barrel through `Layout.tsx`'s\n * import graph. So this module declares its own structural mirror of\n * `WorkspaceCallable` instead of importing it.\n */\nimport type { SnippetCallable, SnippetInput } from \"./sdk-snippets.ts\";\n\n/** Structural mirror of T2.1.2's widened `WorkspaceCallable` (`src/ui/workspace.tsx`). */\nexport type RailCallable =\n | { kind: \"function\"; id: string; key?: string; inputs?: readonly SnippetInput[]; alias?: string }\n | {\n kind: \"endpoint\";\n id: string;\n key?: string;\n invokeUrl?: string;\n invokeUrlByKey?: string;\n urlForm?: \"id\" | \"key\";\n alias?: string;\n inputs?: readonly SnippetInput[];\n }\n | { kind: \"workflow\"; id: string; label?: string; key?: string }\n | { kind: \"connection\"; id: string }\n | null;\n\n/**\n * Is a \"Call from code\" panel meaningful for this context? Mirrors\n * `alias-rail.ts`'s `targetForCallable` fail-closed shape exactly (its own\n * comment: *\"'connection' and no resource at all both fail closed to null —\n * house style\"*) — `\"connection\"` and `null` both answer `false`.\n */\nexport function isAvailable(ctx: RailCallable): boolean {\n if (!ctx) return false;\n switch (ctx.kind) {\n case \"function\":\n case \"endpoint\":\n case \"workflow\":\n return true;\n default:\n return false;\n }\n}\n\n/**\n * The widened-union -> `SnippetCallable` conversion `CodeTool.Panel` hands to\n * `CallFromCodeBody`. `null` for a context this tool has no snippet for\n * (`\"connection\"`, or no resource at all) — defensive, since `isAvailable`\n * already keeps the tool off the strip for those.\n *\n * The one easy-to-miss field: `WorkspaceCallable`'s `label` maps to\n * `SnippetCallable`'s `workflow` arm's `displayName` — NOT the same field\n * name. A naive `{...ctx}` spread compiles (both optional) but silently\n * drops the label everywhere it matters, never caught by `tsc`.\n */\nexport function toSnippetCallable(ctx: RailCallable): SnippetCallable | null {\n if (!ctx) return null;\n switch (ctx.kind) {\n case \"function\":\n return { kind: \"function\", id: ctx.id, key: ctx.key, inputs: ctx.inputs, alias: ctx.alias };\n case \"endpoint\":\n return {\n kind: \"endpoint\",\n id: ctx.id,\n key: ctx.key,\n invokeUrl: ctx.invokeUrl,\n invokeUrlByKey: ctx.invokeUrlByKey,\n urlForm: ctx.urlForm,\n alias: ctx.alias,\n inputs: ctx.inputs,\n };\n case \"workflow\":\n return { kind: \"workflow\", id: ctx.id, displayName: ctx.label, key: ctx.key };\n default:\n return null;\n }\n}\n","/**\n * Pure decision behind `ImportSpecModal`'s Submit gate (T1.2.1, generalizing T3.2.1's A3 over all\n * three spec kinds).\n *\n * `/spec/import` accepts all three spec kinds at one route (T2.1.2 §B), and this affordance is now\n * mounted on the Functions, Endpoints and Workflows lists alike — each instance passing its own\n * `expectedKind`. Pasting a document of the WRONG kind onto a given list would still create a row\n * server-side and then send the operator to e.g. `functions/<ep_…>`, which 404s in the target\n * page's editor. So this module refuses, client-side, before any request is ever sent: (1) text\n * that isn't JSON, (2) a parse result that isn't a plain object, (3) a parsed `kind` that doesn't\n * match `expectedKind`.\n *\n * Nothing beyond that is checked here — `specVersion`, `callable`'s shape,\n * connection/reference resolvability, all of it is the SERVER's job\n * (T2.1.2 §B); duplicating any of it here would drift from what the route\n * actually enforces.\n *\n * `node --test` throws `ERR_UNKNOWN_FILE_EXTENSION` on anything reaching the\n * `@w6w/ui` import graph (`src/lib/alias-rail.ts`'s docblock), so this module\n * takes no value import at all — it has no dependency to avoid in the first\n * place.\n */\n\n/** The parsed paste, once it is confirmed to be a plain JSON object. */\nexport type ParsedSpecDocument = Record<string, unknown>;\n\n/** The one kind a given mount of the Import affordance expects — see `ImportSpecModal`'s `kind` prop. */\nexport type ExpectedSpecKind = \"function\" | \"endpoint\" | \"workflow\";\n\nexport interface ImportPasteResult {\n /**\n * The parsed JSON when it is a plain object — populated even when\n * `blockedReason` names a wrong `kind`, so a caller could still inspect\n * what was found. `null` when the text didn't even parse to an object.\n */\n parsed: ParsedSpecDocument | null;\n /** `null` exactly when the paste is a plausible spec document of `expectedKind`. */\n blockedReason: string | null;\n}\n\n/**\n * Total: never throws, always returns. `JSON.parse` is the only thing here\n * that can throw, and it is caught.\n */\nexport function parseImportPaste(text: string, expectedKind: ExpectedSpecKind): ImportPasteResult {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return { parsed: null, blockedReason: \"Not valid JSON.\" };\n }\n\n if (value === null || Array.isArray(value) || typeof value !== \"object\") {\n return { parsed: null, blockedReason: \"Expected a JSON object, not a bare value or a list.\" };\n }\n\n const parsed = value as ParsedSpecDocument;\n\n if (parsed.kind !== expectedKind) {\n const found = typeof parsed.kind === \"string\" ? parsed.kind : \"unknown\";\n return {\n parsed,\n blockedReason: `This document's kind is \"${found}\", not \"${expectedKind}\" — paste a \"${expectedKind}\" spec document here.`,\n };\n }\n\n return { parsed, blockedReason: null };\n}\n","/**\n * The authoring-time half of the error-handler recursion guard. The server\n * compares resolved values at dispatch time; this small, pure decision keeps\n * the rail from creating the known-identical no-adapter case in the first\n * place without losing an adapter imported or authored elsewhere.\n */\nexport type ErrorHandlerSelfDecision = \"allow\" | \"warn\" | \"block\";\n\nexport interface ErrorHandlerSelfInput {\n resource: { kind: string; id: string };\n target: { kind: string; id: string };\n hasAdapter: boolean;\n}\n\n/**\n * Only Function and Workflow targets can re-enter the currently edited\n * resource. Actions are always allowed. A self-target with no adapter passes\n * the failed input through unchanged, so it is refused; an adapter is kept\n * and called out because only the runtime can determine its resolved values.\n */\nexport function errorHandlerSelfDecision({\n resource,\n target,\n hasAdapter,\n}: ErrorHandlerSelfInput): ErrorHandlerSelfDecision {\n const selfTarget =\n (target.kind === \"function\" || target.kind === \"workflow\") &&\n target.kind === resource.kind &&\n target.id === resource.id;\n if (!selfTarget) return \"allow\";\n return hasAdapter ? \"warn\" : \"block\";\n}\n","/**\n * Pure `Doc[]` → `ExpressionOptions` projections for the ƒx picker's\n * Documents group — extracted out of `ExpressionScope.tsx` so studio's\n * Node-native `test:unit` runner (globbed to `src/lib/__tests__/`,\n * `src/api/__tests__/` and `src/repos/__tests__/` only — `.ai/PLANNER.md`\n * fact 10) can reach it. No React, no import from `src/ui/` — `@w6w/ui`'s\n * `ExpressionDocumentSource` interface is not imported either (it is not\n * exported from `@w6w/ui`'s barrel, D-P3): the object literals returned below\n * are structurally identical to it, so TypeScript carries the shape without a\n * type import.\n *\n * ## The gate — mirrors the engine's own, bit-for-bit\n *\n * A document contributes field data **iff**: `doc.format === \"json\"` AND\n * `JSON.parse(doc.content)` succeeds into a plain object, OR\n * `doc.format === \"yaml\"` AND npm `yaml`'s `parse(doc.content)` succeeds into\n * a plain object — where *plain object* means\n * `typeof v === \"object\" && v !== null && !Array.isArray(v)`. This mirrors\n * the engine's own gate (`documentsSeed` /\n * `packages/server/packages/api/run-seed.ts`, read-only, out of scope)\n * bit-for-bit for each format: `format === \"json\"` or `format === \"yaml\"`,\n * then a `try/catch` parse, falling back to the raw content string on either\n * a non-matching format or a throw. Reproduced here so the picker never\n * offers a ref the run scope itself would refuse to resolve\n * (`render_ref_unresolved`) — `text`/`markdown`/`html` documents, and a\n * `json`/`yaml` document whose parse throws or yields a non-plain-object, are\n * excluded.\n *\n * The two parsers are not identical for every input — `@std/yaml` (server,\n * `{ schema: \"core\" }`) and npm `yaml` (here) diverge on tab-indented content\n * and on an unresolvable custom tag (`!!js/function`), both accepted, tested\n * debt (D-3). Every other input, including a plain JSON object (JSON is a\n * subset of YAML), agrees between the two.\n *\n * Field keys are enumerated RAW and UNFILTERED by {@link projectDocumentSources}\n * — arbitrary user-authored JSON keys (which can contain `.`/`{`/`}`/\n * whitespace) reach the modal; `isRefSafeKey` filters them exactly once, at\n * the modal's render site (`ExpressionEditorModal.tsx`), never here\n * (`building-blocks.md`: \"enumerate raw at the source, filter once at the\n * single render site\").\n */\nimport type { Doc } from \"@w6w/sdk\";\nimport { parse as parseYaml } from \"yaml\";\n\n/** One document's contribution to `ExpressionOptions.documents` — structurally\n * identical to `@w6w/ui`'s (unexported) `ExpressionDocumentSource`. */\nexport interface DocumentSource {\n key: string;\n fields?: { key: string }[];\n}\n\n/**\n * `doc`'s parsed content when the gate holds, else `null`. The one place both\n * functions below apply the gate, so they cannot silently disagree on it.\n */\nfunction gatedFields(doc: Doc): Record<string, unknown> | null {\n let parsed: unknown;\n if (doc.format === \"json\") {\n try {\n parsed = JSON.parse(doc.content);\n } catch {\n return null;\n }\n } else if (doc.format === \"yaml\") {\n try {\n parsed = parseYaml(doc.content);\n } catch {\n return null;\n }\n } else {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return null;\n return parsed as Record<string, unknown>;\n}\n\n/**\n * The `ExpressionOptions.documents` array: `{ key }` for every document, plus\n * `fields` (raw, unfiltered top-level keys) when the gate holds AND the\n * parsed object has at least one key. `fields` is OMITTED (not `[]`) both\n * when the gate fails and when it holds but yields zero keys — a consumer\n * must be able to tell \"nothing declared\" from \"declared none\".\n */\nexport function projectDocumentSources(docs: Doc[]): DocumentSource[] {\n return docs.map((d) => {\n const parsed = gatedFields(d);\n if (!parsed) return { key: d.key };\n const keys = Object.keys(parsed);\n return keys.length > 0 ? { key: d.key, fields: keys.map((key) => ({ key })) } : { key: d.key };\n });\n}\n\n/**\n * The `sampleValues` entries the ƒx Result preview substitutes for document\n * refs: `documents.<key>` → the document's raw content, for every document\n * (unconditional, exactly as before this project), PLUS `documents.<key>.<field>`\n * → the field's own parsed value, for the gated set only. Without the second\n * half, every field ref this project newly makes pickable would preview as\n * the empty string (`renderResult` does an exact flat-key lookup).\n */\nexport function documentSampleValues(docs: Doc[]): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const d of docs) {\n out[`documents.${d.key}`] = d.content;\n const parsed = gatedFields(d);\n if (!parsed) continue;\n for (const [key, value] of Object.entries(parsed)) {\n out[`documents.${d.key}.${key}`] = value;\n }\n }\n return out;\n}\n","/**\n * Pure decisions behind the right rail's Settings tool (`src/ui/rail/SettingsTool.tsx`,\n * `id: \"aliases\"`, `title: \"Settings\"` since T3.1.2 — the tool widened past aliases alone\n * into a resource Settings panel: a metadata block and, for Functions and Endpoints, an\n * Export / Edit JSON action row (T3.3.1 — the definition itself no longer renders in the\n * panel, only the two buttons that open it in a modal), alongside the alias list\n * `../lib/alias-rail.ts` already decides). Split out so `node --test` can gate them\n * directly — same reasoning as\n * `alias-rail.ts`'s own header: `node --test` throws `ERR_UNKNOWN_FILE_EXTENSION` on\n * anything reaching the `@w6w/ui` / `Layout.tsx` import graph, and `src/ui/workspace.tsx`\n * sits one hop from that barrel through `Layout.tsx`'s import graph. So this module\n * declares its own structural mirror of the kinds it cares about instead of importing\n * `WorkspaceKind`, and takes only `import type` throughout.\n *\n * T4.1.1 widens this file's scope past the Settings tool itself: `restoreRailState`\n * (A2, `RightRail.tsx`'s persisted-state read path) and `isRowArchived`/`visibleRows`\n * (A6, the three listing pages' \"Show archived\" toggle) are pure decisions with the\n * exact same `node --test`-reachability constraint, so they land here rather than in\n * a new sibling module the contract's `inputs.touch` list didn't ask for.\n */\n\n/** Structural mirror of `WorkspaceCallable[\"kind\"]` (`src/ui/workspace.tsx`) — every kind\n * the rail can have open, not only the two this tool's action-row/metadata sections\n * apply to. */\nexport type RailSettingsKind = \"workflow\" | \"function\" | \"endpoint\" | \"connection\";\n\n/**\n * A4/T3.1.1: which metadata rows the Settings panel shows for this kind. `id` always\n * (every kind the tool is available on carries one). `key` for `function`/`endpoint`\n * (unchanged) AND, since T3.1.1, `workflow` too — `GET /workflows` now carries `key`\n * on every row (`string | null`, D-1: nullable, no backfill), and the panel renders it\n * as an editable control for `function`/`workflow` and the existing read-only `<code>`\n * for `endpoint` (`SettingsTool.tsx` gates that render choice on `ctx.kind` directly,\n * never on this array — an Endpoint's `key` entry here must not be read as \"editable\").\n * `updatedAt` stays `function`/`endpoint`-only: nothing asks for a Workflow Updated row,\n * and adding one would be a second, unrelated rail row. Deliberately never `createdAt`\n * (note 6): neither `GET /functions/:id` nor `GET /endpoints/:id` returns it, so\n * surfacing it would take a server change for one cosmetic field — this function's own\n * absence of a `createdAt` arm is half of that gate, the other half is the negative\n * assertion in the caller's markup.\n */\nexport function metadataFieldsForKind(\n kind: RailSettingsKind,\n): ReadonlyArray<\"id\" | \"key\" | \"updatedAt\"> {\n switch (kind) {\n case \"function\":\n case \"endpoint\":\n return [\"id\", \"key\", \"updatedAt\"];\n case \"workflow\":\n return [\"id\", \"key\"];\n case \"connection\":\n return [\"id\"];\n }\n}\n\n/**\n * A2/A5: the Export / Edit JSON action row exists for `function`/`endpoint` only. A\n * Workflow already has its own read-only Definition card\n * (`pages/WorkflowDetailPage.tsx:371-388`); a Connection has no stored definition shaped\n * like these two to show at all. (T3.3.1: renamed from the panel's earlier JSON-section\n * name — there is no JSON section left in the panel to describe, only the two buttons\n * that open one in a modal.)\n */\nexport function hasDefinitionActions(kind: RailSettingsKind): boolean {\n return kind === \"function\" || kind === \"endpoint\";\n}\n\n/**\n * A1/T3.1.1: does this kind have a version-history browser (the read-only browse list plus\n * Publish and Enable/Disable) in the Settings panel? `true` for `function`/`workflow`/`endpoint`,\n * `false` for `connection` — written as a `switch` naming every one of the four `RailSettingsKind`\n * arms explicitly, with no `default:`, matching {@link specCollectionForKind}'s shape and the\n * reason its own docblock gives (`:69` below — \"every one of the four `RailSettingsKind` arms is\n * named explicitly below\" so a kind can never silently fall through). Deliberately NOT derived\n * from {@link hasDefinitionActions}, which is `function`/`endpoint`-only: History covers Workflow\n * too, so deriving one from the other would silently drop it.\n */\nexport function hasVersionHistory(kind: RailSettingsKind): boolean {\n switch (kind) {\n case \"function\":\n case \"workflow\":\n case \"endpoint\":\n return true;\n case \"connection\":\n return false;\n }\n}\n\n/**\n * A1/T1.3.1: does this kind get a Delete (or, for `workflow`, Archive-then-Delete) affordance at\n * the bottom of the Settings panel? `true` for `function`/`workflow`/`endpoint`, `false` for\n * `connection` — written as a named `switch` naming every one of the four `RailSettingsKind` arms\n * explicitly, with no `default:`, matching {@link hasVersionHistory}'s exact shape (`:72-81` above)\n * for the same reason its own doc comment gives: a kind can never silently fall through. Deliberately\n * NOT derived from {@link hasVersionHistory} even though the two currently agree on every arm — a\n * future kind that gets history but not deletion (or vice versa) must not silently inherit the\n * wrong answer from a sibling predicate.\n */\nexport function hasDelete(kind: RailSettingsKind): boolean {\n switch (kind) {\n case \"function\":\n case \"workflow\":\n case \"endpoint\":\n return true;\n case \"connection\":\n return false;\n }\n}\n\n/**\n * A4: which `/<collection>/:id/spec` route the Export button's `useSpecQuery`\n * (`../repos/spec-export.ts`) must call for this kind — `null` for the two kinds A2's\n * action row never renders on. Kept in lockstep with {@link hasDefinitionActions}\n * (both are `function`/`endpoint`-only) but expressed as its own total function rather\n * than derived from it, so a Function can never be exported through\n * `/endpoints/:id/spec` by a wrong `if`/`else` fallthrough — every one of the four\n * `RailSettingsKind` arms is named explicitly below.\n */\nexport function specCollectionForKind(kind: RailSettingsKind): \"functions\" | \"endpoints\" | null {\n switch (kind) {\n case \"function\":\n return \"functions\";\n case \"endpoint\":\n return \"endpoints\";\n case \"workflow\":\n case \"connection\":\n return null;\n }\n}\n\n/** What A8's `evaluateEdit` needs to know about the row already on screen — deliberately\n * narrower than a whole `FunctionDef`/`EndpointDef`: the two fields a hand-edit must not\n * be allowed to change out from under the row it opened on. */\nexport interface EditStored {\n id: string;\n key: string;\n}\n\n/** A8's total function's result: the parsed body (when parseable and a plain object, even\n * if it goes on to fail arm 2 or 3 — the modal still has something to inspect for the\n * render, just never something Save may submit) plus the one reason Save is refused, or\n * `null` when the edit is allowed through. */\nexport interface EditEvaluation {\n parsed: Record<string, unknown> | null;\n blockedReason: string | null;\n}\n\n/**\n * A8: is this edited text a Save the rail may submit? A total function over the modal's\n * OWN text state — never `JsonEditor`'s `onValidityChange` (note 10: the only browser\n * harness this repo has stubs `JsonEditor` with a callback that is wired but never\n * invoked, so a Save gated on it would look gated and be inert; parsing `text` here is\n * behaviourally identical and fully observable by a page guard).\n *\n * Three refusals, evaluated in order, each named for the near-miss it kills:\n * 1. the text does not parse as JSON, or parses to something that is not a plain object\n * (`null` and an array both fail here, not a dedicated fourth arm — a\n * `FunctionDef`/`EndpointDef` is never legitimately either);\n * 2. `parsed.id !== stored.id` (note 9 — `FunctionsRepo.upsert` selects the row by\n * `definition.id`, so an edited id does not edit this row, it creates or hijacks a\n * different one);\n * 3. `parsed.key !== stored.key` (note 8 — `POST /endpoints` 409s on a changed key while\n * `POST /functions` silently accepts one; locking it here keeps both kinds behaving\n * the same from this one modal).\n */\nexport function evaluateEdit(text: string, stored: EditStored): EditEvaluation {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return { parsed: null, blockedReason: \"Not valid JSON.\" };\n }\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { parsed: null, blockedReason: \"Not valid JSON.\" };\n }\n const parsed = value as Record<string, unknown>;\n if (parsed.id !== stored.id) {\n return { parsed, blockedReason: \"id cannot be changed here.\" };\n }\n if (parsed.key !== stored.key) {\n return { parsed, blockedReason: \"key cannot be changed here.\" };\n }\n return { parsed, blockedReason: null };\n}\n\n/** A7/D-3's total function's result: may the save proceed, and if not, why —\n * rendered verbatim in `WorkflowsPage.tsx`'s existing error/banner idiom. */\nexport interface KeyEditEvaluation {\n allowed: boolean;\n reason: string | null;\n}\n\n/**\n * D-3: is a Workflow save carrying this `key` one `WorkflowsPage.tsx`'s raw-JSON\n * editor may submit? The right rail's Key control (`SettingsTool.tsx`) is the ONLY\n * path allowed to assign or change a workflow's key (see this project's Requirement);\n * this total function is what keeps a hand-edit of the JSON — via the Save button OR\n * auto-save, both of which must fold this in (see `WorkflowsPage.tsx`'s `canSave`) —\n * from doing it silently instead.\n *\n * `loadedKey` is the key `WorkflowsPage.tsx` most recently loaded FROM THE SERVER\n * (its own `loadedKeyRef`, captured at both of its load sites — the initial `editId`\n * effect and `reloadFromServer`). `undefined` means nothing has loaded yet, which\n * refuses unconditionally: there is nothing yet to compare the parsed text against,\n * so allowing the save through would let an unloaded/stale comparison pass by\n * accident. Once loaded, `loadedKey` is `string | null` (P5's unset state, D-1).\n *\n * `parsedKey` is whatever the parsed JSON text's own `key` field currently holds.\n * `undefined` (the field is absent from the text) is treated exactly like an\n * explicit `null` — both mean \"no key\" on the wire, and a definition that dropped\n * the field entirely must be refused exactly like one that changed it, never waved\n * through as \"nothing to compare\".\n */\nexport function workflowKeyEditAllowed(\n loadedKey: string | null | undefined,\n parsedKey: unknown,\n): KeyEditEvaluation {\n if (loadedKey === undefined) {\n return { allowed: false, reason: \"Workflow not loaded yet.\" };\n }\n const normalizedParsed = parsedKey === undefined ? null : parsedKey;\n if (normalizedParsed !== loadedKey) {\n return {\n allowed: false,\n reason: \"key cannot be changed here — use the Settings panel's Key field.\",\n };\n }\n return { allowed: true, reason: null };\n}\n\n/**\n * T4.1.1/A2: the shape actually written to `localStorage` for the right\n * rail's persisted state (`RightRail.tsx`'s `PersistedRail`) — `activeTool`\n * ONLY. `open` is deliberately absent from this interface, not merely\n * unwritten: {@link restoreRailState} below has nothing to read it FROM, so\n * a pre-existing `{\"open\":true,…}` value written before this task cannot\n * reopen the rail even by accident.\n */\nexport interface StoredRailState {\n activeTool: string | null;\n}\n\n/**\n * A2: parses `localStorage`'s raw rail entry into {@link StoredRailState}.\n * Missing/unparsable input, or a non-string `activeTool`, all fall back to\n * `{ activeTool: null }` — the same defensive shape `RightRail.tsx`'s own\n * `readStoredState` used before this task, minus the `open` field entirely.\n * `RightRail.tsx` is the one caller; it combines this result with a hardcoded\n * `open: false` on every read (D-I0-2) — that combination happens there, not\n * here, because `open`'s absence from THIS function's return type is the\n * proof a page guard can pin: there is no `open` member left to misread.\n */\nexport function restoreRailState(raw: string | null): StoredRailState {\n if (!raw) return { activeTool: null };\n try {\n const parsed = JSON.parse(raw) as Partial<Record<string, unknown>>;\n return { activeTool: typeof parsed.activeTool === \"string\" ? parsed.activeTool : null };\n } catch {\n return { activeTool: null };\n }\n}\n\n/**\n * A6: a listing row either Workflow, Function or Endpoint's list carries —\n * whichever archived signal the row's own kind uses. Workflow rows signal\n * archived via the existing `status === \"archived\"` (`WorkflowSummary`);\n * Function/Endpoint rows via the new `archivedAt` column T1.1.1 ships\n * (`string | null`). Both fields optional so one predicate below covers all\n * three wire shapes without a per-kind branch at each listing page's call\n * site.\n */\nexport interface ArchivableRow {\n status?: string;\n archivedAt?: string | null;\n}\n\n/**\n * A6: is this row archived? `status` takes priority when the row carries one\n * (Workflow rows always do) — falls back to `archivedAt` otherwise (Function/\n * Endpoint rows, which have no `status` field at all).\n */\nexport function isRowArchived(row: ArchivableRow): boolean {\n if (row.status !== undefined) return row.status === \"archived\";\n return row.archivedAt != null;\n}\n\n/**\n * A6: which rows a listing page's \"Show archived\" toggle should render.\n * `showArchived` false (the default) drops every archived row; `true`\n * reveals them ALONGSIDE the live ones — an include, never a toggle that\n * hides the rest (the contract's mutation M6: a toggle that hides LIVE rows\n * once ON must fail the \"both a live and an archived row survive together\"\n * case below; M7: defaulting to showing archived rows must fail the\n * toggle-OFF case). One pure function shared by `WorkflowsPage.tsx`,\n * `FunctionsPage.tsx` and `EndpointsPage.tsx` rather than three inline\n * `.filter`s.\n */\nexport function visibleRows<T extends ArchivableRow>(\n rows: readonly T[],\n showArchived: boolean,\n): T[] {\n return showArchived ? rows.slice() : rows.filter((row) => !isRowArchived(row));\n}\n","/**\n * Pure decisions behind the right rail's Error handling tool\n * (`src/ui/rail/SettingsTool.tsx`, D-10) — the third `railTools` entry,\n * rendering `@w6w/ui`'s `NodeConfigForm` for a Function or an Endpoint and\n * persisting `retry` / `onError` / `reroute` onto that resource's own\n * definition. Split out so `node --test` can gate them directly — mirrors\n * `code-rail.ts`'s own reason for existing: `node --test` throws\n * `ERR_UNKNOWN_FILE_EXTENSION` on any `@w6w/ui`-adjacent import, and\n * `src/ui/workspace.tsx` sits one hop from that barrel through `Layout.tsx`'s\n * import graph. So this module declares its own structural mirror of\n * `WorkspaceCallable` instead of importing it — `import type … from\n * \"@w6w/sdk/console\"` is safe and precedented (`src/lib/workflow-poll.ts:15`,\n * `src/lib/tenant-oauth-patch.ts:69`, both unit-tested today).\n */\nimport type { CallableOnError, ErrorReroute, RetryPolicy } from \"@w6w/sdk/console\";\n\n/** Structural mirror of `WorkspaceCallable` (`src/ui/workspace.tsx`) — only\n * the fields this module reads. `onPolicyChange` is the WORKFLOW arm's\n * injected writer (see {@link isAvailable}); the two callable arms have no\n * such member and never read it. */\nexport type SettingsCallable = {\n kind: string;\n id: string;\n onPolicyChange?: (policy: CallablePolicy) => void;\n} | null;\n\n/** The three fields this tool owns on a Function/Endpoint definition —\n * TC2's pinned shape, shared by both `Fn` and `Endpoint`. */\nexport interface CallablePolicy {\n retry?: RetryPolicy;\n onError?: CallableOnError;\n reroute?: ErrorReroute;\n}\n\n/** A definition carrying (at least) the three fields above, plus whatever\n * else `Fn`/`Endpoint` declares — `definitionWithPolicy` preserves every\n * field this type doesn't name. */\nexport type CallableDefinition = CallablePolicy;\n\n/**\n * Is the Error handling tool meaningful for this context?\n *\n * A Function and an Endpoint: always — the panel owns their whole\n * read-modify-write, because nothing else on the page is editing the same\n * definition at the same time.\n *\n * A Workflow: only when the publishing page injects `onPolicyChange` (core\n * Workflow RFC — *Amendment — 2026-08-21: the run-level error handler*). This\n * is not fussiness. The workflow canvas holds the definition as JSON TEXT it\n * owns, and auto-saves it (`settings.autoSave` defaults to ON), so a rail\n * panel doing its own read-modify-write against the server would be racing the\n * editor: whichever wrote last would silently drop the other's edit, and the\n * loser would most often be the rail, since the canvas re-sends its whole\n * buffer on the next keystroke. Injecting the writer instead means the rail\n * edits the SAME buffer the canvas is about to save. A page that does not own\n * that buffer (the run-detail page) publishes no writer, and the tool simply\n * does not appear there.\n *\n * A Connection has no run-level policy at all. `null` (no resource published)\n * fails closed, house style (mirrors `code-rail.ts`'s `isAvailable`).\n */\nexport function isAvailable(ctx: SettingsCallable): boolean {\n if (!ctx) return false;\n if (ctx.kind === \"function\" || ctx.kind === \"endpoint\") return true;\n return ctx.kind === \"workflow\" && typeof ctx.onPolicyChange === \"function\";\n}\n\n/**\n * Read a definition's `{retry, onError, reroute}` into the shape the panel's\n * local editing state starts from. Normalizes the same way\n * `definitionWithPolicy` writes: a stored `onError: \"fail\"` (never written by\n * this tool, but defensive against a hand-edited or older definition) reads\n * back as absent, matching how `NodeConfigForm` already treats `\"fail\"` as\n * its own default.\n */\nexport function policyFromDefinition(def: CallableDefinition): CallablePolicy {\n const policy: CallablePolicy = {};\n if (def.retry) policy.retry = def.retry;\n if (def.onError && def.onError !== \"fail\") policy.onError = def.onError;\n if (def.reroute) policy.reroute = def.reroute;\n return policy;\n}\n\n/**\n * Read-modify-write: apply `policy`'s `{retry, onError, reroute}` onto `def`,\n * preserving every OTHER field untouched (`impl`/`inputs`/`key` on a\n * Function, `target`/`input`/`key` on an Endpoint, …) — the save this tool\n * issues is never a bare `{retry, onError, reroute}` object. A field whose\n * value is the default is OMITTED entirely, not written as `undefined`:\n * `policy.onError === \"fail\"` (or absent) drops the key, matching\n * `NodeConfigForm`'s own \"fail\" -> absent convention for the field it edits\n * in place. Built by destructuring the three fields OUT of `def` and\n * conditionally re-spreading them, rather than `delete`, so the key is\n * genuinely absent from the returned object, not merely `undefined`-valued —\n * `node:assert/strict`'s deep-equal distinguishes the two (this module's own\n * test pins it).\n */\nexport function definitionWithPolicy<T extends CallableDefinition>(\n def: T,\n policy: CallablePolicy,\n): T {\n const { retry: _retry, onError: _onError, reroute: _reroute, ...rest } = def;\n return {\n ...rest,\n ...(policy.retry ? { retry: policy.retry } : {}),\n ...(policy.onError && policy.onError !== \"fail\" ? { onError: policy.onError } : {}),\n ...(policy.reroute ? { reroute: policy.reroute } : {}),\n } as T;\n}\n","/**\n * \"Call from code\" trigger preview (T2.2.1, HITL-2/HITL-4 pinned):\n *\n * > one tab per MANUAL (`@w6w/trigger`) trigger step, in declared order,\n * > labelled `step.displayName ?? step.id`. Webhook/scheduler steps are\n * > excluded — they declare named params, never a generic `fields` array.\n *\n * Pure and testable by design, same shape as `workflow-validity.ts`:\n * `WorkflowDetailPage.tsx`/`WorkflowsPage.tsx` are JSX, which Node 24's\n * type-stripping cannot parse, so nothing in it can be loaded by\n * `node --test`. This module cannot import `@w6w/ui`/`@w6w/ui/flow` either\n * way (`ERR_UNKNOWN_FILE_EXTENSION` — see `workflow-validity.ts`'s docstring).\n * Instead, \"is this step a MANUAL trigger\" and \"read a trigger's declared\n * `fields`\" are **caller-injected** on `TriggerPreviewContext` —\n * `WorkflowsPage.tsx`/`WorkflowDetailPage.tsx` import the real\n * `TRIGGER_APP`/`asFieldDefs` from `@w6w/ui/flow` and pass them in. This file\n * contains no `@w6w/*` app-id string literal.\n *\n * Deliberately narrower than `@w6w/ui/flow`'s own `isTriggerApp`, which also\n * matches `@w6w/webhook`/`@w6w/scheduler` (all three are \"entry nodes\" for the\n * canvas). Those two kinds declare named params, not a generic `fields`\n * array, so they cannot be previewed the same way — the injected predicate a\n * caller supplies here is expected to be the MANUAL-only check\n * (`app === TRIGGER_APP`), not the broader `isTriggerApp`.\n */\n\n/** One field a trigger declares — just enough of `@w6w/ui/flow`'s\n * `TriggerFieldDef` for this preview (structurally compatible, not imported). */\nexport interface TriggerPreviewFieldDef {\n key?: string;\n type?: string;\n required?: boolean;\n default?: unknown;\n}\n\n/** A workflow graph step, just enough of it for this preview. */\nexport interface WorkflowStepLike {\n id: string;\n /** Human-facing step name, when the author set one. Falls back to `id`. */\n displayName?: string;\n uses?: { app?: string; action?: string };\n with?: Record<string, unknown>;\n}\n\n/** A workflow definition, just enough of it for this preview. */\nexport interface WorkflowLike {\n steps?: WorkflowStepLike[];\n}\n\n/**\n * Everything `triggerPreviews` needs that this pure module cannot compute or\n * import itself — see the module docstring for why each field is\n * caller-injected rather than derived in here.\n */\nexport interface TriggerPreviewContext {\n /** Is this step's `uses.app` a MANUAL trigger (`@w6w/trigger`)? Webhook and\n * scheduler steps must answer `false` here even though they are also\n * \"entry nodes\" — they have no generic `fields` array to preview. */\n isManualTrigger: (app: string) => boolean;\n /** `@w6w/ui/flow`'s `asFieldDefs`, injected — reads a step's `with.fields`\n * param value as an array of field definitions. */\n asFieldDefs: (fields: unknown) => TriggerPreviewFieldDef[];\n}\n\n/** One manual trigger's declared fields, ready for the modal's picker. */\nexport interface TriggerPreview {\n id: string;\n /** `step.displayName ?? step.id`. */\n label: string;\n fields: TriggerPreviewFieldDef[];\n}\n\n/**\n * One `TriggerPreview` per manual trigger step in `workflow.steps`, in\n * declared order. Non-manual steps (including webhook/scheduler entry nodes)\n * are excluded. A field with a missing/blank `key` is dropped — mirrors\n * `@w6w/ui/flow`'s `fieldsToParams`, which does the same before turning\n * `TriggerFieldDef[]` into a fillable form.\n */\nexport function triggerPreviews(\n workflow: WorkflowLike,\n ctx: TriggerPreviewContext,\n): TriggerPreview[] {\n const steps = workflow.steps ?? [];\n const previews: TriggerPreview[] = [];\n for (const step of steps) {\n const app = step.uses?.app;\n if (!app || !ctx.isManualTrigger(app)) continue;\n const fields = ctx\n .asFieldDefs(step.with?.fields)\n .filter((f) => typeof f.key === \"string\" && f.key.trim() !== \"\");\n previews.push({ id: step.id, label: step.displayName ?? step.id, fields });\n }\n return previews;\n}\n\n/**\n * A start-payload skeleton for one manual trigger — every declared field at its\n * declared default, so the Run panel opens with the shape the workflow actually\n * expects instead of an empty object the author has to reconstruct by hand.\n *\n * Mirrors `@w6w/ui/flow`'s `seedValues` (which this module cannot import — see\n * the header): an explicit `default` wins; otherwise the empty value for the\n * declared type. Unknown types fall to `\"\"`, matching that function.\n *\n * `undefined` in → `{}`, so a caller can pass a still-loading preview.\n */\nexport function triggerInputSeed(preview: TriggerPreview | undefined): Record<string, unknown> {\n const seed: Record<string, unknown> = {};\n for (const f of preview?.fields ?? []) {\n if (typeof f.key !== \"string\" || f.key.trim() === \"\") continue;\n if (f.default !== undefined) {\n seed[f.key] = f.default;\n continue;\n }\n seed[f.key] = f.type === \"number\" ? 0 : f.type === \"boolean\" ? false : \"\";\n }\n return seed;\n}\n","/**\n * Node/CLI call snippets for a studio resource — \"how do I do this from code?\"\n *\n * Pure string builders over the wrapper contract at `packages/wrappers`\n * (`endpoints.json` + `docs/endpoints.md`). Nothing here fetches, and nothing\n * here invents an operation: every snippet emitted maps to an operation the\n * contract lists as `status: required, serverImplemented: true`, using the exact\n * symbol its `naming.ts` / `naming.cli` field pins. If an operation is not in\n * the contract there is no snippet for it — a copyable example of a method that\n * does not exist is worse than no example.\n *\n * The surface at contract v0.3.0, and what each studio page can therefore show:\n *\n * | Resource | Node | CLI | Python | curl |\n * |-----------|-------------------------------------|------------------------------|--------|------|\n * | Workflow | `client.workflows.run(id, opts?)` | `w6w workflows run <id>` | `client.workflows.run(id, ...)` | `curl … /workflows/{id}/run?wait=true` |\n * | Function | `client.functions.run(name, {payload})` | `w6w functions run <name>` | `client.functions.run(name, payload=...)` | `curl … /functions/{name}/invoke` |\n * | Endpoint | `client.endpoints.run(name, {payload})` | `w6w endpoints run <name>` | `client.endpoints.run(name, payload=...)` | `curl … <server-rendered URL>` |\n * | Connection | `client.run({urn, action, payload})` | `w6w run <urn> --action` | `client.run(urn, action=..., payload=...)` | — |\n * | Var | `client.vars.getByName(name)` | `w6w vars get-by-name <n>` | `client.vars.get_by_name(name)` | — |\n * | Document | `client.documents.getByKey(key)` | `w6w documents get-by-key` | `client.documents.get_by_key(key)` | — |\n *\n * There is a fourth, contract-free arm: a raw-HTTP (`curl`) snippet, for the\n * three kinds a caller reaches through a fixed route — Function and Workflow\n * against the `$W6W_BASE_URL` env placeholder (the same one the node/cli/python\n * arms already tell the reader to export), and Endpoint against the URL the\n * SERVER rendered, handed in on the resource. It maps to no wrapper operation\n * on purpose — the three wrapper arms reach a Function or Endpoint through\n * `run`, which takes a URN and not a URL, so raw HTTP is the only place a\n * literal route (or, for an Endpoint, the id-form / key-form URL toggle) can\n * even be shown. An Endpoint's URL is used VERBATIM: nothing here concatenates\n * a host, a path or a slug onto it. Connection, Var and Document have no\n * fixed single-resource route to curl against, so they carry no `curl` arm.\n *\n * **Functions and Endpoints have their own namespaces** as of `@w6w/sdk` 0.6.0\n * (contract 0.3.0): `functions.run(name, {payload})` and\n * `endpoints.run(name, {payload})`, with the NAME FIRST and the same slot\n * accepting either the resource's key or its `fn_…`/`ep_…` id — the two shapes\n * cannot collide, so nothing is tagged. This module used to emit\n * `client.run({urn: \"fn:send-email\"})`, a kind smuggled into a string because\n * the field was one string; that form is gone.\n *\n * **One form per kind, always.** An earlier version rendered\n * `client.run({urn: alias})` for a resource that carried an alias, which put\n * two different call styles side by side for two Functions. `key` is required\n * on every Function and Endpoint server-side, so the namespace call always\n * works and the alias form was never the only way in. An alias is a SECOND\n * address with its own rail (`alias-rail.ts`); it is not advertised here,\n * because the answer to \"how do I call this Function?\" should not change shape\n * depending on whether someone aliased it. See {@link addressName}.\n *\n * `isUrnAddressable` still gates every arm: an id without its kind prefix is\n * not addressable by `run`, so the snippet is withheld rather than emitting a\n * call that cannot work.\n */\n\nimport type { TriggerPreviewFieldDef } from \"./trigger-preview.ts\";\n\n/**\n * One declared input of a Function or Endpoint, as a snippet needs it.\n *\n * A BARE STRING is treated as REQUIRED. That is the shape this file took before\n * it knew about optionality, when every input rendered active — so a caller that\n * only has keys keeps its existing output rather than silently having every\n * field commented out.\n */\nexport type SnippetInput = string | { key: string; required?: boolean };\n\n/** Normalized, so the renderers below never branch on the union. */\ninterface ResolvedInput {\n key: string;\n required: boolean;\n}\n\n/** What the caller is looking at. Mirrors the four runnable URN arms plus assets. */\nexport type SnippetCallable =\n | { kind: \"workflow\"; id: string; displayName?: string; key?: string; alias?: string }\n | { kind: \"function\"; id: string; key?: string; inputs?: readonly SnippetInput[]; alias?: string }\n /**\n * An Endpoint. `invokeUrl` / `invokeUrlByKey` are the two SERVER-rendered\n * forms of its public address, passed straight through from the endpoints\n * envelope; `urlForm` is which of them the page currently has selected, so a\n * raw-HTTP sample follows the toggle the reader can see. All three are\n * optional — an Endpoint with no URL in hand simply gets no HTTP snippet.\n * `inputs` are the target's input parameter keys, resolved from the Function\n * or Workflow the Endpoint dispatches to.\n */\n | {\n kind: \"endpoint\";\n id: string;\n key?: string;\n invokeUrl?: string;\n invokeUrlByKey?: string;\n urlForm?: \"id\" | \"key\";\n alias?: string;\n inputs?: readonly SnippetInput[];\n }\n /** One app action, invoked through a connection — the `conn_` URN arm. */\n | { kind: \"connection\"; id: string; action: string; params?: string[] }\n | { kind: \"var\"; name: string }\n | { kind: \"document\"; key: string };\n\nexport interface Snippet {\n /** Runnable TypeScript against `@w6w/sdk`. */\n node: string;\n /** A single `w6w …` invocation. */\n cli: string;\n /** Runnable Python against `w6w` (PyPI). */\n python: string;\n /**\n * A raw-HTTP (`curl`) call against the resource's own public URL — OPTIONAL,\n * and emitted only where such a URL exists and was handed in (today: an\n * Endpoint). Optional rather than required so the other five `case` arms of\n * {@link buildSnippet} are untouched, and so the tab strip can render only\n * the tabs a built snippet actually carries.\n */\n curl?: string;\n /** The contract operation this maps to, shown so the snippet is checkable. */\n operation: string;\n}\n\n/**\n * The URN prefixes `POST /run` resolves. Kept as data rather than inlined so\n * the gate below and the docs above cannot drift apart.\n */\nconst RUNNABLE_PREFIXES = [\"conn_\", \"fn_\", \"wf_\", \"ep_\"] as const;\n\n/**\n * Can this id be passed to `client.run({urn})` at all?\n *\n * Ids are host-issued and carry a kind prefix (rfcs/function.md §id — \"host-issued\n * opaque id (`fn_…`)\"), but the create routes do not *enforce* it, so a\n * hand-authored id can reach the database without one. Such a resource is\n * reachable through the studio and through its own `/invoke` route, but NOT\n * through the URN operation the wrappers expose — and a snippet is a promise\n * that the code in it runs.\n */\nexport function isUrnAddressable(id: string): boolean {\n return RUNNABLE_PREFIXES.some((p) => id.startsWith(p));\n}\n\n/**\n * The three kinds `POST /run` addresses by URN and that can carry an alias.\n */\ntype AddressableCallable = Extract<SnippetCallable, { kind: \"workflow\" | \"function\" | \"endpoint\" }>;\n\n/**\n * The name a snippet addresses a resource by: its own `key`, falling back to\n * the opaque id when it somehow has none.\n *\n * ONE FORM, ALWAYS — `functions.run(name)` / `endpoints.run(name)`. An earlier\n * version branched to `client.run({urn: alias})` when the resource carried an\n * alias, which rendered two different call styles for two Functions side by\n * side. That inconsistency bought nothing: `key` is REQUIRED on every Function\n * and Endpoint server-side (`admin/functions.ts`: \"`key` is required\"), so the\n * namespace call always works and the alias form was never the only way in.\n *\n * An alias is a SECOND address, not a substitute for the first, and it has its\n * own rail (`alias-rail.ts`) on the page where it belongs. It is deliberately\n * not advertised here: this snippet answers \"how do I call this Function?\",\n * and the answer should not change shape depending on whether someone happened\n * to alias it.\n *\n * `key` is optional on the type rather than on the wire — a row that predates\n * the requirement can still reach the studio — so the id fallback stays.\n */\nfunction addressName(resource: AddressableCallable): string {\n const key = (resource as { key?: string }).key?.trim();\n return key && key.length > 0 ? key : resource.id;\n}\n\n/** Single-quoted shell literal — `'` closed, escaped, reopened. */\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\\\\''`)}'`;\n}\n\n/**\n * Past this many characters a one-line command is harder to read than a\n * continued one. Chosen so the common `w6w run <urn> --action <a>` stays on one\n * line and only a real payload pushes it over.\n */\nconst CLI_WRAP_AT = 72;\n\n/**\n * Assemble a CLI command, breaking it across lines with `\\` when it is long.\n *\n * A single-line `w6w run conn_… --action … --payload '{\"a\":\"<a>\",\"b\":\"<b>\"}'`\n * runs off the edge of the panel, so the reader scrolls sideways to find out\n * what the flags even are. Continued, each flag is its own line and the shape\n * of the call is visible at a glance:\n *\n * w6w run conn_c19f4db6 \\\n * --action message-post \\\n * --payload '{\"channel\":\"<channel>\"}'\n *\n * `\\`-newline is the POSIX continuation, so the wrapped form pastes into\n * bash/zsh **and copies as one command** — the text is identical to what the\n * shell sees. (It is not `cmd.exe` syntax; the snippets already assume a POSIX\n * shell for their single-quoting.)\n *\n * Short commands are left alone: breaking `w6w vars get-by-name x` across two\n * lines makes it less readable, not more.\n *\n * @param head the command and its positional argument(s), never split\n * @param flags one `--flag value` (or bare `--flag`) per entry\n */\nfunction cliCommand(head: string, ...flags: string[]): string {\n const parts = [head, ...flags].filter((p) => p.length > 0);\n const oneLine = parts.join(\" \");\n if (flags.length === 0 || oneLine.length <= CLI_WRAP_AT) return oneLine;\n return parts.join(\" \\\\\\n \");\n}\n\n/** Normalize the caller's input list. A bare key is required — see {@link SnippetInput}. */\nfunction resolveInputs(inputs: readonly SnippetInput[] | undefined): ResolvedInput[] {\n if (!inputs || inputs.length === 0) return [];\n return inputs\n .map((i) =>\n typeof i === \"string\"\n ? { key: i, required: true }\n : {\n key: i.key,\n // Only an explicit `true` is required — an undeclared flag means the\n // Function did not mark it, which is exactly what optional means.\n required: i.required === true,\n },\n )\n .filter((i) => typeof i.key === \"string\" && i.key.trim() !== \"\");\n}\n\n/**\n * A sample payload for a Function's declared inputs, so the snippet shows the\n * shape rather than an empty object the reader has to go and look up.\n * Values are placeholders — this is an example, not a saved request.\n *\n * `requiredOnly` is for the comment-less lanes (JSON has no comments), which\n * carry the required fields and name the optional ones in trailing shell\n * comments instead — the same D-4 split the workflow arm already makes.\n */\nfunction samplePayload(\n inputs: readonly SnippetInput[] | undefined,\n requiredOnly = false,\n): Record<string, string> {\n const resolved = resolveInputs(inputs);\n const used = requiredOnly ? resolved.filter((i) => i.required) : resolved;\n return Object.fromEntries(used.map((i) => [i.key, `<${i.key}>`]));\n}\n\n/**\n * The payload object rendered as SOURCE, with optional inputs commented out —\n * the same active/commented rule {@link nodeInputBlock} applies to a trigger's\n * fields, so both halves of this file read alike.\n *\n * EVERY line ends with a comma, active or commented. A JS object literal\n * tolerates the trailing one, and without it uncommenting the last optional\n * field would leave the line above it without a separator — a paste that no\n * longer parses, produced by doing exactly what the comment invites.\n */\nfunction payloadSource(\n inputs: readonly SnippetInput[] | undefined,\n opts: { indent: string; comment: string; compact?: boolean },\n): string {\n const resolved = resolveInputs(inputs);\n if (resolved.length === 0) return \"{}\";\n // Python's payload is a one-liner today, and stays one when there is nothing\n // to comment: the multi-line form exists to carry the `#` lines, so growing\n // it for a Function whose inputs are all required would be churn in every\n // snippet to serve the minority that needs it.\n if (opts.compact && resolved.every((i) => i.required)) {\n return JSON.stringify(Object.fromEntries(resolved.map((i) => [i.key, `<${i.key}>`])));\n }\n const lines = resolved.map(({ key, required }) => {\n const member = `${JSON.stringify(key)}: ${JSON.stringify(`<${key}>`)},`;\n return required ? `${opts.indent} ${member}` : `${opts.indent} ${opts.comment} ${member}`;\n });\n return `{\\n${lines.join(\"\\n\")}\\n${opts.indent}}`;\n}\n\n/**\n * Trailing `# optional: <key>` lines for the lanes that cannot carry a comment\n * INSIDE the payload (CLI and curl both pass JSON). Appended after the command,\n * and none of them ends with a backslash, so the block still pastes and runs as\n * one command. Mirrors `cliWorkflowCommand`/`curlWorkflowCommand`.\n */\nfunction optionalNotes(inputs: readonly SnippetInput[] | undefined): string {\n return resolveInputs(inputs)\n .filter((i) => !i.required)\n .map((i) => `\\n# optional: ${i.key}`)\n .join(\"\");\n}\n\n/**\n * A trigger field with no declared/blank `key` is dropped — mirrors\n * `trigger-preview.ts`'s own `triggerPreviews()` (and `@w6w/ui/flow`'s\n * `fieldsToParams`), which do the same before turning field defs into\n * anything fillable. Declared order is preserved.\n */\nfunction usableTriggerFields(\n fields: readonly TriggerPreviewFieldDef[] | undefined,\n): TriggerPreviewFieldDef[] {\n if (!fields) return [];\n return fields.filter((f) => typeof f.key === \"string\" && f.key.trim() !== \"\");\n}\n\n/**\n * The D-3 placeholder VALUE for a trigger field's declared `type`. The domain\n * is closed at four values — `trigger-fields.ts`'s `fieldWidget()` collapses\n * anything else to `\"string\"` — so this mirrors that collapse rather than\n * re-deriving it. The `\"<key>\"` form mirrors `samplePayload()`'s own\n * convention, so both arms of this file stay idiomatic.\n */\nfunction fieldPlaceholderValue(\n type: string | undefined,\n key: string,\n): string | number | boolean | Record<string, never> {\n if (type === \"number\") return 0;\n if (type === \"boolean\") return false;\n if (type === \"json\") return {};\n return `<${key}>`;\n}\n\n/**\n * The placeholder rendered as SOURCE CODE for one lane. Only the boolean\n * literal differs between Python (`False`) and Node/JSON (`false`) — a\n * shared `JSON.stringify` across all three lanes would emit `false` into\n * Python and raise `NameError` the moment the pasted snippet runs, which is\n * why this branches on `python` rather than reusing one formatter.\n */\nfunction fieldSourceLiteral(type: string | undefined, key: string, python: boolean): string {\n const value = fieldPlaceholderValue(type, key);\n if (typeof value === \"boolean\") return python ? \"False\" : \"false\";\n return JSON.stringify(value);\n}\n\n/**\n * The trigger's `input` object rendered into the Node call — required fields\n * active, optional fields commented out with `//` (D-3/D-4). `\"\"` when there\n * is nothing to show, so the caller can splice it straight after `wait: true,`\n * without leaving a dangling empty block.\n */\nfunction nodeInputBlock(fields: readonly TriggerPreviewFieldDef[]): string {\n if (fields.length === 0) return \"\";\n const lines = fields.map((f) => {\n // A field key is free text (`packages/ui/src/flow-types.ts:340`, no\n // validation) — `first-name`, `2fa`, `api key` are all reachable. A bare\n // object member (`first-name: ...`) is not valid TypeScript; quoting the\n // key with `JSON.stringify` (the same shape `:311`'s payload already\n // uses) is correct for every key by construction, so nothing here has to\n // decide what counts as a \"safe\" identifier.\n const member = `${JSON.stringify(f.key)}: ${fieldSourceLiteral(f.type, f.key as string, false)},`;\n return f.required === true ? ` ${member}` : ` // ${member}`;\n });\n return `\n input: {\n${lines.join(\"\\n\")}\n },`;\n}\n\n/**\n * The whole `client.workflows.run(...)` call expression for Python — not just\n * the `input=` block, because the no-fields case keeps the existing\n * single-line call rather than growing an empty `input={}`. Same active/\n * commented rule as `nodeInputBlock()`, `#` in place of `//`.\n */\nfunction pythonWorkflowCall(id: string, fields: readonly TriggerPreviewFieldDef[]): string {\n const idLiteral = JSON.stringify(id);\n if (fields.length === 0) return `client.workflows.run(${idLiteral}, wait=True)`;\n const lines = fields.map((f) => {\n const member = `\"${f.key}\": ${fieldSourceLiteral(f.type, f.key as string, true)},`;\n return f.required === true ? ` ${member}` : ` # ${member}`;\n });\n return `client.workflows.run(\n ${idLiteral},\n wait=True,\n input={\n${lines.join(\"\\n\")}\n },\n)`;\n}\n\n/**\n * The CLI arm of the same rule (D-4): JSON admits no comments, so\n * `--input '<json>'` carries the REQUIRED fields only, and each optional\n * field's key is instead named in a trailing `#` shell-comment line. Those\n * lines are appended after `cliCommand()` returns and none of them ends\n * with `\\`, so the whole block — command plus comments — still pastes and\n * runs as one command.\n */\nfunction cliWorkflowCommand(id: string, fields: readonly TriggerPreviewFieldDef[]): string {\n if (fields.length === 0) return cliCommand(`w6w workflows run ${id}`, \"--wait\");\n const required = fields.filter((f) => f.required === true);\n const optional = fields.filter((f) => f.required !== true);\n const payload = Object.fromEntries(\n required.map((f) => [f.key as string, fieldPlaceholderValue(f.type, f.key as string)]),\n );\n let cmd = cliCommand(\n `w6w workflows run ${id}`,\n \"--wait\",\n `--input ${shellQuote(JSON.stringify(payload))}`,\n );\n for (const f of optional) {\n cmd += `\\n# optional: ${f.key} (${f.type ?? \"string\"})`;\n }\n return cmd;\n}\n\n/**\n * The lines every Node snippet opens with. `extra` names any additional symbol\n * the body uses — the import list has to be complete or the snippet does not\n * compile when pasted, which is the one thing a copyable example must not do.\n */\nfunction nodePreamble(...extra: string[]): string {\n const symbols = [\"W6WClient\", ...extra].join(\", \");\n return `import { ${symbols} } from \"@w6w/sdk\";\n\n// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.\nconst client = new W6WClient();`;\n}\n\n/**\n * The lines every Python snippet opens with. Mirrors `nodePreamble()`:\n * `extra` names any additional symbol the body uses (a discriminator\n * free-function), and the import list has to be complete or the snippet does\n * not run when pasted.\n */\nfunction pythonPreamble(...extra: string[]): string {\n const symbols = [\"Client\", ...extra].join(\", \");\n return `from w6w import ${symbols}\n\n# Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.\nclient = Client()`;\n}\n\n/**\n * The two header lines and the `-d` line every curl arm shares — the \"one\n * body builder, not three\" the three curl arms below are built on. `urlToken`\n * is the URL already rendered as a shell token: `\"$W6W_BASE_URL/…\"`\n * double-quoted so the env var expands (the function/workflow arms), or\n * `shellQuote`d (the endpoint arm, whose URL is a server-rendered literal\n * that may carry an operator-typed `'`). The auth header is DOUBLE-quoted so\n * `$W6W_TOKEN` expands on paste; `content-type` keeps single quotes (nothing\n * in it expands); `-d`'s JSON body is always `shellQuote`d — double-quoting\n * it would let the shell eat its own `\"` characters.\n */\nfunction curlBody(urlToken: string, data: unknown): string {\n return `curl -X POST ${urlToken} \\\\\n -H \"authorization: Bearer $W6W_TOKEN\" \\\\\n -H 'content-type: application/json' \\\\\n -d ${shellQuote(JSON.stringify(data))}`;\n}\n\n/**\n * A raw-HTTP call against a URL the SERVER rendered (the Endpoint arm).\n *\n * `url` is spliced in verbatim (through the same `shellQuote` every other shell\n * literal in this file uses) — this function has no notion of a host, a path, an\n * account or a key, and must never grow one: the whole point of the id/key\n * toggle is that both strings arrive fully formed from the server.\n * `payload` is the optional data payload to send with the request.\n */\nfunction curlCommand(url: string, payload?: Record<string, string>): string {\n return curlBody(shellQuote(url), payload ?? {});\n}\n\n/**\n * The name-addressed arm: `POST $W6W_BASE_URL/{group}/{name}/invoke`.\n *\n * `bodyKey` is a parameter because the wire is inconsistent where the SDK is\n * not — a Function takes `inputs`, an Endpoint takes `input`. The wrappers\n * spell both `payload`; raw HTTP cannot, so the caller passes the real one and\n * this helper never guesses.\n *\n * `name` is percent-encoded: it lands in a URL path, and a key that predates\n * the kebab-slug grammar may still contain something that needs escaping.\n */\nfunction curlInvokeCommand(\n group: \"functions\" | \"endpoints\",\n name: string,\n bodyKey: \"inputs\" | \"input\",\n payload: Record<string, string>,\n): string {\n const url = `\"$W6W_BASE_URL/${group}/${encodeURIComponent(name)}/invoke\"`;\n return curlBody(url, { [bodyKey]: payload });\n}\n\n/**\n * The Workflow arm: `POST /workflows/{id}/run?wait=true` — same route as the\n * node/cli/python lanes' `wait: true` / `--wait`. Mirrors `cliWorkflowCommand`\n * (D-3/D-4): required trigger fields are active JSON, optional ones are named\n * in a trailing `#` comment line each (JSON admits no comments), and a\n * trigger with no usable fields emits a bare `{}` body and no trailer.\n */\nfunction curlWorkflowCommand(id: string, fields: readonly TriggerPreviewFieldDef[]): string {\n const url = `\"$W6W_BASE_URL/workflows/${id}/run?wait=true\"`;\n if (fields.length === 0) return curlBody(url, {});\n const required = fields.filter((f) => f.required === true);\n const optional = fields.filter((f) => f.required !== true);\n const payload = Object.fromEntries(\n required.map((f) => [f.key as string, fieldPlaceholderValue(f.type, f.key as string)]),\n );\n let cmd = curlBody(url, { input: payload });\n for (const f of optional) {\n cmd += `\\n# optional: ${f.key} (${f.type ?? \"string\"})`;\n }\n return cmd;\n}\n\n/**\n * Build the Node + CLI snippet for one resource, or `null` when the contract\n * has no operation for it (today: a function or endpoint whose id carries no\n * runnable prefix).\n */\nexport function buildSnippet(\n resource: SnippetCallable,\n triggerFields?: readonly TriggerPreviewFieldDef[],\n): Snippet | null {\n switch (resource.kind) {\n case \"workflow\": {\n if (!isUrnAddressable(resource.id)) return null;\n const name = addressName(resource);\n const fields = usableTriggerFields(triggerFields);\n return {\n operation: \"workflows.run — POST /workflows/{idOrKey}/run\",\n node: `${nodePreamble()}\n\n// \\`wait: true\\` blocks until the run reaches a terminal state.\n// Omit it and you get \\`{ runId, status: \"queued\" }\\` back immediately.\nconst result = await client.workflows.run(${JSON.stringify(name)}, {\n wait: true,${nodeInputBlock(fields)}\n});\n\nconsole.log(result.status, result.runId);`,\n cli: cliWorkflowCommand(name, fields),\n python: `${pythonPreamble()}\n\n# \\`wait=True\\` blocks until the run reaches a terminal state.\n# Omit it and you get \\`WorkflowRunResult(status=\"queued\", ...)\\` back immediately.\nresult = ${pythonWorkflowCall(name, fields)}\n\nprint(result.status, result.runId)`,\n curl: curlWorkflowCommand(name, fields),\n };\n }\n\n case \"function\": {\n if (!isUrnAddressable(resource.id)) return null;\n const name = addressName(resource);\n // JSON carries no comments, so the CLI/curl lanes take the REQUIRED\n // inputs and name the optional ones underneath; Node and Python render\n // every input and comment the optional ones out in place.\n const payload = samplePayload(resource.inputs, true);\n const payloadJson = JSON.stringify(payload);\n const notes = optionalNotes(resource.inputs);\n const payloadBlock = payloadSource(resource.inputs, { indent: \" \", comment: \"//\" });\n const pythonPayload = payloadSource(resource.inputs, {\n indent: \"\",\n comment: \"#\",\n compact: true,\n });\n return {\n operation: \"functions.run — POST /functions/{idOrKey}/invoke\",\n node: `${nodePreamble()}\n\n// The name is the first argument, and it may be the Function's key or its\n// \\`fn_…\\` id — one slot takes either. Returns the OUTPUT directly: the kind is\n// settled by the method, so there is no envelope to narrow.\nconst output = await client.functions.run(${JSON.stringify(name)}, {\n payload: ${payloadBlock},\n});\n\nconsole.log(output);`,\n cli:\n cliCommand(`w6w functions run ${name}`, `--payload ${shellQuote(payloadJson)}`) + notes,\n python: `${pythonPreamble()}\n\n# The name is the first argument — the Function's key or its \\`fn_…\\` id.\noutput = client.functions.run(${JSON.stringify(name)}, payload=${pythonPayload})\n\nprint(output)`,\n curl: curlInvokeCommand(\"functions\", name, \"inputs\", payload) + notes,\n };\n }\n\n case \"endpoint\": {\n if (!isUrnAddressable(resource.id)) return null;\n // Which of the two server-rendered URLs the raw-HTTP arm shows. The\n // absence of a URL altogether means no `curl` snippet at all, rather than\n // a plausible-looking one built here.\n const httpUrl =\n resource.urlForm === \"key\" && resource.invokeUrlByKey\n ? resource.invokeUrlByKey\n : resource.invokeUrl;\n const name = addressName(resource);\n const payload = samplePayload(resource.inputs, true);\n const payloadJson = JSON.stringify(payload);\n const notes = optionalNotes(resource.inputs);\n const payloadBlock = payloadSource(resource.inputs, { indent: \" \", comment: \"//\" });\n const pythonPayload = payloadSource(resource.inputs, {\n indent: \"\",\n comment: \"#\",\n compact: true,\n });\n return {\n operation: \"endpoints.run — POST /endpoints/{idOrKey}/invoke\",\n node: `${nodePreamble()}\n\n// The name is the first argument — the Endpoint's key or its \\`ep_…\\` id. Unlike\n// \\`functions.run\\` this returns the ENVELOPE: an Endpoint dispatches to an app\n// action, a Function or a Workflow, and only \\`kind\\` says which answered.\nconst envelope = await client.endpoints.run(${JSON.stringify(name)}, {\n payload: ${payloadBlock},\n});\n\nconsole.log(envelope.kind, envelope);`,\n cli:\n cliCommand(`w6w endpoints run ${name}`, `--payload ${shellQuote(payloadJson)}`) + notes,\n python: `${pythonPreamble()}\n\n# The name is the first argument — the Endpoint's key or its \\`ep_…\\` id.\nenvelope = client.endpoints.run(${JSON.stringify(name)}, payload=${pythonPayload})\n\nprint(envelope[\"kind\"], envelope)`,\n ...(typeof httpUrl === \"string\" && httpUrl !== \"\"\n ? { curl: curlCommand(httpUrl, payload) + notes }\n : {}),\n };\n }\n\n case \"connection\": {\n if (!isUrnAddressable(resource.id)) return null;\n const payload = samplePayload(resource.params);\n return {\n operation: \"run — POST /run\",\n node: `${nodePreamble(\"isActionRun\")}\n\n// An app action runs through the CONNECTION that authenticates it, so the URN\n// is the connection id and \\`action\\` names the action on its app. This is the\n// one arm where \\`action\\` is required — a workflow, function or endpoint URN\n// has no action to name.\nconst envelope = await client.run({\n urn: ${JSON.stringify(resource.id)},\n action: ${JSON.stringify(resource.action)},\n payload: ${JSON.stringify(payload, null, 2).replaceAll(\"\\n\", \"\\n \")},\n});\n\nif (isActionRun(envelope)) console.log(envelope.value);`,\n cli: cliCommand(\n `w6w run ${resource.id}`,\n `--action ${resource.action}`,\n `--payload ${shellQuote(JSON.stringify(payload))}`,\n ),\n python: `${pythonPreamble(\"is_action_run\")}\n\n# An app action runs through the CONNECTION that authenticates it, so the URN\n# is the connection id and \\`action\\` names the action on its app. This is the\n# one arm where \\`action\\` is required — a workflow, function or endpoint URN\n# has no action to name.\nenvelope = client.run(\n ${JSON.stringify(resource.id)},\n action=${JSON.stringify(resource.action)},\n payload=${JSON.stringify(payload)},\n)\n\nif is_action_run(envelope):\n print(envelope[\"value\"])`,\n };\n }\n\n case \"var\":\n return {\n operation: \"vars.getByName — GET /vars/by-name/{name}\",\n node: `${nodePreamble()}\n\nconst variable = await client.vars.getByName(${JSON.stringify(resource.name)});\nconsole.log(variable.value);`,\n cli: `w6w vars get-by-name ${resource.name}`,\n python: `${pythonPreamble()}\n\nvariable = client.vars.get_by_name(${JSON.stringify(resource.name)})\nprint(variable.value)`,\n };\n\n case \"document\":\n return {\n operation: \"documents.getByKey — GET /documents/by-key/{key}\",\n node: `${nodePreamble()}\n\nconst doc = await client.documents.getByKey(${JSON.stringify(resource.key)});\nconsole.log(doc.content);`,\n cli: `w6w documents get-by-key ${shellQuote(resource.key)}`,\n python: `${pythonPreamble()}\n\ndoc = client.documents.get_by_key(${JSON.stringify(resource.key)})\nprint(doc.content)`,\n };\n }\n}\n\n/** Why no snippet exists, phrased for the reader rather than for a log. */\nexport function unavailableReason(resource: SnippetCallable): string {\n if (\n (resource.kind === \"function\" ||\n resource.kind === \"endpoint\" ||\n resource.kind === \"workflow\") &&\n !isUrnAddressable(resource.id)\n ) {\n return `This ${resource.kind}'s id (${resource.id}) has no \\`${\n resource.kind === \"workflow\" ? \"wf_\" : resource.kind === \"function\" ? \"fn_\" : \"ep_\"\n }\\` prefix, so it cannot be addressed by URN. The SDK and CLI reach ${resource.kind}s through \\`run\\`, which resolves a URN by that prefix — re-create it with a host-issued id to call it from code.`;\n }\n return \"The client libraries do not expose an operation for this yet.\";\n}\n","/**\n * Slug rules — the ONE place in `studio/src` that owns one.\n *\n * Two rules live here and they are deliberately NOT the same rule:\n *\n * · `slugify()` turns a human display name into a machine key. It is the\n * fallback the Endpoint and Function editors use when the operator leaves\n * `key` blank, and it is permissive on purpose: whatever it returns is a\n * legal resource key, digits-first and two characters included.\n * · `ACCOUNT_SLUG_RE` / `isValidAccountSlug()` decide whether a string is a\n * legal ACCOUNT slug — the account segment a key-form invoke URL is\n * addressed by. That rule is stricter: it must start with a letter and run to\n * at least three characters, so `2024-team` and `ab` are both perfectly good\n * keys and both invalid account slugs.\n *\n * The regex is exported rather than re-typed by each caller. A second copy is\n * exactly how a form comes to accept a value the server rejects, so the literal\n * appears in this file and nowhere else in `src/`.\n *\n * Why `src/lib` and why this module imports nothing: `src/lib/*.ts` is the only\n * place studio's `node --test` suite can reach. A rule living inside a `.tsx`\n * page cannot be unit-tested at all (Node's type-stripping does not parse JSX),\n * and a `src/lib` module that imports `@w6w/ui` throws\n * `ERR_UNKNOWN_FILE_EXTENSION` under the same runner because the barrel\n * re-exports `.tsx`. Same constraint documented at\n * `src/lib/workflow-validity.ts:11-20`.\n */\n\n/** Kebab-case a display name into a machine key (the fallback when key is blank). */\nexport function slugify(s: string): string {\n return s\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\n/**\n * A legal account slug: lowercase, opens with a LETTER, then two or more\n * letters/digits/hyphens — three characters minimum.\n *\n * Note this is NOT the server's `tenants.ts` `SLUG_RE`\n * (`/^[a-z0-9][a-z0-9_-]*$/`), which governs tenant ids and is a different,\n * more permissive rule. Do not merge the two.\n */\nexport const ACCOUNT_SLUG_RE = /^[a-z][a-z0-9-]{2,}$/;\n\n/** Does `s` satisfy {@link ACCOUNT_SLUG_RE}? */\nexport function isValidAccountSlug(s: string): boolean {\n return ACCOUNT_SLUG_RE.test(s);\n}\n\n/**\n * A legal Endpoint `key` — mirrors the server's rule VERBATIM, not\n * {@link ACCOUNT_SLUG_RE} above: that one is `{2,}` with no 39-character cap\n * and encodes neither the `--` rule nor the trailing-`-` rule, so a form that\n * validated a key with it would accept a value the server rejects.\n *\n * Source of truth: `packages/server/packages/bll/accounts.ts:72`\n * (`ACCOUNT_SLUG_RE = /^[a-z][a-z0-9-]{2,38}$/`) + `:216-218` (`isAccountSlug`),\n * reached from `packages/server/packages/api/invoke-address.ts:55-57`\n * (`isEndpointKey = isAccountSlug`). There is no reserved-word check on an\n * Endpoint key server-side — `isAccountSlug` only, never\n * `RESERVED_ACCOUNT_SLUGS` — so none is added here either.\n */\nexport function isEndpointKey(s: string): boolean {\n return /^[a-z][a-z0-9-]{2,38}$/.test(s) && !s.includes(\"--\") && !s.endsWith(\"-\");\n}\n\n/**\n * Filters a keystroke into a key input down to what {@link isEndpointKey}'s\n * grammar can ever accept: lowercase letters, digits, hyphens — nothing\n * else, capped at the grammar's own 39-character ceiling. A space or any\n * other disallowed character is dropped outright rather than folded into a\n * `-` ({@link slugify}'s job, for the one-time displayName-to-key fallback —\n * this is a LIVE filter on a field the operator is typing directly into, so\n * silently substituting a different character would be its own surprise).\n * Positional rules the grammar also enforces (must START with a letter, no\n * `--`, no trailing `-`) are left to {@link isEndpointKey} at Save time —\n * blocking those mid-keystroke would refuse a caller who is one keystroke\n * away from a valid value (e.g. typing `\"2\"` before backspacing to start\n * over).\n */\nexport function filterKeyInput(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, \"\")\n .slice(0, 39);\n}\n"],"names":["stepFailure","step","ctx","uses","params","values","stepValid","workflowValid","workflow","invalidReason","failure","VARIABLE_TYPES","readVariables","raw","out","entry","e","row","variablesForSave","rows","r","duplicateKeyIndexes","seen","varsRailFor","index","projectVars","k","isExprDefault","v","runFormFields","fields","computed","readWorkflowStatus","status","readSettings","settings","s","writeSetting","key","value","next","isAvailable","toSnippetCallable","parseImportPaste","text","expectedKind","parsed","found","errorHandlerSelfDecision","resource","target","hasAdapter","gatedFields","doc","parseYaml","projectDocumentSources","docs","d","keys","documentSampleValues","metadataFieldsForKind","kind","hasDefinitionActions","hasVersionHistory","hasDelete","specCollectionForKind","evaluateEdit","stored","workflowKeyEditAllowed","loadedKey","parsedKey","restoreRailState","isRowArchived","visibleRows","showArchived","policyFromDefinition","def","policy","definitionWithPolicy","_retry","_onError","_reroute","rest","triggerPreviews","steps","previews","app","_a","_b","f","triggerInputSeed","preview","seed","RUNNABLE_PREFIXES","isUrnAddressable","id","p","addressName","shellQuote","CLI_WRAP_AT","cliCommand","head","flags","parts","oneLine","resolveInputs","inputs","i","samplePayload","requiredOnly","resolved","used","payloadSource","opts","required","member","optionalNotes","usableTriggerFields","fieldPlaceholderValue","type","fieldSourceLiteral","python","nodeInputBlock","pythonWorkflowCall","idLiteral","lines","cliWorkflowCommand","optional","payload","cmd","nodePreamble","extra","pythonPreamble","curlBody","urlToken","data","curlCommand","url","curlInvokeCommand","group","name","bodyKey","curlWorkflowCommand","buildSnippet","triggerFields","payloadJson","notes","payloadBlock","pythonPayload","httpUrl","unavailableReason","slugify","ACCOUNT_SLUG_RE","isValidAccountSlug","isEndpointKey","filterKeyInput"],"mappings":"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"}
|