@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.
Files changed (102) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +166 -2
  3. package/dist/W6WEmbedProvider.d.ts +29 -0
  4. package/dist/chrome/CallFromCodeButton.d.ts +155 -0
  5. package/dist/chrome/CallableSettingsModal.d.ts +17 -0
  6. package/dist/chrome/ConfirmModal.d.ts +20 -0
  7. package/dist/chrome/DangerZone.d.ts +19 -0
  8. package/dist/chrome/ExecutionProfileHeader.d.ts +69 -0
  9. package/dist/chrome/HistoryButton.d.ts +8 -0
  10. package/dist/chrome/HistoryModal.d.ts +9 -0
  11. package/dist/chrome/HistoryView.d.ts +15 -0
  12. package/dist/chrome/ImportSpecModal.d.ts +40 -0
  13. package/dist/chrome/JsonToggle.d.ts +51 -0
  14. package/dist/chrome/Modal.d.ts +20 -0
  15. package/dist/chrome/RightRail.d.ts +24 -0
  16. package/dist/chrome/TagEditor.d.ts +23 -0
  17. package/dist/chrome/VersionHistoryModal.d.ts +38 -0
  18. package/dist/chrome/history-open-run.d.ts +7 -0
  19. package/dist/chrome/index.d.ts +36 -0
  20. package/dist/chrome/workspace.d.ts +67 -0
  21. package/dist/client-context-CX61Bgw-.js +16 -0
  22. package/dist/client-context-CX61Bgw-.js.map +1 -0
  23. package/dist/draft/autosave-flush.d.ts +63 -0
  24. package/dist/draft/autosave.d.ts +68 -0
  25. package/dist/draft/client-context.d.ts +8 -0
  26. package/dist/draft/draft-registry.d.ts +14 -0
  27. package/dist/draft/index.d.ts +15 -0
  28. package/dist/draft/use-workflow-draft.d.ts +67 -0
  29. package/dist/draft/workflow-save.d.ts +48 -0
  30. package/dist/draft-registry-YF0tqNN0.js +49 -0
  31. package/dist/draft-registry-YF0tqNN0.js.map +1 -0
  32. package/dist/draft.d.ts +2 -0
  33. package/dist/draft.mjs +18 -0
  34. package/dist/draft.mjs.map +1 -0
  35. package/dist/editor/WorkflowEditor.d.ts +12 -0
  36. package/dist/editor/WorkflowSettingsModal.d.ts +17 -0
  37. package/dist/editor/definition.d.ts +31 -0
  38. package/dist/editor/editor-apps.d.ts +7 -0
  39. package/dist/editor/types.d.ts +34 -0
  40. package/dist/editor.d.ts +9 -0
  41. package/dist/editor.mjs +2170 -0
  42. package/dist/editor.mjs.map +1 -0
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.mjs +67 -0
  45. package/dist/index.mjs.map +1 -0
  46. package/dist/lib/callable-descriptors.d.ts +77 -0
  47. package/dist/lib/callable-kind.d.ts +13 -0
  48. package/dist/lib/code-rail.d.ts +45 -0
  49. package/dist/lib/document-sources.d.ts +26 -0
  50. package/dist/lib/error-handler-self.d.ts +25 -0
  51. package/dist/lib/history-query.d.ts +135 -0
  52. package/dist/lib/import-paste.d.ts +41 -0
  53. package/dist/lib/index.d.ts +17 -0
  54. package/dist/lib/new-id.d.ts +10 -0
  55. package/dist/lib/rail-settings.d.ts +196 -0
  56. package/dist/lib/save-invalidation.d.ts +24 -0
  57. package/dist/lib/sdk-snippets.d.ts +96 -0
  58. package/dist/lib/settings-rail.d.ts +68 -0
  59. package/dist/lib/slug.d.ts +69 -0
  60. package/dist/lib/spec-import-invalidation.d.ts +48 -0
  61. package/dist/lib/tag-editor.d.ts +36 -0
  62. package/dist/lib/trigger-preview.d.ts +89 -0
  63. package/dist/lib/workflow-live-run.d.ts +165 -0
  64. package/dist/lib/workflow-poll.d.ts +8 -0
  65. package/dist/lib/workflow-route.d.ts +26 -0
  66. package/dist/lib/workflow-settings.d.ts +72 -0
  67. package/dist/lib/workflow-validity.d.ts +92 -0
  68. package/dist/lib/workflow-variables.d.ts +106 -0
  69. package/dist/lib.d.ts +2 -0
  70. package/dist/lib.mjs +62 -0
  71. package/dist/lib.mjs.map +1 -0
  72. package/dist/project-context-Dbk0Gr1K.js +16 -0
  73. package/dist/project-context-Dbk0Gr1K.js.map +1 -0
  74. package/dist/project-context.d.ts +11 -0
  75. package/dist/rail/CodeTool.d.ts +2 -0
  76. package/dist/rail/ErrorHandlingTool.d.ts +22 -0
  77. package/dist/rail/ExpressionScope.d.ts +21 -0
  78. package/dist/rail/SettingsTool.d.ts +27 -0
  79. package/dist/rail/editor-tools.d.ts +2 -0
  80. package/dist/rail/rail-env.d.ts +18 -0
  81. package/dist/rail/settings-sections.d.ts +93 -0
  82. package/dist/repos/documents.d.ts +102 -0
  83. package/dist/repos/history.d.ts +24 -0
  84. package/dist/repos/index.d.ts +22 -0
  85. package/dist/repos/spec-import.d.ts +44 -0
  86. package/dist/repos/step-tests.d.ts +19 -0
  87. package/dist/repos/vars.d.ts +25 -0
  88. package/dist/repos/vault.d.ts +24 -0
  89. package/dist/repos/versions.d.ts +112 -0
  90. package/dist/repos.d.ts +2 -0
  91. package/dist/repos.mjs +94 -0
  92. package/dist/repos.mjs.map +1 -0
  93. package/dist/slug-ByKQgxrf.js +642 -0
  94. package/dist/slug-ByKQgxrf.js.map +1 -0
  95. package/dist/spec-import-HgO7ZkLZ.js +898 -0
  96. package/dist/spec-import-HgO7ZkLZ.js.map +1 -0
  97. package/dist/spec-import-invalidation-D3retX4Q.js +18 -0
  98. package/dist/spec-import-invalidation-D3retX4Q.js.map +1 -0
  99. package/dist/use-workflow-draft-oI02dsP-.js +314 -0
  100. package/dist/use-workflow-draft-oI02dsP-.js.map +1 -0
  101. package/package.json +84 -3
  102. package/src/styles.css +829 -0
@@ -0,0 +1,165 @@
1
+ import { RunStatus } from '@w6w/sdk';
2
+ export type { RunStatus };
3
+ /**
4
+ * The five states a workflow step's execution can be in — a thin LOCAL copy
5
+ * of `@w6w/ui`'s `StepStatus` (itself a thin local copy of the engine's
6
+ * `StepStatus` — see `run-visuals.ts`'s own header in `packages/ui`, the
7
+ * same house idiom). `@w6w/sdk/console`'s `RunState.steps` is deliberately
8
+ * typed `Record<string, unknown>` — opaque pass-through, by that module's
9
+ * own documented design — so the real per-step shape has to be re-stated
10
+ * here rather than imported.
11
+ */
12
+ export type StepStatus = "pending" | "running" | "succeeded" | "failed" | "skipped";
13
+ /** The per-step metadata (which app/version/action/connection ran) — one
14
+ * local structural copy of the pinned `StepMeta`. A `type` alias, not an
15
+ * `interface`, so it stays assignable to index-signature types. */
16
+ export type StepMetaLike = {
17
+ app: string;
18
+ version: string;
19
+ action: string;
20
+ connectionId: string | null;
21
+ };
22
+ /** The slice of a `StepExecution` this module reads, to build one
23
+ * `ExecutionLogPanel` row. */
24
+ export interface StepExecutionLike {
25
+ status: StepStatus;
26
+ startedAt?: string;
27
+ finishedAt?: string;
28
+ input?: unknown;
29
+ output?: unknown;
30
+ /** `StepExecution.error` — a `StepError` on `failed` per rfcs/workflow.md
31
+ * §StepExecution, but read as `unknown` because `RunState.steps` is opaque
32
+ * on the wire; {@link toLogError} normalises whatever actually arrives. */
33
+ error?: unknown;
34
+ /** Recorded metadata; absent (or null) for steps that recorded none. */
35
+ meta?: StepMetaLike | null;
36
+ }
37
+ /** A step or run error, as the run log panel renders it — field-for-field
38
+ * `@w6w/ui`'s `ExecutionLogError` (rfcs/workflow.md §StepError's
39
+ * `code`/`message`/`phase`/`retryable`), restated locally for the same reason
40
+ * as {@link ExecutionLogStepLike} below. `message` is never empty. */
41
+ export interface LogErrorLike {
42
+ code?: string;
43
+ message: string;
44
+ phase?: string;
45
+ retryable?: boolean;
46
+ }
47
+ /** One `RunState.stepErrors` entry the panel shows at run level — field-for-field
48
+ * `@w6w/ui`'s `ExecutionLogRecordedError`, restated locally (see above). */
49
+ export interface RecordedLogErrorLike {
50
+ stepId: string;
51
+ label?: string;
52
+ error: LogErrorLike;
53
+ }
54
+ /** The slice of a `RunState` {@link runLevelErrors} reads. */
55
+ export interface RunErrorSourceLike {
56
+ status?: string;
57
+ error?: unknown;
58
+ stepErrors?: ReadonlyArray<{
59
+ stepId: string;
60
+ error: unknown;
61
+ }>;
62
+ }
63
+ /** The slice of a saved step-test fixture (`StepTest`) {@link latestFixtureInput}
64
+ * reads — `with` is what the trigger's Test tab invokes it with. */
65
+ export interface StepTestFixtureLike {
66
+ with?: unknown;
67
+ }
68
+ /** The row-level fallback for a `failed` step that carries no `error` at all. */
69
+ export declare const STEP_FAILED_NO_REASON = "Step failed without reporting a reason.";
70
+ /** The run-level fallback for a `failed` run where nothing carries a reason. */
71
+ export declare const RUN_FAILED_NO_REASON = "Run failed without reporting a reason.";
72
+ /** One `ExecutionLogPanel` row — field-for-field `@w6w/ui`'s
73
+ * `ExecutionLogStep`, restated locally for the same reason as
74
+ * {@link StepExecutionLike} above (no runtime dependency on `@w6w/ui`,
75
+ * which this module must not import — see the file header). */
76
+ export interface ExecutionLogStepLike {
77
+ id: string;
78
+ status: StepStatus;
79
+ startedAt?: string;
80
+ finishedAt?: string;
81
+ input?: unknown;
82
+ output?: unknown;
83
+ error?: LogErrorLike;
84
+ meta?: StepMetaLike;
85
+ }
86
+ /** How a cancel-request failure should be handled (A6). */
87
+ export type CancelErrorOutcome = "reconcile" | "surface";
88
+ /**
89
+ * A2/M1 — the `refetchInterval` decision: keep polling (`true`) until the
90
+ * run's status is terminal (`false`), including while no run has answered
91
+ * yet (`status === undefined` — the very first poll hasn't landed, or no run
92
+ * is active at all).
93
+ */
94
+ export declare function shouldContinuePolling(status: RunStatus | undefined): boolean;
95
+ /**
96
+ * A4/M2/M3 — is a run currently "in flight" from this page's point of view?
97
+ * `true` only while the poll has a live, non-terminal status AND the poll
98
+ * itself hasn't given up/errored — a failed poll unlocks the canvas exactly
99
+ * like reaching a real terminal status does (A4's own named failure case: "a
100
+ * canvas that stays locked after a cancel"). Drives the canvas's `readOnly`
101
+ * prop, the Stop button's visibility, and the Run button's disabled state —
102
+ * one function, three call sites, so they can never drift out of sync with
103
+ * each other.
104
+ */
105
+ export declare function isRunInFlight(status: RunStatus | undefined, pollFailed: boolean): boolean;
106
+ /** A1/A6 — what the Run button should read right now. */
107
+ export declare function runButtonLabel(status: RunStatus | undefined, pollFailed: boolean): string;
108
+ /**
109
+ * A6/M6 — classify a `cancel()` failure. `run_not_cancelable` (409) means
110
+ * the run already reached a terminal state before the cancel request landed
111
+ * — not a user-facing error, just reconcile to whatever the next poll
112
+ * reports. Everything else (`unknown_run`, a network failure, …) is a real
113
+ * failure the page's existing error affordance must show.
114
+ */
115
+ export declare function classifyCancelError(code: string): CancelErrorOutcome;
116
+ /**
117
+ * G5 — map a `RunState`'s opaque `steps` record onto `ExecutionLogPanel`'s
118
+ * row shape, in the record's own key order (the order the server checkpoints
119
+ * steps in, so it already reads as execution order). `ExecutionLogPanel`'s
120
+ * own contract is "never re-sorted" (`ExecutionLogPanel.tsx`'s header), so
121
+ * this function must not reorder either.
122
+ */
123
+ export declare function mapRunStateToLogSteps(steps: Record<string, StepExecutionLike> | undefined): ExecutionLogStepLike[];
124
+ /**
125
+ * Normalise whatever a step or run reported as its error into the panel's
126
+ * {@link LogErrorLike}. `null`/`undefined` mean "no error". A non-empty string
127
+ * is the message. An object contributes `code` (string), `message` (its own
128
+ * non-empty `message`, else a non-empty `code`, else its JSON), `phase`
129
+ * (string) and `retryable` (boolean). Anything else is stringified. The
130
+ * returned `message` is never empty.
131
+ */
132
+ export declare function toLogError(raw: unknown): LogErrorLike | undefined;
133
+ /**
134
+ * The run-level half of the run log: `RunState.error` as `runError`, plus the
135
+ * `RunState.stepErrors` entries whose step has NO row already carrying an
136
+ * error (a `continue-record` failure is usually also on its own row — showing
137
+ * it twice would read as two failures), in their given order. A row showing
138
+ * only {@link STEP_FAILED_NO_REASON} does not count as carrying an error here,
139
+ * so the reason recorded for that step is still surfaced. A `failed` run where
140
+ * nothing — run, rows or surfaced step errors — carries a reason gets
141
+ * {@link RUN_FAILED_NO_REASON}. `runError` is omitted when it duplicates a
142
+ * row's error (equal `message` and equal `code`), since the step failure that
143
+ * stopped the run is already shown on its row. It is likewise omitted when it
144
+ * duplicates a surfaced `stepErrors` entry's error, by the same equality.
145
+ * Keys are omitted when empty.
146
+ */
147
+ export declare function runLevelErrors(run: RunErrorSourceLike | undefined, rows: ReadonlyArray<ExecutionLogStepLike>): {
148
+ runError?: LogErrorLike;
149
+ stepErrors?: RecordedLogErrorLike[];
150
+ };
151
+ /**
152
+ * The header Run's `input`: the LAST saved fixture's `with` (`listStepTests`
153
+ * answers oldest-first — the same "last is latest" reading
154
+ * `@w6w/ui`'s `TriggerFillForm` seeds from), when it is a plain object.
155
+ * Sent verbatim — `{type:"expr",…}` values included.
156
+ */
157
+ export declare function latestFixtureInput(tests: ReadonlyArray<StepTestFixtureLike> | undefined): Record<string, unknown> | undefined;
158
+ /**
159
+ * Resolve the header Run's `input` for the manual trigger `triggerStepId`.
160
+ * No trigger id → `undefined` without fetching. A fetch that throws or
161
+ * rejects → `undefined`: a missing fixture never blocks the run. Fetched at
162
+ * click time on purpose — a cached `stepTestsKey` query can be stale, since
163
+ * saving a fixture does not invalidate it.
164
+ */
165
+ export declare function resolveHeaderRunInput(triggerStepId: string | undefined, list: (stepId: string) => Promise<ReadonlyArray<StepTestFixtureLike> | undefined>): Promise<Record<string, unknown> | undefined>;
@@ -0,0 +1,8 @@
1
+ import { RunState } from '@w6w/sdk/console';
2
+ /**
3
+ * Poll `getRun` until the run reaches a terminal status, or 600 polls (~5
4
+ * minutes at the default 500ms interval) elapse — whichever comes first.
5
+ * Ported verbatim from `api/client.ts`'s `runWorkflow`; see
6
+ * `../repos/workflows.ts` for the caller.
7
+ */
8
+ export declare function pollRunToTerminal(getRun: () => Promise<RunState>, sleep?: (ms: number) => Promise<void>): Promise<RunState>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Read the legacy `edit` parameter off a location's search string.
3
+ *
4
+ * Returns `null` when there is nothing to redirect: no `edit` key at all, or
5
+ * one that is empty (`?edit=` is not an id). Otherwise `id` is the `edit`
6
+ * value and `search` is the rest of the query — `edit` removed, every other
7
+ * parameter kept in its original order — as a leading-`?` search string, or
8
+ * `""` when nothing is left.
9
+ *
10
+ * legacyEditRedirect("?edit=wf_a") // { id: "wf_a", search: "" }
11
+ * legacyEditRedirect("?edit=wf_a&tab=steps") // { id: "wf_a", search: "?tab=steps" }
12
+ */
13
+ export declare function legacyEditRedirect(search: string): {
14
+ id: string;
15
+ search: string;
16
+ } | null;
17
+ /**
18
+ * Read the `run` query param off a location's search string, honouring it
19
+ * only when it looks like a real run id.
20
+ *
21
+ * runParamFromSearch("?run=run_1&x=1") // "run_1"
22
+ * runParamFromSearch("?run=") // null
23
+ * runParamFromSearch("?run=wf_1") // null — not a run id
24
+ * runParamFromSearch("") // null
25
+ */
26
+ export declare function runParamFromSearch(search: string): string | null;
@@ -0,0 +1,72 @@
1
+ import { WorkflowStatus } from '@w6w/sdk';
2
+ /**
3
+ * Read a workflow definition's `status` field as the real three-state value.
4
+ *
5
+ * `WorkflowsPage.tsx` used to coerce this with `status === "active" ? "active" :
6
+ * "draft"` — a two-way ternary that silently collapsed a freshly-archived
7
+ * workflow back down to `"draft"`, which would have reproduced the same bug one
8
+ * layer up in the archive/delete button-swap (an archived workflow would render
9
+ * Archive again instead of Delete). `unknown` because the source is parsed JSON,
10
+ * not a validated value — anything that isn't exactly `"active"` or `"archived"`
11
+ * reads as `"draft"`, same fallback the old coercion used for a missing/garbage
12
+ * status.
13
+ */
14
+ export declare function readWorkflowStatus(status: unknown): WorkflowStatus;
15
+ /** Authoring presentation for one workflow. Declarative only — the engine ignores it. */
16
+ export type WorkflowSettings = {
17
+ /** Persist edits without an explicit save. Omitted ⇒ **true**. */
18
+ autoSave?: boolean;
19
+ /** Persist step coordinates and `viewport` on save. Omitted ⇒ **true**. */
20
+ savePosition?: boolean;
21
+ /** The canvas camera, written by the editor — never by the settings modal. */
22
+ viewport?: {
23
+ x: number;
24
+ y: number;
25
+ zoom: number;
26
+ };
27
+ };
28
+ /** Both flags resolved against their defaults. */
29
+ export type EffectiveWorkflowSettings = {
30
+ autoSave: boolean;
31
+ savePosition: boolean;
32
+ };
33
+ /**
34
+ * The effective flags for a workflow, applying the **true-by-default** rule.
35
+ *
36
+ * ⚠️ Both flags are `true` when omitted. That is deliberately *unlike* the house
37
+ * convention `ports` and `onError` follow, where an absent field reproduces
38
+ * prior behaviour: here the product requires both features on by default, so an
39
+ * absent `settings` object means auto-save **on** and positions **persisted**.
40
+ * The RFC states it three ways and names `?? false` as a contradiction. Only an
41
+ * explicit `false` turns a feature off — hence `!== false`, which also refuses
42
+ * to read `null`, `0` or `"false"` out of a hand-edited definition as "off".
43
+ *
44
+ * Takes `unknown` because the caller's source is parsed JSON, not a validated
45
+ * value; every non-object reads as "no flags set", i.e. both on.
46
+ */
47
+ export declare function readSettings(settings: unknown): EffectiveWorkflowSettings;
48
+ /**
49
+ * Set one flag, returning the `settings` object to store.
50
+ *
51
+ * Two rules, both about *not* writing more than was asked:
52
+ *
53
+ * 1. **The default is written as absent.** `true` deletes the key instead of
54
+ * storing `autoSave: true` (the same idiom as an omitted `onError: "fail"`).
55
+ * Otherwise merely opening this modal on a legacy workflow and toggling
56
+ * something back would rewrite the definition of every workflow ever
57
+ * authored — and with auto-save on, that write happens by itself.
58
+ * 2. **Everything else survives verbatim**, `viewport` above all: it is the
59
+ * author's saved camera, written by the editor, and a whole-object replace
60
+ * here would silently discard it on the next toggle.
61
+ *
62
+ * Returns `undefined` when nothing is left to store, so the caller drops the
63
+ * key entirely rather than persisting an empty object.
64
+ *
65
+ * The input is `unknown` for the same reason `readSettings`' is — it comes straight
66
+ * out of `JSON.parse`, and the `</>` editor in the very same header lets an author
67
+ * write `"settings": "hello"`. Spreading that would persist `{"0":"h","1":"e",…}`,
68
+ * and with auto-save on the rewrite would repeat on a debounce, without anyone
69
+ * clicking anything. So anything that is not a plain object reads as "no flags
70
+ * set", exactly as it does in `readSettings`.
71
+ */
72
+ export declare function writeSetting(settings: unknown, key: "autoSave" | "savePosition", value: boolean): WorkflowSettings | undefined;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The publish-time validity gate (`logs/decisions.jsonl` row 9, verbatim):
3
+ *
4
+ * > a step is valid iff (app+action set, or function id set) and all its
5
+ * > required params are filled (reuse `requiredParamsFilled`,
6
+ * > `StepBuilderModal.tsx:577-590`) and, where `testRequired` is set for the
7
+ * > app, its saved test has passed. The workflow is valid iff a trigger exists
8
+ * > and every step is valid. Graph well-formedness (orphaned/unreachable
9
+ * > nodes, dangling edges) is explicitly OUT of scope for this project.
10
+ *
11
+ * Pure and testable by design: `WorkflowsPage.tsx` is JSX, which Node 24's
12
+ * type-stripping cannot parse, so nothing in it can be loaded by `node --test`
13
+ * (same shape as `src/lib/workflow-save.ts` + its `.test.ts`). This module
14
+ * cannot import `@w6w/ui`/`@w6w/ui/flow` either way: `@w6w/ui`'s
15
+ * `package.json` `exports["."]` resolves to raw `./src/index.ts`, which
16
+ * re-exports `StepBuilderModal.tsx` — a `.tsx` file — so `node --test` throws
17
+ * `ERR_UNKNOWN_FILE_EXTENSION` the moment anything here imports it. Instead,
18
+ * the two functions the pinned predicate reuses
19
+ * (`requiredParamsFilled`/`isTestRequired`) are **caller-injected** on
20
+ * `ValidityContext` — `WorkflowsPage.tsx` (unaffected by the JSX constraint)
21
+ * imports the real ones from `@w6w/ui` and passes them in. Same for "a
22
+ * trigger exists": that reads a graph STEP whose `INTERNAL_NODES` entry has
23
+ * `group === "trigger"` (`@w6w/ui/flow`), never the workflow's top-level
24
+ * `trigger` field (`rfcs/workflow.md:114`, "Absent means manual-only" — always
25
+ * present, so it can't gate anything) — so `hasTrigger` is caller-computed too.
26
+ *
27
+ * `ActionParamLike`/`WorkflowStepLike`/`WorkflowLike` below are this file's
28
+ * own minimal local types (see `rfcs/workflow.md` §"Step" for the real shape,
29
+ * `rfcs/function.md` for the `uses.function` arm).
30
+ */
31
+ /** A declared action/internal-node param, just enough of it for this gate. */
32
+ export interface ActionParamLike {
33
+ key: string;
34
+ type: string;
35
+ required?: boolean;
36
+ default?: unknown;
37
+ children?: ActionParamLike[];
38
+ }
39
+ /** A workflow graph step, just enough of it for this gate. */
40
+ export interface WorkflowStepLike {
41
+ id: string;
42
+ uses?: {
43
+ app?: string;
44
+ action?: string;
45
+ /** The "or a function id" arm (`rfcs/function.md:49,260`) — `Step.uses.function`. */
46
+ function?: string;
47
+ };
48
+ with?: Record<string, unknown>;
49
+ }
50
+ /** A workflow definition, just enough of it for this gate. */
51
+ export interface WorkflowLike {
52
+ steps?: WorkflowStepLike[];
53
+ /**
54
+ * Present on real definitions, never read here — graph well-formedness
55
+ * (orphaned/unreachable nodes, dangling edges) is explicitly out of scope
56
+ * for the publish gate (`logs/decisions.jsonl` row 9).
57
+ */
58
+ edges?: unknown;
59
+ }
60
+ /**
61
+ * Everything `stepValid`/`workflowValid`/`invalidReason` need that this pure
62
+ * module cannot compute or import itself — see the module docstring for why
63
+ * each field is caller-built rather than derived in here.
64
+ */
65
+ export interface ValidityContext {
66
+ /** Does the graph contain a step whose (app, action) is a trigger node? */
67
+ hasTrigger: boolean;
68
+ /** Declared params for a step's target, keyed `` `${app}::${action}` ``. */
69
+ actionParamsByKey: Record<string, ActionParamLike[]>;
70
+ /** The fetched apps list, keyed by app id — only a key present here is test-gated. */
71
+ appsById: Record<string, unknown>;
72
+ /** Whether the given step id has a saved test that last ran successfully. */
73
+ testStatus: Record<string, boolean>;
74
+ /** `@w6w/ui`'s `requiredParamsFilled`, injected (see module docstring). */
75
+ requiredParamsFilled: (params: ActionParamLike[], values: Record<string, unknown>) => boolean;
76
+ /** `@w6w/ui`'s `isTestRequired`, injected (see module docstring). */
77
+ isTestRequired: (app: unknown) => boolean;
78
+ }
79
+ /** Is this one step valid, per the pinned predicate? */
80
+ export declare function stepValid(step: WorkflowStepLike, ctx: ValidityContext): boolean;
81
+ /**
82
+ * Is the whole workflow valid? A trigger step must exist and every step must
83
+ * be individually valid — nothing about graph well-formedness (this never
84
+ * reads `workflow.edges`, even when present).
85
+ */
86
+ export declare function workflowValid(workflow: WorkflowLike, ctx: ValidityContext): boolean;
87
+ /**
88
+ * `null` when the workflow is valid; otherwise names the cause — `"no trigger
89
+ * step"`, or the id of the first invalid step in declared order plus which
90
+ * check it fails.
91
+ */
92
+ export declare function invalidReason(workflow: WorkflowLike, ctx: ValidityContext): string | null;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The pure decisions behind a workflow's `variables` list (T1.1.5) — the
3
+ * Variables tab's authoring surface and the run page's generated-form
4
+ * projection. `variables` rides inside the workflow **definition**
5
+ * (`w6w-workflow/packages/types/mod.ts:170`), the same JSON document that
6
+ * already carries `steps`, so there is no column, no migration and no server
7
+ * change behind it.
8
+ *
9
+ * Pure, React-free, `.ts`, **no value import of `@w6w/ui`** — studio's
10
+ * `test:unit` is a bare `node --test` with no jsx loader
11
+ * (`studio/package.json:17`), so a value import of the barrel (which
12
+ * re-exports `.tsx`) kills the test. Same shape as `workflow-settings.ts`'s
13
+ * reader/writer discipline and `input-seeding.ts`'s pure-module docstring
14
+ * rule.
15
+ *
16
+ * The row type is defined **locally**, structurally identical to
17
+ * `WorkflowVariable` (`w6w-workflow/packages/types/mod.ts:40-45`: `key`,
18
+ * `type?`, `required?`, `default?`), so no cast is needed at the `.tsx`
19
+ * boundary in either direction.
20
+ */
21
+ /** One row of a workflow's declared `variables` list. */
22
+ export interface WorkflowVariableRow {
23
+ key: string;
24
+ type?: "string" | "number" | "boolean" | "object" | "array";
25
+ required?: boolean;
26
+ default?: unknown;
27
+ }
28
+ /**
29
+ * Read a workflow definition's `variables` field as an array of rows.
30
+ *
31
+ * Takes `unknown` because the source is `JSON.parse`d and the `</>` editor
32
+ * lets an author type anything: a non-array reads as no variables, and a
33
+ * non-object array entry is dropped rather than crashing the tab. **Never
34
+ * sorts, never de-dups, never re-orders** — declaration order *is*
35
+ * resolution order (D-5) and `resolveVariables` iterates the array in order
36
+ * (`w6w-workflow/packages/engine/src/run.ts:70-83`), so two rows sharing a
37
+ * key both survive, in the order they were declared.
38
+ */
39
+ export declare function readVariables(raw: unknown): WorkflowVariableRow[];
40
+ /**
41
+ * The rows ready to write back into the definition's `variables` field.
42
+ *
43
+ * Mirrors `workflow-settings.ts`'s "default written as absent" rule, but here
44
+ * it applies to a row's **optional flags, not the value**: `required` is
45
+ * omitted when `false` and `type` is omitted when unset, so opening the tab
46
+ * and touching nothing does not rewrite a legacy definition into
47
+ * `{required:false,type:undefined}` rows. `default` is user data and is kept
48
+ * **verbatim** — including `false`, `0`, `""` and `null` — never dropped as
49
+ * an optimisation (a "drop falsy" implementation would lose a `false`
50
+ * default, which is exactly the case the tests pin).
51
+ *
52
+ * Returns `undefined` for an empty array (never `[]`) so the caller
53
+ * (`patchMeta`, via `JSON.stringify`) drops the key entirely — which matters
54
+ * beyond hygiene here: `draftFromWorkflowVariables`
55
+ * (`server/packages/api/mcp/tool-schema.ts:310-326`) treats `undefined` and
56
+ * `length === 0` identically (pass-through), so `[]` and absent already agree
57
+ * on the wire; this just keeps the definition itself from growing an empty
58
+ * `"variables": []` on the first open of the tab.
59
+ */
60
+ export declare function variablesForSave(rows: WorkflowVariableRow[]): WorkflowVariableRow[] | undefined;
61
+ /**
62
+ * Every index whose `key` repeats an earlier row's key. `resolveVariables`
63
+ * writes `vars[v.key]` in a loop with no duplicate check (`run.ts:74-80`), so
64
+ * a later row silently wins — this is informational only (the tab marks the
65
+ * row; nothing here blocks a save), never de-duping or rejecting.
66
+ */
67
+ export declare function duplicateKeyIndexes(rows: WorkflowVariableRow[]): number[];
68
+ /**
69
+ * The `vars.*` names to offer row `index`'s expression rail: the keys of
70
+ * rows **strictly above** it, then `projectVars`, deduped, with blanks
71
+ * dropped. Declaration order is resolution order (D-5), so a row can only
72
+ * reference a variable declared earlier than itself — offering a row at or
73
+ * below `index` would suggest a forward reference the engine rejects
74
+ * (T2.1.1). This is the offered rail only; it is not validation.
75
+ */
76
+ export declare function varsRailFor(rows: WorkflowVariableRow[], index: number, projectVars: string[]): string[];
77
+ /** `true` if `v` is an `ExprValue` envelope — the two-key check `@w6w/ui`'s
78
+ * `isExprValue` (`ui/src/types.ts:301-309`) makes, re-implemented locally
79
+ * because this module cannot import `@w6w/ui` at value level (see the
80
+ * module docstring). Mirrors `trigger-preview.ts:102-119`'s sanctioned
81
+ * pattern for the same constraint — this is not duplication. */
82
+ export declare function isExprDefault(v: unknown): boolean;
83
+ /** One field the run page's generated form fills — structurally assignable
84
+ * to `@w6w/ui/flow`'s `TriggerFieldDef` (all fields optional) with no cast. */
85
+ export interface RunFormField {
86
+ key: string;
87
+ type?: WorkflowVariableRow["type"];
88
+ default?: unknown;
89
+ required?: boolean;
90
+ }
91
+ /**
92
+ * Project a workflow's declared variables into the run page's form fields.
93
+ *
94
+ * A row whose `default` is an `ExprValue` envelope is a server-side
95
+ * computation (its value is resolved at run time, not authored on the
96
+ * client), so it is emitted with **`default` dropped and `required: false`**
97
+ * — never as a value `ui`'s `seedValues` would `String(...)` the envelope
98
+ * into — and its key is listed in `computed` so the host can label the field
99
+ * "computed at run time" and post nothing for it. A row with a blank/missing
100
+ * key is dropped, mirroring `@w6w/ui`'s `fieldsToParams`, which does the same
101
+ * before turning field definitions into a fillable form.
102
+ */
103
+ export declare function runFormFields(rows: WorkflowVariableRow[]): {
104
+ fields: RunFormField[];
105
+ computed: string[];
106
+ };
package/dist/lib.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './lib/index'
2
+ export {}
package/dist/lib.mjs ADDED
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { A as n, b as d, d as c, a as u, c as p, e as m, f as S, g as f, h as g, i as v, j as w, k as R, l as b, m as h, n as y, o as F, p as A, q as K, r as C, s as D, t as E, u as I, v as x, w as P, x as V, y as L, z as U, B as k, C as H, D as W, E as _, F as j, G, H as N, I as O, J as q, K as z, L as B, M as J, N as M, O as T } from "./slug-ByKQgxrf.js";
3
+ import { i as Q, s as X } from "./spec-import-invalidation-D3retX4Q.js";
4
+ function t(s) {
5
+ const e = new URLSearchParams(s), a = e.get("edit");
6
+ if (a === null || a === "") return null;
7
+ e.delete("edit");
8
+ const i = e.toString();
9
+ return { id: a, search: i === "" ? "" : `?${i}` };
10
+ }
11
+ function r(s) {
12
+ const a = new URLSearchParams(s).get("run");
13
+ return a != null && a.startsWith("run_") ? a : null;
14
+ }
15
+ export {
16
+ n as ACCOUNT_SLUG_RE,
17
+ d as buildSnippet,
18
+ c as definitionWithPolicy,
19
+ u as documentSampleValues,
20
+ p as duplicateKeyIndexes,
21
+ m as errorHandlerSelfDecision,
22
+ S as evaluateEdit,
23
+ f as filterKeyInput,
24
+ g as hasDefinitionActions,
25
+ v as hasDelete,
26
+ w as hasVersionHistory,
27
+ R as invalidReason,
28
+ Q as invalidateImportedCallable,
29
+ b as isCodeRailAvailable,
30
+ h as isEndpointKey,
31
+ y as isExprDefault,
32
+ F as isRowArchived,
33
+ A as isSettingsRailAvailable,
34
+ K as isUrnAddressable,
35
+ C as isValidAccountSlug,
36
+ t as legacyEditRedirect,
37
+ D as metadataFieldsForKind,
38
+ E as parseImportPaste,
39
+ I as policyFromDefinition,
40
+ x as projectDocumentSources,
41
+ P as readSettings,
42
+ V as readVariables,
43
+ L as readWorkflowStatus,
44
+ U as restoreRailState,
45
+ k as runFormFields,
46
+ r as runParamFromSearch,
47
+ H as slugify,
48
+ W as specCollectionForKind,
49
+ X as specImportListKey,
50
+ _ as stepValid,
51
+ j as toSnippetCallable,
52
+ G as triggerInputSeed,
53
+ N as triggerPreviews,
54
+ O as unavailableReason,
55
+ q as variablesForSave,
56
+ z as varsRailFor,
57
+ B as visibleRows,
58
+ J as workflowKeyEditAllowed,
59
+ M as workflowValid,
60
+ T as writeSetting
61
+ };
62
+ //# sourceMappingURL=lib.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.mjs","sources":["../src/lib/workflow-route.ts"],"sourcesContent":["// T4.1.1 (R-3): `/<account>/<project>/workflows/:id` is the workflow visual\n// editor's canonical URL; the older `workflows?edit=<id>` form survives only as\n// an alias. Parsing that alias is a pure URL question with no React and no\n// router in it, so it lives here — `.ts`, zero imports — rather than inline in\n// `WorkflowsPage.tsx`, which `node --test` cannot load (JSX).\n\n/**\n * Read the legacy `edit` parameter off a location's search string.\n *\n * Returns `null` when there is nothing to redirect: no `edit` key at all, or\n * one that is empty (`?edit=` is not an id). Otherwise `id` is the `edit`\n * value and `search` is the rest of the query — `edit` removed, every other\n * parameter kept in its original order — as a leading-`?` search string, or\n * `\"\"` when nothing is left.\n *\n * legacyEditRedirect(\"?edit=wf_a\") // { id: \"wf_a\", search: \"\" }\n * legacyEditRedirect(\"?edit=wf_a&tab=steps\") // { id: \"wf_a\", search: \"?tab=steps\" }\n */\nexport function legacyEditRedirect(search: string): { id: string; search: string } | null {\n const params = new URLSearchParams(search);\n const id = params.get(\"edit\");\n if (id === null || id === \"\") return null;\n params.delete(\"edit\");\n const rest = params.toString();\n return { id, search: rest === \"\" ? \"\" : `?${rest}` };\n}\n\n// T2.4.2 — the History page's \"open in visual view\" link lands on\n// `workflows/:id?run=<runId>`; `WorkflowsPage` reads the `run` param on mount\n// and seeds `activeRunId` from it (EXTEND, not rebuild — the live-run\n// overlay machinery already handles a terminal run identically to a live\n// one). Guarded to `run_`-prefixed values only, so an unrelated/garbled\n// param (or this file's OWN `edit` alias from a stale link) never gets\n// treated as a run id.\n\n/**\n * Read the `run` query param off a location's search string, honouring it\n * only when it looks like a real run id.\n *\n * runParamFromSearch(\"?run=run_1&x=1\") // \"run_1\"\n * runParamFromSearch(\"?run=\") // null\n * runParamFromSearch(\"?run=wf_1\") // null — not a run id\n * runParamFromSearch(\"\") // null\n */\nexport function runParamFromSearch(search: string): string | null {\n const params = new URLSearchParams(search);\n const run = params.get(\"run\");\n return run?.startsWith(\"run_\") ? run : null;\n}\n"],"names":["legacyEditRedirect","search","params","id","rest","runParamFromSearch","run"],"mappings":";;;AAkBO,SAASA,EAAmBC,GAAuD;AACxF,QAAMC,IAAS,IAAI,gBAAgBD,CAAM,GACnCE,IAAKD,EAAO,IAAI,MAAM;AAC5B,MAAIC,MAAO,QAAQA,MAAO,GAAI,QAAO;AACrC,EAAAD,EAAO,OAAO,MAAM;AACpB,QAAME,IAAOF,EAAO,SAAA;AACpB,SAAO,EAAE,IAAAC,GAAI,QAAQC,MAAS,KAAK,KAAK,IAAIA,CAAI,GAAA;AAClD;AAmBO,SAASC,EAAmBJ,GAA+B;AAEhE,QAAMK,IADS,IAAI,gBAAgBL,CAAM,EACtB,IAAI,KAAK;AAC5B,SAAOK,KAAA,QAAAA,EAAK,WAAW,UAAUA,IAAM;AACzC;"}
@@ -0,0 +1,16 @@
1
+ import { createContext as o, useContext as r } from "react";
2
+ const n = o(void 0);
3
+ function u() {
4
+ return r(n);
5
+ }
6
+ function c(t, e) {
7
+ return t === void 0 ? e || null : t || null;
8
+ }
9
+ function s(t) {
10
+ return c(t, u());
11
+ }
12
+ export {
13
+ n as E,
14
+ s as u
15
+ };
16
+ //# sourceMappingURL=project-context-Dbk0Gr1K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context-Dbk0Gr1K.js","sources":["../src/project-context.ts"],"sourcesContent":["/**\n * Which project does an embedded editor save into? One answer, in one place.\n *\n * A project-less workflow save is not harmless: the server resolves a missing `?project=` to the\n * account default and WRITES it on update, silently moving the row there. The editor therefore\n * always names its project explicitly, or refuses. Internal to the embed package (not exported\n * from any barrel).\n */\nimport { createContext, useContext } from \"react\";\n\n/** The provider's project, as frozen with the applied client (see `W6WEmbedProvider`). */\nexport const EmbedProjectContext = createContext<string | undefined>(undefined);\n\nexport function useProvidedProject(): string | undefined {\n return useContext(EmbedProjectContext);\n}\n\n/**\n * The editor's own prop wins over the provider's project. `undefined` (omitted) defers to the\n * provider; `null` or `\"\"` means \"no project yet\" and REFUSES (`null`) — it never falls through,\n * so a host whose project is still loading cannot have edits saved into the provider's project.\n * (`prop ?? provided` would be wrong: `null` would fall through.)\n */\nexport function resolveEditorProject(\n prop: string | null | undefined,\n provided: string | undefined,\n): string | null {\n if (prop === undefined) return provided ? provided : null;\n return prop ? prop : null;\n}\n\nexport function useEditorProject(prop: string | null | undefined): string | null {\n return resolveEditorProject(prop, useProvidedProject());\n}\n"],"names":["EmbedProjectContext","createContext","useProvidedProject","useContext","resolveEditorProject","prop","provided","useEditorProject"],"mappings":";AAWO,MAAMA,IAAsBC,EAAkC,MAAS;AAEvE,SAASC,IAAyC;AACvD,SAAOC,EAAWH,CAAmB;AACvC;AAQO,SAASI,EACdC,GACAC,GACe;AACf,SAAID,MAAS,SAAkBC,KAAsB,OAC9CD,KAAc;AACvB;AAEO,SAASE,EAAiBF,GAAgD;AAC/E,SAAOD,EAAqBC,GAAMH,GAAoB;AACxD;"}
@@ -0,0 +1,11 @@
1
+ /** The provider's project, as frozen with the applied client (see `W6WEmbedProvider`). */
2
+ export declare const EmbedProjectContext: import('react').Context<string | undefined>;
3
+ export declare function useProvidedProject(): string | undefined;
4
+ /**
5
+ * The editor's own prop wins over the provider's project. `undefined` (omitted) defers to the
6
+ * provider; `null` or `""` means "no project yet" and REFUSES (`null`) — it never falls through,
7
+ * so a host whose project is still loading cannot have edits saved into the provider's project.
8
+ * (`prop ?? provided` would be wrong: `null` would fall through.)
9
+ */
10
+ export declare function resolveEditorProject(prop: string | null | undefined, provided: string | undefined): string | null;
11
+ export declare function useEditorProject(prop: string | null | undefined): string | null;
@@ -0,0 +1,2 @@
1
+ import { RailTool } from '../chrome/RightRail.tsx';
2
+ export declare const codeTool: RailTool;
@@ -0,0 +1,22 @@
1
+ import { RailTool } from '../chrome/RightRail.tsx';
2
+ import { CallablePolicy } from '../lib/settings-rail.ts';
3
+ /**
4
+ * `@w6w/ui/flow`'s `CALL_APP`, restated: a VALUE import from the flow subpath would put the whole
5
+ * canvas on the editor's eager path (the editor loads it with a dynamic `import()` only). A test
6
+ * (`workflow-editor.test.ts`) pins the two spellings equal.
7
+ */
8
+ export declare const CALL_APP = "@w6w/call";
9
+ export type ErrorHandlerKind = "function" | "endpoint" | "workflow";
10
+ export interface ErrorHandlerSectionProps {
11
+ kind: ErrorHandlerKind;
12
+ id: string;
13
+ /** The policy as currently stored (already read off the definition or buffer). */
14
+ policy: CallablePolicy;
15
+ /** The definition (or buffer) the policy was read from is present. */
16
+ ready: boolean;
17
+ saving: boolean;
18
+ /** Write a whole new policy. `onError` shows a refusal inline. */
19
+ onPersist(next: CallablePolicy, onError: (message: string) => void): void;
20
+ }
21
+ export declare function ErrorHandlerSection({ kind, id, policy, ready, saving, onPersist, }: ErrorHandlerSectionProps): import("react").JSX.Element;
22
+ export declare const errorHandlingTool: RailTool;
@@ -0,0 +1,21 @@
1
+ import { ExpressionOptions } from '@w6w/ui';
2
+ import { ReactNode } from 'react';
3
+ /**
4
+ * The current project's expression sources, as an `ExpressionOptions`.
5
+ *
6
+ * Exported because a surface that renders OUTSIDE `ProjectExpressionScope` —
7
+ * or one that needs the values themselves rather than the context — can still
8
+ * build the same object. Inside the scope, prefer inheriting it.
9
+ */
10
+ export declare function useProjectExpressionOptions(project: string | null): ExpressionOptions;
11
+ /**
12
+ * Provide the current project's expression sources to every route below.
13
+ *
14
+ * Mount once, inside `ProjectProvider` (it reads the active project) and around
15
+ * `Layout` (so every page inherits). It contributes no `inputs` and no `steps`
16
+ * on purpose — see the module doc.
17
+ */
18
+ export declare function ProjectExpressionScope({ project, children, }: {
19
+ project: string | null;
20
+ children: ReactNode;
21
+ }): import("react").JSX.Element;