@w6w/embed 0.2.11 → 0.2.20

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 (133) hide show
  1. package/README.md +22 -5
  2. package/dist/ConfirmModal-Pv2-A_3U.js +186 -0
  3. package/dist/ConfirmModal-Pv2-A_3U.js.map +1 -0
  4. package/dist/{CreateFunctionModal-D6CQLpa_.js → CreateFunctionModal-DScxp_LN.js} +2 -2
  5. package/dist/{CreateFunctionModal-D6CQLpa_.js.map → CreateFunctionModal-DScxp_LN.js.map} +1 -1
  6. package/dist/{DocumentFormModal-YauVdolr.js → DocumentFormModal-Br4s8wmi.js} +3 -3
  7. package/dist/{DocumentFormModal-YauVdolr.js.map → DocumentFormModal-Br4s8wmi.js.map} +1 -1
  8. package/dist/ImportSpecModal-Cpzp8ndt.js +251 -0
  9. package/dist/ImportSpecModal-Cpzp8ndt.js.map +1 -0
  10. package/dist/{ModelRoutesManager-BGESQahw.js → ModelRoutesManager-1Ac5wcas.js} +3 -3
  11. package/dist/{ModelRoutesManager-BGESQahw.js.map → ModelRoutesManager-1Ac5wcas.js.map} +1 -1
  12. package/dist/WorkflowEditor-CmhXHRxi.js +1109 -0
  13. package/dist/WorkflowEditor-CmhXHRxi.js.map +1 -0
  14. package/dist/apps-ItBvnWX3.js +92 -0
  15. package/dist/apps-ItBvnWX3.js.map +1 -0
  16. package/dist/chrome/DangerZone.d.ts +4 -3
  17. package/dist/chrome/ExecutionProfileHeader.d.ts +3 -3
  18. package/dist/chrome/JsonToggle.d.ts +29 -20
  19. package/dist/chrome/Modal.d.ts +3 -1
  20. package/dist/chrome/RightRail.d.ts +6 -1
  21. package/dist/chrome/VersionHistoryModal.d.ts +2 -0
  22. package/dist/chrome/index.d.ts +1 -0
  23. package/dist/chrome/workspace.d.ts +32 -1
  24. package/dist/{coerce-input-DttlcSdO.js → coerce-input-DFJ4n_wc.js} +68 -69
  25. package/dist/coerce-input-DFJ4n_wc.js.map +1 -0
  26. package/dist/{connections-D7cgXhDS.js → connections-CzsCyIxY.js} +10 -10
  27. package/dist/{connections-D7cgXhDS.js.map → connections-CzsCyIxY.js.map} +1 -1
  28. package/dist/{credentials-DaQU3Ca_.js → credentials-Cn92LGhJ.js} +4 -4
  29. package/dist/{credentials-DaQU3Ca_.js.map → credentials-Cn92LGhJ.js.map} +1 -1
  30. package/dist/data-stores-UeQvwVCa.js +170 -0
  31. package/dist/data-stores-UeQvwVCa.js.map +1 -0
  32. package/dist/document-sources-DNmBojx6.js +169 -0
  33. package/dist/document-sources-DNmBojx6.js.map +1 -0
  34. package/dist/draft/use-workflow-draft.d.ts +2 -0
  35. package/dist/draft.mjs +2 -2
  36. package/dist/editor/PublishTooltip.d.ts +7 -0
  37. package/dist/editor/SetupIncompleteBanner.d.ts +12 -0
  38. package/dist/editor/StartingStateModal.d.ts +14 -0
  39. package/dist/editor/WorkflowSettingsModal.d.ts +6 -1
  40. package/dist/editor/WorkflowVariablesEditor.d.ts +6 -0
  41. package/dist/editor/definition.d.ts +4 -0
  42. package/dist/editor/json-apply.d.ts +29 -0
  43. package/dist/editor/step-problems-feed.d.ts +5 -0
  44. package/dist/editor/types.d.ts +2 -2
  45. package/dist/editor-apps-DkkC7wOQ.js +152 -0
  46. package/dist/editor-apps-DkkC7wOQ.js.map +1 -0
  47. package/dist/editor-tools-BR27RGto.js +1683 -0
  48. package/dist/editor-tools-BR27RGto.js.map +1 -0
  49. package/dist/editor.mjs +1 -1
  50. package/dist/editors.mjs +536 -478
  51. package/dist/editors.mjs.map +1 -1
  52. package/dist/forms.mjs +3 -3
  53. package/dist/{rail-settings-XYGToh00.js → import-bindings-EUtxZ9Ti.js} +90 -24
  54. package/dist/import-bindings-EUtxZ9Ti.js.map +1 -0
  55. package/dist/index.mjs +138 -108
  56. package/dist/index.mjs.map +1 -1
  57. package/dist/lib/binding-problems.d.ts +5 -1
  58. package/dist/lib/history-query.d.ts +45 -0
  59. package/dist/lib/import-bindings.d.ts +89 -0
  60. package/dist/lib/index.d.ts +3 -0
  61. package/dist/lib/rail-settings.d.ts +1 -1
  62. package/dist/lib/setup-incomplete.d.ts +22 -0
  63. package/dist/lib/starting-data.d.ts +31 -0
  64. package/dist/lib/state-panel.d.ts +29 -0
  65. package/dist/lib/target-fields.d.ts +3 -15
  66. package/dist/lib/workflow-live-run.d.ts +84 -6
  67. package/dist/lib/workflow-validity.d.ts +64 -16
  68. package/dist/lib/workflow-variables.d.ts +1 -1
  69. package/dist/lib/workflow-version.d.ts +2 -0
  70. package/dist/lib.mjs +87 -72
  71. package/dist/lists/DataStoreList.d.ts +17 -0
  72. package/dist/lists/DataStoreView.d.ts +19 -0
  73. package/dist/lists/Logs.d.ts +19 -0
  74. package/dist/lists.d.ts +6 -0
  75. package/dist/lists.mjs +1255 -816
  76. package/dist/lists.mjs.map +1 -1
  77. package/dist/rail/ConnectionsTool.d.ts +2 -0
  78. package/dist/rail/HistoryTool.d.ts +2 -0
  79. package/dist/rail/StartingStateTool.d.ts +2 -0
  80. package/dist/rail/settings-sections.d.ts +4 -1
  81. package/dist/rail.mjs +1 -1
  82. package/dist/repos/connections.d.ts +1 -0
  83. package/dist/repos/constants.d.ts +12 -0
  84. package/dist/repos/data-stores.d.ts +84 -0
  85. package/dist/repos/history.d.ts +9 -0
  86. package/dist/repos/index.d.ts +2 -0
  87. package/dist/repos/spec-export.d.ts +3 -3
  88. package/dist/repos/spec-import.d.ts +30 -1
  89. package/dist/repos/step-tests.d.ts +2 -0
  90. package/dist/repos/webhook-listen.d.ts +35 -0
  91. package/dist/repos/workflows.d.ts +105 -2
  92. package/dist/repos.mjs +370 -328
  93. package/dist/repos.mjs.map +1 -1
  94. package/dist/setup-incomplete-BHs3Lpfy.js +199 -0
  95. package/dist/setup-incomplete-BHs3Lpfy.js.map +1 -0
  96. package/dist/{spec-export-CBbloO_n.js → spec-export-DGy5ijps.js} +72 -59
  97. package/dist/spec-export-DGy5ijps.js.map +1 -0
  98. package/dist/spec-import-SWOonsNr.js +116 -0
  99. package/dist/spec-import-SWOonsNr.js.map +1 -0
  100. package/dist/{step-tests-CivICmTq.js → step-tests-B4E4W3ly.js} +8 -7
  101. package/dist/step-tests-B4E4W3ly.js.map +1 -0
  102. package/dist/{use-callable-draft-DsALnSfF.js → use-callable-draft-DCauHt5o.js} +2 -2
  103. package/dist/{use-callable-draft-DsALnSfF.js.map → use-callable-draft-DCauHt5o.js.map} +1 -1
  104. package/dist/use-workflow-draft-l3P5KZzw.js +338 -0
  105. package/dist/use-workflow-draft-l3P5KZzw.js.map +1 -0
  106. package/dist/workflows-BZN4Hyz1.js +623 -0
  107. package/dist/workflows-BZN4Hyz1.js.map +1 -0
  108. package/package.json +4 -3
  109. package/src/styles.css +153 -1
  110. package/dist/ConfirmModal-BE-SdX-O.js +0 -185
  111. package/dist/ConfirmModal-BE-SdX-O.js.map +0 -1
  112. package/dist/ImportSpecModal-B7qd1Km2.js +0 -136
  113. package/dist/ImportSpecModal-B7qd1Km2.js.map +0 -1
  114. package/dist/WorkflowEditor-CwvmAGp2.js +0 -925
  115. package/dist/WorkflowEditor-CwvmAGp2.js.map +0 -1
  116. package/dist/apps-CboASBKr.js +0 -77
  117. package/dist/apps-CboASBKr.js.map +0 -1
  118. package/dist/coerce-input-DttlcSdO.js.map +0 -1
  119. package/dist/document-sources-UCwe8x77.js +0 -91
  120. package/dist/document-sources-UCwe8x77.js.map +0 -1
  121. package/dist/editor-apps-BUZWld-m.js +0 -95
  122. package/dist/editor-apps-BUZWld-m.js.map +0 -1
  123. package/dist/editor-tools-B_Lfx3kw.js +0 -1279
  124. package/dist/editor-tools-B_Lfx3kw.js.map +0 -1
  125. package/dist/rail-settings-XYGToh00.js.map +0 -1
  126. package/dist/spec-export-CBbloO_n.js.map +0 -1
  127. package/dist/spec-import-CW6R_Wk1.js +0 -469
  128. package/dist/spec-import-CW6R_Wk1.js.map +0 -1
  129. package/dist/step-tests-CivICmTq.js.map +0 -1
  130. package/dist/trigger-preview-DKxfjzUY.js +0 -145
  131. package/dist/trigger-preview-DKxfjzUY.js.map +0 -1
  132. package/dist/use-workflow-draft-DzAyUeA6.js +0 -316
  133. package/dist/use-workflow-draft-DzAyUeA6.js.map +0 -1
@@ -1,469 +0,0 @@
1
- import { useQueryClient as c, useMutation as a, useQuery as y } from "@tanstack/react-query";
2
- import { u as i } from "./client-context-CX61Bgw-.js";
3
- import { isTerminalRunStatus as g, path as b } from "@w6w/sdk";
4
- import { i as C } from "./spec-import-invalidation-D3retX4Q.js";
5
- function E(t) {
6
- return (t == null ? void 0 : t.nodes) ?? (t == null ? void 0 : t.steps) ?? void 0;
7
- }
8
- const p = "Node failed without reporting a reason.", A = "Run failed without reporting a reason.";
9
- function K(t) {
10
- return t === void 0 || !g(t);
11
- }
12
- function F(t, e) {
13
- return e || t === void 0 ? !1 : !g(t);
14
- }
15
- function et(t, e) {
16
- return F(t, e) ? t === "queued" ? "Queued…" : "Running…" : "Run";
17
- }
18
- function nt(t) {
19
- return t === "run_not_cancelable" ? "reconcile" : "surface";
20
- }
21
- function Q(t) {
22
- return t ? Object.entries(t).map(([e, n]) => ({
23
- id: e,
24
- status: n.status,
25
- startedAt: n.startedAt,
26
- finishedAt: n.finishedAt,
27
- input: n.input,
28
- output: n.output,
29
- ...n.meta !== void 0 && n.meta !== null ? { meta: n.meta } : {},
30
- ...M(n)
31
- })) : [];
32
- }
33
- function M(t) {
34
- const e = w(t.error);
35
- return e ? { error: e } : t.status === "failed" ? { error: { message: p } } : {};
36
- }
37
- function w(t) {
38
- if (t != null) {
39
- if (typeof t == "string" && t !== "") return { message: t };
40
- if (typeof t == "object") {
41
- const e = t, n = typeof e.code == "string" ? e.code : void 0, o = typeof e.message == "string" && e.message !== "" ? e.message : n || D(t);
42
- return {
43
- ...n !== void 0 ? { code: n } : {},
44
- message: o || "Unknown error.",
45
- ...typeof e.phase == "string" ? { phase: e.phase } : {},
46
- ...typeof e.retryable == "boolean" ? { retryable: e.retryable } : {}
47
- };
48
- }
49
- return { message: String(t) || "Unknown error." };
50
- }
51
- }
52
- function D(t) {
53
- try {
54
- return JSON.stringify(t) ?? "";
55
- } catch {
56
- return "";
57
- }
58
- }
59
- function ot(t, e) {
60
- if (!t) return {};
61
- const n = new Set(e.filter((r) => r.error !== void 0).map((r) => r.id)), o = new Set(
62
- e.filter((r) => r.error !== void 0 && r.error.message !== p).map((r) => r.id)
63
- ), s = (t.stepErrors ?? []).map((r) => ({ e: r, id: r.nodeId ?? r.stepId ?? "" })).filter(({ id: r }) => !o.has(r)).map(({ e: r, id: v }) => ({
64
- stepId: v,
65
- error: w(r.error) ?? { message: p }
66
- })), u = w(t.error), l = (r) => u !== void 0 && (r == null ? void 0 : r.message) === u.message && (r == null ? void 0 : r.code) === u.code;
67
- let d = e.some((r) => l(r.error)) || s.some((r) => l(r.error)) ? void 0 : u;
68
- return !d && t.status === "failed" && n.size === 0 && s.length === 0 && (d = { message: A }), {
69
- ...d ? { runError: d } : {},
70
- ...s.length > 0 ? { stepErrors: s } : {}
71
- };
72
- }
73
- function I(t) {
74
- var n;
75
- const e = (n = t == null ? void 0 : t[t.length - 1]) == null ? void 0 : n.with;
76
- if (!(e === null || typeof e != "object" || Array.isArray(e)))
77
- return e;
78
- }
79
- async function rt(t, e) {
80
- if (t)
81
- try {
82
- return I(await e(t));
83
- } catch {
84
- return;
85
- }
86
- }
87
- const st = {
88
- status: "",
89
- kind: "",
90
- from: "",
91
- to: "",
92
- q: "",
93
- offset: 0
94
- }, q = 25, T = /* @__PURE__ */ new Set([
95
- "queued",
96
- "running",
97
- "succeeded",
98
- "failed",
99
- "canceled"
100
- ]), N = /* @__PURE__ */ new Set(["function", "endpoint", "workflow"]), _ = /^\d{4}-\d{2}-\d{2}$/;
101
- function m(t) {
102
- if (!_.test(t)) return !1;
103
- const { y: e, m: n, d: o } = h(t), s = new Date(e, n - 1, o);
104
- return s.getFullYear() === e && s.getMonth() === n - 1 && s.getDate() === o;
105
- }
106
- function h(t) {
107
- const [e, n, o] = t.split("-").map(Number);
108
- return { y: e, m: n, d: o };
109
- }
110
- function it(t) {
111
- const e = new URLSearchParams(t), n = e.get("status") ?? "", o = e.get("kind") ?? "", s = e.get("from") ?? "", u = e.get("to") ?? "", l = e.get("q") ?? "", f = e.get("offset");
112
- let d = 0;
113
- if (f !== null) {
114
- const r = Number(f);
115
- Number.isInteger(r) && r >= 0 && (d = r);
116
- }
117
- return {
118
- status: T.has(n) ? n : "",
119
- kind: N.has(o) ? o : "",
120
- from: m(s) ? s : "",
121
- to: m(u) ? u : "",
122
- q: l,
123
- offset: d
124
- };
125
- }
126
- function ut(t) {
127
- const e = new URLSearchParams();
128
- t.status !== "" && e.set("status", t.status), t.kind !== "" && e.set("kind", t.kind), t.from !== "" && e.set("from", t.from), t.to !== "" && e.set("to", t.to), t.q !== "" && e.set("q", t.q), t.offset > 0 && e.set("offset", String(t.offset));
129
- const n = e.toString();
130
- return n === "" ? "" : `?${n}`;
131
- }
132
- function k(t, e, n) {
133
- const o = {};
134
- if ("project" in t ? (o.project = t.project, e.kind !== "" && (o.kind = e.kind)) : o.callable = t.callable, e.status !== "" && (o.status = e.status), e.from !== "" && m(e.from)) {
135
- const { y: u, m: l, d: f } = h(e.from);
136
- o.from = new Date(u, l - 1, f).toISOString();
137
- }
138
- if (e.to !== "" && m(e.to)) {
139
- const { y: u, m: l, d: f } = h(e.to);
140
- o.to = new Date(u, l - 1, f + 1).toISOString();
141
- }
142
- const s = e.q.trim();
143
- return s !== "" && (o.q = s), n.paged && (o.limit = String(n.limit ?? q), e.offset > 0 && (o.offset = String(e.offset))), o;
144
- }
145
- const R = {
146
- root: ["history"],
147
- list(t, e, n) {
148
- return ["history", "list", t, e, n];
149
- },
150
- stats(t, e) {
151
- return ["history", "stats", t, e];
152
- },
153
- exists(t) {
154
- return ["history", "exists", t];
155
- },
156
- detail(t, e) {
157
- return ["history", "detail", t, e];
158
- }
159
- };
160
- function at(t, e, n, o = q) {
161
- return t.request({
162
- method: "GET",
163
- path: "/history",
164
- query: k(e, n, { paged: !0, limit: o })
165
- }).then((s) => s.body);
166
- }
167
- function ct(t, e, n) {
168
- return t.request({
169
- method: "GET",
170
- path: "/history/stats",
171
- query: k(e, n, { paged: !1 })
172
- }).then((o) => o.body.stats);
173
- }
174
- async function lt(t, e) {
175
- if (e.kind === "workflow") {
176
- const s = await t.console.workflows.getRun(e.id);
177
- return {
178
- id: e.id,
179
- kind: "workflow",
180
- callableName: e.callableName,
181
- status: s.status,
182
- startedAt: e.startedAt,
183
- finishedAt: e.finishedAt,
184
- durationMs: e.durationMs,
185
- input: s.variables,
186
- output: s.output,
187
- error: s.error,
188
- steps: Q(E(s))
189
- };
190
- }
191
- const o = (await t.request({
192
- method: "GET",
193
- path: `/invocations/${encodeURIComponent(e.id)}`
194
- })).body.invocation;
195
- return {
196
- id: e.id,
197
- kind: e.kind,
198
- callableName: e.callableName,
199
- status: o.status,
200
- startedAt: o.startedAt,
201
- finishedAt: o.finishedAt,
202
- durationMs: o.durationMs,
203
- input: o.input,
204
- output: o.output,
205
- error: o.error
206
- };
207
- }
208
- const j = /* @__PURE__ */ new Set(["succeeded", "failed", "canceled"]);
209
- function L(t) {
210
- return new Promise((e) => setTimeout(e, t));
211
- }
212
- async function O(t, e = L) {
213
- for (let n = 0; n < 600; n++) {
214
- const o = await t();
215
- if (j.has(o.status)) return o;
216
- await e(500);
217
- }
218
- return t();
219
- }
220
- const P = (t) => ["workflows", t];
221
- function W(t, e) {
222
- return t.workflows.list({ project: e });
223
- }
224
- function ft(t, e = !0) {
225
- const n = i();
226
- return y({
227
- queryKey: P(t),
228
- queryFn: () => W(n, t),
229
- enabled: e
230
- });
231
- }
232
- const U = (t) => ["workflow", t];
233
- function x(t, e) {
234
- return t.workflows.get(e);
235
- }
236
- function dt(t, e = !0) {
237
- const n = i();
238
- return y({
239
- queryKey: U(t),
240
- queryFn: () => x(n, t),
241
- enabled: e
242
- });
243
- }
244
- function yt(t) {
245
- const e = i(), n = c();
246
- return a({
247
- mutationFn: (o) => t ? e.console.workflows.upsert(o, { project: t }) : Promise.reject(new Error("No project selected yet.")),
248
- onSuccess: () => n.invalidateQueries({ queryKey: ["workflows"] })
249
- });
250
- }
251
- function mt(t) {
252
- const e = i(), n = c();
253
- return a({
254
- mutationFn: (o) => t ? e.console.workflows.upsert(o.definition, {
255
- project: t,
256
- ifUnmodifiedSince: o.ifUnmodifiedSince
257
- }) : Promise.reject(new Error("No project selected yet.")),
258
- onSuccess: () => n.invalidateQueries({ queryKey: ["workflows"] })
259
- });
260
- }
261
- function pt() {
262
- const t = i(), e = c();
263
- return a({
264
- mutationFn: (n) => t.workflows.archive(n),
265
- onSuccess: () => e.invalidateQueries({ queryKey: ["workflows"] })
266
- });
267
- }
268
- function wt() {
269
- const t = i(), e = c();
270
- return a({
271
- mutationFn: (n) => t.workflows.delete(n),
272
- onSuccess: () => e.invalidateQueries({ queryKey: ["workflows"] })
273
- });
274
- }
275
- const S = (t) => ["runs", t];
276
- function ht(t) {
277
- const e = i();
278
- return y({
279
- queryKey: S(t),
280
- queryFn: () => e.console.workflows.listRuns(t)
281
- });
282
- }
283
- function H(t, e, n, o) {
284
- return t.workflows.run(e, { variables: n, input: o, allowUnpublished: !0 }).then((s) => O(() => t.console.workflows.getRun(s.runId)));
285
- }
286
- function St() {
287
- const t = i(), e = c();
288
- return a({
289
- mutationFn: (n) => H(t, n.id, n.variables, n.input),
290
- onSuccess: (n, o) => e.invalidateQueries({ queryKey: S(o.id) }),
291
- onSettled: () => e.invalidateQueries({ queryKey: R.root })
292
- });
293
- }
294
- function gt(t, e, n, o) {
295
- return t.workflows.run(e, { variables: n, input: o, wait: !0 });
296
- }
297
- function G(t, e, n, o) {
298
- return t.workflows.run(e, { variables: n, input: o, allowUnpublished: !0 }).then((s) => ({ runId: s.runId }));
299
- }
300
- function qt() {
301
- const t = i(), e = c();
302
- return a({
303
- mutationFn: (n) => G(t, n.id, n.variables, n.input),
304
- onSuccess: (n, o) => e.invalidateQueries({ queryKey: S(o.id) }),
305
- onSettled: () => e.invalidateQueries({ queryKey: R.root })
306
- });
307
- }
308
- function Y(t, e) {
309
- return t.workflows.cancel(e);
310
- }
311
- function kt() {
312
- const t = i();
313
- return a({
314
- mutationFn: (e) => Y(t, e)
315
- });
316
- }
317
- function $(t, e) {
318
- return t.console.workflows.getRun(e);
319
- }
320
- const J = (t) => ["run", t];
321
- function Rt(t) {
322
- const e = i();
323
- return y({
324
- queryKey: J(t ?? ""),
325
- queryFn: () => $(e, t),
326
- enabled: t != null,
327
- refetchInterval: (n) => {
328
- var o;
329
- return K((o = n.state.data) == null ? void 0 : o.status) ? 500 : !1;
330
- }
331
- });
332
- }
333
- function vt(t) {
334
- return t.shared ? t.sourceRepo == null ? "pending" : "synced" : "private";
335
- }
336
- function V(t) {
337
- return ["documents", t];
338
- }
339
- function z(t, e) {
340
- return ["documents", "detail", t, e];
341
- }
342
- function bt(t, e, n = !0) {
343
- const o = i();
344
- return y({
345
- queryKey: z(t, e),
346
- queryFn: async () => await o.documents.get(t, { project: e }),
347
- enabled: n
348
- });
349
- }
350
- function Ct(t, e = !0) {
351
- const n = i();
352
- return y({
353
- queryKey: V(t),
354
- // Cast to DocWithProvenance[], same as useDocumentQuery above: the wire
355
- // response already carries `shared`/`source*`/`syncedAt` (repo.list()
356
- // serializes every document the same way repo.get() does), but the SDK's
357
- // own `Doc` type doesn't declare them yet (D-5). Without this cast,
358
- // DocumentsPage.tsx's list rows have no type-visible way to branch on
359
- // `d.shared` the way DocumentDetailPage.tsx already does.
360
- queryFn: async () => await n.documents.list({ project: t }),
361
- enabled: e
362
- });
363
- }
364
- function Et() {
365
- const t = i(), e = c();
366
- return a({
367
- mutationFn: (n) => t.documents.create(n.input, { project: n.project }),
368
- onSuccess: () => e.invalidateQueries({ queryKey: ["documents"] })
369
- });
370
- }
371
- function At() {
372
- const t = i(), e = c();
373
- return a({
374
- mutationFn: (n) => t.documents.update(n.id, n.patch, { project: n.project }),
375
- onSuccess: () => e.invalidateQueries({ queryKey: ["documents"] })
376
- });
377
- }
378
- function Kt() {
379
- const t = i(), e = c();
380
- return a({
381
- mutationFn: (n) => t.documents.delete(n.id, { project: n.project }),
382
- onSuccess: () => e.invalidateQueries({ queryKey: ["documents"] })
383
- });
384
- }
385
- function Ft() {
386
- const t = i(), e = c();
387
- return a({
388
- mutationFn: (n) => t.request({
389
- method: "POST",
390
- path: b`/documents/${n.id}/sync`,
391
- query: { project: n.project }
392
- }),
393
- onSuccess: () => e.invalidateQueries({ queryKey: ["documents"] })
394
- });
395
- }
396
- function Qt(t, e) {
397
- const n = i(), o = c();
398
- return a({
399
- mutationFn: async (s) => (await n.request({
400
- method: "POST",
401
- path: "/spec/import",
402
- body: s
403
- })).body,
404
- // A row exists in every `201` outcome (T2.1.2 §E creates it even when
405
- // some references stayed unresolved), so the list is stale either way —
406
- // but ONLY the list the imported kind actually belongs to (AC-3): the
407
- // unconditional `functionsKey` this used to invalidate left an imported
408
- // Endpoint or Workflow's own list stale while pointlessly invalidating
409
- // Functions.
410
- onSuccess: (s) => C(o, s.kind, e, t)
411
- });
412
- }
413
- export {
414
- P as $,
415
- J as A,
416
- H as B,
417
- gt as C,
418
- S as D,
419
- st as E,
420
- K as F,
421
- G,
422
- q as H,
423
- w as I,
424
- pt as J,
425
- kt as K,
426
- yt as L,
427
- Kt as M,
428
- wt as N,
429
- bt as O,
430
- Ct as P,
431
- Rt as Q,
432
- A as R,
433
- p as S,
434
- St as T,
435
- ht as U,
436
- mt as V,
437
- qt as W,
438
- Ft as X,
439
- dt as Y,
440
- ft as Z,
441
- U as _,
442
- At as a,
443
- Qt as b,
444
- Y as c,
445
- nt as d,
446
- z as e,
447
- vt as f,
448
- V as g,
449
- it as h,
450
- ut as i,
451
- lt as j,
452
- at as k,
453
- ct as l,
454
- $ as m,
455
- x as n,
456
- R as o,
457
- k as p,
458
- F as q,
459
- I as r,
460
- W as s,
461
- Q as t,
462
- Et as u,
463
- O as v,
464
- rt as w,
465
- et as x,
466
- ot as y,
467
- E as z
468
- };
469
- //# sourceMappingURL=spec-import-CW6R_Wk1.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spec-import-CW6R_Wk1.js","sources":["../src/lib/workflow-live-run.ts","../src/lib/history-query.ts","../src/lib/workflow-poll.ts","../src/repos/workflows.ts","../src/repos/documents.ts","../src/repos/spec-import.ts"],"sourcesContent":["/**\n * Pure decision layer for the visual editor's live Run/Stop feature (T2.1.1,\n * A7). Every judgment call this feature makes that is NOT layout — is a run\n * in flight? should polling continue? is the canvas editable right now? what\n * should the Run button say and is it disabled? how does a cancel failure\n * get handled? how does a `RunState`'s steps map to the execution log\n * panel's rows, and what error does each row and the run show? what `input`\n * does the header Run send? — lives here as plain functions of (run state) -> result,\n * with no `.tsx` import and no React import, so `node --test` can load this\n * module directly. Same mechanical reason `workflow-poll.ts` and\n * `repos/reliability-uptime.ts` exist as separate `.ts` modules — read\n * `workflow-poll.ts`'s own header. `WorkflowsPage.tsx` calls these functions\n * rather than restating the conditions inline.\n */\nimport { type RunStatus, isTerminalRunStatus } from \"@w6w/sdk\";\n\nexport type { RunStatus };\n\n/**\n * The five states a workflow step's execution can be in — a thin LOCAL copy\n * of `@w6w/ui`'s `StepStatus` (itself a thin local copy of the engine's\n * `StepStatus` — see `run-visuals.ts`'s own header in `packages/ui`, the\n * same house idiom). `@w6w/sdk/console`'s `RunState.steps` is deliberately\n * typed `Record<string, unknown>` — opaque pass-through, by that module's\n * own documented design — so the real per-step shape has to be re-stated\n * here rather than imported.\n */\nexport type StepStatus = \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n\n/** The per-step metadata (which app/version/action/connection ran) — one\n * local structural copy of the pinned `StepMeta`. A `type` alias, not an\n * `interface`, so it stays assignable to index-signature types. */\nexport type StepMetaLike = {\n app: string;\n version: string;\n action: string;\n connectionId: string | null;\n};\n\n/** The slice of a `StepExecution` this module reads, to build one\n * `ExecutionLogPanel` row. */\nexport interface StepExecutionLike {\n status: StepStatus;\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n /** `StepExecution.error` — a `StepError` on `failed` per rfcs/workflow.md\n * §StepExecution, but read as `unknown` because `RunState.steps` is opaque\n * on the wire; {@link toLogError} normalises whatever actually arrives. */\n error?: unknown;\n /** Recorded metadata; absent (or null) for steps that recorded none. */\n meta?: StepMetaLike | null;\n}\n\n/** A step or run error, as the run log panel renders it — field-for-field\n * `@w6w/ui`'s `ExecutionLogError` (rfcs/workflow.md §StepError's\n * `code`/`message`/`phase`/`retryable`), restated locally for the same reason\n * as {@link ExecutionLogStepLike} below. `message` is never empty. */\nexport interface LogErrorLike {\n code?: string;\n message: string;\n phase?: string;\n retryable?: boolean;\n}\n\n/** One `RunState.stepErrors` entry the panel shows at run level — field-for-field\n * `@w6w/ui`'s `ExecutionLogRecordedError`, restated locally (see above). */\nexport interface RecordedLogErrorLike {\n stepId: string;\n label?: string;\n error: LogErrorLike;\n}\n\n/** The slice of a `RunState` {@link runLevelErrors} reads. */\nexport interface RunErrorSourceLike {\n status?: string;\n error?: unknown;\n stepErrors?: ReadonlyArray<{ nodeId?: string; stepId?: string; error: unknown }>;\n}\n\n/** The per-node execution map of a run record, in either shape — `nodes`\n * preferred, else the legacy `steps`. */\nexport function runNodeMap(\n run: { nodes?: unknown; steps?: unknown } | undefined | null,\n): Record<string, StepExecutionLike> | undefined {\n return (run?.nodes ?? run?.steps ?? undefined) as Record<string, StepExecutionLike> | undefined;\n}\n\n/** The slice of a saved step-test fixture (`StepTest`) {@link latestFixtureInput}\n * reads — `with` is what the trigger's Test tab invokes it with. */\nexport interface StepTestFixtureLike {\n with?: unknown;\n}\n\n/** The row-level fallback for a `failed` step that carries no `error` at all. */\nexport const STEP_FAILED_NO_REASON = \"Node failed without reporting a reason.\";\n\n/** The run-level fallback for a `failed` run where nothing carries a reason. */\nexport const RUN_FAILED_NO_REASON = \"Run failed without reporting a reason.\";\n\n/** One `ExecutionLogPanel` row — field-for-field `@w6w/ui`'s\n * `ExecutionLogStep`, restated locally for the same reason as\n * {@link StepExecutionLike} above (no runtime dependency on `@w6w/ui`,\n * which this module must not import — see the file header). */\nexport interface ExecutionLogStepLike {\n id: string;\n status: StepStatus;\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n error?: LogErrorLike;\n meta?: StepMetaLike;\n}\n\n/** How a cancel-request failure should be handled (A6). */\nexport type CancelErrorOutcome = \"reconcile\" | \"surface\";\n\n/**\n * A2/M1 — the `refetchInterval` decision: keep polling (`true`) until the\n * run's status is terminal (`false`), including while no run has answered\n * yet (`status === undefined` — the very first poll hasn't landed, or no run\n * is active at all).\n */\nexport function shouldContinuePolling(status: RunStatus | undefined): boolean {\n return status === undefined || !isTerminalRunStatus(status);\n}\n\n/**\n * A4/M2/M3 — is a run currently \"in flight\" from this page's point of view?\n * `true` only while the poll has a live, non-terminal status AND the poll\n * itself hasn't given up/errored — a failed poll unlocks the canvas exactly\n * like reaching a real terminal status does (A4's own named failure case: \"a\n * canvas that stays locked after a cancel\"). Drives the canvas's `readOnly`\n * prop, the Stop button's visibility, and the Run button's disabled state —\n * one function, three call sites, so they can never drift out of sync with\n * each other.\n */\nexport function isRunInFlight(status: RunStatus | undefined, pollFailed: boolean): boolean {\n if (pollFailed) return false;\n if (status === undefined) return false;\n return !isTerminalRunStatus(status);\n}\n\n/** A1/A6 — what the Run button should read right now. */\nexport function runButtonLabel(status: RunStatus | undefined, pollFailed: boolean): string {\n if (!isRunInFlight(status, pollFailed)) return \"Run\";\n return status === \"queued\" ? \"Queued…\" : \"Running…\";\n}\n\n/**\n * A6/M6 — classify a `cancel()` failure. `run_not_cancelable` (409) means\n * the run already reached a terminal state before the cancel request landed\n * — not a user-facing error, just reconcile to whatever the next poll\n * reports. Everything else (`unknown_run`, a network failure, …) is a real\n * failure the page's existing error affordance must show.\n */\nexport function classifyCancelError(code: string): CancelErrorOutcome {\n return code === \"run_not_cancelable\" ? \"reconcile\" : \"surface\";\n}\n\n/**\n * G5 — map a `RunState`'s opaque `steps` record onto `ExecutionLogPanel`'s\n * row shape, in the record's own key order (the order the server checkpoints\n * steps in, so it already reads as execution order). `ExecutionLogPanel`'s\n * own contract is \"never re-sorted\" (`ExecutionLogPanel.tsx`'s header), so\n * this function must not reorder either.\n */\nexport function mapRunStateToLogSteps(\n steps: Record<string, StepExecutionLike> | undefined,\n): ExecutionLogStepLike[] {\n if (!steps) return [];\n return Object.entries(steps).map(([id, step]) => ({\n id,\n status: step.status,\n startedAt: step.startedAt,\n finishedAt: step.finishedAt,\n input: step.input,\n output: step.output,\n ...(step.meta !== undefined && step.meta !== null ? { meta: step.meta } : {}),\n ...rowError(step),\n }));\n}\n\n/** The `error` key for one row — present ONLY when the step reports an error\n * or is `failed` (then with {@link STEP_FAILED_NO_REASON}), so a healthy row\n * keeps exactly the shape it had before errors were carried. */\nfunction rowError(step: StepExecutionLike): { error?: LogErrorLike } {\n const error = toLogError(step.error);\n if (error) return { error };\n if (step.status === \"failed\") return { error: { message: STEP_FAILED_NO_REASON } };\n return {};\n}\n\n/**\n * Normalise whatever a step or run reported as its error into the panel's\n * {@link LogErrorLike}. `null`/`undefined` mean \"no error\". A non-empty string\n * is the message. An object contributes `code` (string), `message` (its own\n * non-empty `message`, else a non-empty `code`, else its JSON), `phase`\n * (string) and `retryable` (boolean). Anything else is stringified. The\n * returned `message` is never empty.\n */\nexport function toLogError(raw: unknown): LogErrorLike | undefined {\n if (raw === null || raw === undefined) return undefined;\n if (typeof raw === \"string\" && raw !== \"\") return { message: raw };\n if (typeof raw === \"object\") {\n const o = raw as Record<string, unknown>;\n const code = typeof o.code === \"string\" ? o.code : undefined;\n const message =\n typeof o.message === \"string\" && o.message !== \"\" ? o.message : code || safeJson(raw);\n return {\n ...(code !== undefined ? { code } : {}),\n message: message || \"Unknown error.\",\n ...(typeof o.phase === \"string\" ? { phase: o.phase } : {}),\n ...(typeof o.retryable === \"boolean\" ? { retryable: o.retryable } : {}),\n };\n }\n return { message: String(raw) || \"Unknown error.\" };\n}\n\n/** `JSON.stringify` that answers `\"\"` instead of throwing (a cycle, a BigInt)\n * or returning `undefined` (a `toJSON` that yields nothing). */\nfunction safeJson(raw: unknown): string {\n try {\n return JSON.stringify(raw) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/**\n * The run-level half of the run log: `RunState.error` as `runError`, plus the\n * `RunState.stepErrors` entries whose step has NO row already carrying an\n * error (a `continue-record` failure is usually also on its own row — showing\n * it twice would read as two failures), in their given order. A row showing\n * only {@link STEP_FAILED_NO_REASON} does not count as carrying an error here,\n * so the reason recorded for that step is still surfaced. A `failed` run where\n * nothing — run, rows or surfaced step errors — carries a reason gets\n * {@link RUN_FAILED_NO_REASON}. `runError` is omitted when it duplicates a\n * row's error (equal `message` and equal `code`), since the step failure that\n * stopped the run is already shown on its row. It is likewise omitted when it\n * duplicates a surfaced `stepErrors` entry's error, by the same equality.\n * Keys are omitted when empty.\n */\nexport function runLevelErrors(\n run: RunErrorSourceLike | undefined,\n rows: ReadonlyArray<ExecutionLogStepLike>,\n): { runError?: LogErrorLike; stepErrors?: RecordedLogErrorLike[] } {\n if (!run) return {};\n const carried = new Set(rows.filter((r) => r.error !== undefined).map((r) => r.id));\n const reasoned = new Set(\n rows\n .filter((r) => r.error !== undefined && r.error.message !== STEP_FAILED_NO_REASON)\n .map((r) => r.id),\n );\n const stepErrors = (run.stepErrors ?? [])\n .map((e) => ({ e, id: e.nodeId ?? e.stepId ?? \"\" }))\n .filter(({ id }) => !reasoned.has(id))\n .map(({ e, id }) => ({\n stepId: id,\n error: toLogError(e.error) ?? { message: STEP_FAILED_NO_REASON },\n }));\n const own = toLogError(run.error);\n const sameAsOwn = (e: LogErrorLike | undefined) =>\n own !== undefined && e?.message === own.message && e?.code === own.code;\n const shown = rows.some((r) => sameAsOwn(r.error)) || stepErrors.some((e) => sameAsOwn(e.error));\n let runError = shown ? undefined : own;\n if (!runError && run.status === \"failed\" && carried.size === 0 && stepErrors.length === 0) {\n runError = { message: RUN_FAILED_NO_REASON };\n }\n return {\n ...(runError ? { runError } : {}),\n ...(stepErrors.length > 0 ? { stepErrors } : {}),\n };\n}\n\n/**\n * The header Run's `input`: the LAST saved fixture's `with` (`listStepTests`\n * answers oldest-first — the same \"last is latest\" reading\n * `@w6w/ui`'s `TriggerFillForm` seeds from), when it is a plain object.\n * Sent verbatim — `{type:\"expr\",…}` values included.\n */\nexport function latestFixtureInput(\n tests: ReadonlyArray<StepTestFixtureLike> | undefined,\n): Record<string, unknown> | undefined {\n const last = tests?.[tests.length - 1]?.with;\n if (last === null || typeof last !== \"object\" || Array.isArray(last)) return undefined;\n return last as Record<string, unknown>;\n}\n\n/**\n * Resolve the header Run's `input` for the manual trigger `triggerStepId`.\n * No trigger id → `undefined` without fetching. A fetch that throws or\n * rejects → `undefined`: a missing fixture never blocks the run. Fetched at\n * click time on purpose — a cached `stepTestsKey` query can be stale, since\n * saving a fixture does not invalidate it.\n */\nexport async function resolveHeaderRunInput(\n triggerStepId: string | undefined,\n list: (stepId: string) => Promise<ReadonlyArray<StepTestFixtureLike> | undefined>,\n): Promise<Record<string, unknown> | undefined> {\n if (!triggerStepId) return undefined;\n try {\n return latestFixtureInput(await list(triggerStepId));\n } catch {\n return undefined;\n }\n}\n","// Run: node --test src/lib/__tests__/history-query.test.ts (Node 24, type-stripped)\n//\n// T2.3.1 — the pure data layer behind the project-wide and per-callable\n// History page (T2.4.1) and the Function/Endpoint/Workflow header's History\n// button (T2.4.2). Everything that is a judgment call rather than React\n// plumbing lives here: how a URL's search string becomes a `HistoryFilters`\n// (and back), how a filter set becomes the wire's own query params, the\n// query keys every hook in `repos/history.ts` shares, and how a summary row\n// is expanded into a full detail view for one of the three callable kinds.\n//\n// Zero runtime imports other than `./workflow-live-run.ts` (A1) — every other\n// import here is `import type`, erased at build time, so `node --test` can\n// load this module directly with no React, no SDK runtime, no JSX. The one\n// runtime import reuses `mapRunStateToLogSteps`, the same step mapper the\n// visual editor's live-run overlay already uses, so a workflow's historical\n// detail view renders steps identically to its live one.\n//\n// The wire shape (`ExecutionKind`, `ExecutionStatus`, `ExecutionSummary`,\n// `ExecutionStats`) is pinned verbatim against T2.1.1's own contract — do not\n// drift it; T2.4.1/T2.4.2 are written against this file's exports exactly.\n\nimport type { W6WClient } from \"@w6w/sdk\";\nimport { mapRunStateToLogSteps, runNodeMap } from \"./workflow-live-run.ts\";\n\n// ── wire types (pinned, identical to T2.1.1 §Wire) ──────────────────────\n\nexport type ExecutionKind = \"function\" | \"endpoint\" | \"workflow\";\nexport type ExecutionStatus = \"queued\" | \"running\" | \"succeeded\" | \"failed\" | \"canceled\";\n\nexport interface ExecutionSummary {\n id: string;\n kind: ExecutionKind;\n callableId: string;\n callableName: string;\n status: ExecutionStatus;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n workflowRunId: string | null;\n}\n\nexport interface ExecutionStats {\n total: number;\n succeeded: number;\n failed: number;\n canceled: number;\n inFlight: number;\n successRate: number | null;\n avgDurationMs: number | null;\n}\n\n// ── scope + filters ───────────────────────────────────────────────────────\n\n/** Either the project-wide view or one callable's own history — mutually\n * exclusive, never both, mirroring the wire's own `project`|`callable`\n * params (exactly one). */\nexport type HistoryScope = { project: string } | { callable: string };\n\n/** Everything the History page's filter chrome can set, already parsed out\n * of the URL. `status`/`kind` are `\"\"` for \"any\"; `from`/`to` are the\n * `YYYY-MM-DD` the date pickers hand back, or `\"\"` for unset; `offset` is\n * always a non-negative integer (0 for \"first page\"). */\nexport interface HistoryFilters {\n status: ExecutionStatus | \"\";\n kind: ExecutionKind | \"\";\n from: string;\n to: string;\n q: string;\n offset: number;\n}\n\nexport const EMPTY_HISTORY_FILTERS: HistoryFilters = {\n status: \"\",\n kind: \"\",\n from: \"\",\n to: \"\",\n q: \"\",\n offset: 0,\n};\n\nexport const HISTORY_PAGE_SIZE = 25;\n\nconst VALID_STATUSES: ReadonlySet<string> = new Set([\n \"queued\",\n \"running\",\n \"succeeded\",\n \"failed\",\n \"canceled\",\n]);\nconst VALID_KINDS: ReadonlySet<string> = new Set([\"function\", \"endpoint\", \"workflow\"]);\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** True when `YYYY-MM-DD` names a real calendar day (`2026-02-30` rolls into\n * March through `new Date`, so a round-trip comparison rejects it). */\nfunction isRealDate(s: string): boolean {\n if (!DATE_RE.test(s)) return false;\n const { y, m, d } = dateParts(s);\n const dt = new Date(y, m - 1, d);\n return dt.getFullYear() === y && dt.getMonth() === m - 1 && dt.getDate() === d;\n}\n\n/** Parse a validated `YYYY-MM-DD` string into its three numeric parts. */\nfunction dateParts(value: string): { y: number; m: number; d: number } {\n const [y, m, d] = value.split(\"-\").map(Number);\n return { y, m, d };\n}\n\n/**\n * URL search string → `HistoryFilters`. An unrecognised `status`/`kind`, a\n * `from`/`to` not matching `YYYY-MM-DD`, or a non-integer/negative `offset`\n * all fall back to their empty/zero default rather than carrying a bogus\n * value forward into a request — a stale or hand-edited URL degrades to \"no\n * filter\" instead of erroring.\n */\nexport function filtersFromSearch(search: string): HistoryFilters {\n const params = new URLSearchParams(search);\n const status = params.get(\"status\") ?? \"\";\n const kind = params.get(\"kind\") ?? \"\";\n const from = params.get(\"from\") ?? \"\";\n const to = params.get(\"to\") ?? \"\";\n const q = params.get(\"q\") ?? \"\";\n const offsetRaw = params.get(\"offset\");\n let offset = 0;\n if (offsetRaw !== null) {\n const n = Number(offsetRaw);\n if (Number.isInteger(n) && n >= 0) offset = n;\n }\n return {\n status: VALID_STATUSES.has(status) ? (status as ExecutionStatus) : \"\",\n kind: VALID_KINDS.has(kind) ? (kind as ExecutionKind) : \"\",\n from: isRealDate(from) ? from : \"\",\n to: isRealDate(to) ? to : \"\",\n q,\n offset,\n };\n}\n\n/**\n * `HistoryFilters` → URL search string. `\"\"` when every field is at its\n * default, else a leading-`?` string with only the non-default fields, in\n * the pinned key order `status,kind,from,to,q,offset` (so two renders of the\n * same filters always produce byte-identical URLs — stable for bookmarking\n * and for `filtersFromSearch` round-tripping).\n */\nexport function filtersToSearch(f: HistoryFilters): string {\n const params = new URLSearchParams();\n if (f.status !== \"\") params.set(\"status\", f.status);\n if (f.kind !== \"\") params.set(\"kind\", f.kind);\n if (f.from !== \"\") params.set(\"from\", f.from);\n if (f.to !== \"\") params.set(\"to\", f.to);\n if (f.q !== \"\") params.set(\"q\", f.q);\n if (f.offset > 0) params.set(\"offset\", String(f.offset));\n const s = params.toString();\n return s === \"\" ? \"\" : `?${s}`;\n}\n\n/**\n * `HistoryFilters` + a scope → the wire's own query params (D3/pinned rules).\n * `kind` is sent only for a project scope with a non-empty kind — a\n * per-callable view already knows its one kind, and the server's `kind`\n * param is project-mode-only. `from`/`to` are expanded from the picked\n * calendar day into the half-open `[from, to)` ISO instant range the wire\n * wants — `to` is the NEXT day's midnight so the picked day itself is fully\n * inclusive. `q` is trimmed and omitted when blank (server-side id/name\n * search, D3 — never a payload scan). Paging params are added only when\n * `opts.paged`: `limit` always (defaulting to `HISTORY_PAGE_SIZE`), `offset`\n * only when it would change anything (`> 0`).\n */\nexport function historyRequestQuery(\n scope: HistoryScope,\n f: HistoryFilters,\n opts: { paged: boolean; limit?: number },\n): Record<string, string> {\n const query: Record<string, string> = {};\n\n if (\"project\" in scope) {\n query.project = scope.project;\n if (f.kind !== \"\") query.kind = f.kind;\n } else {\n query.callable = scope.callable;\n }\n\n if (f.status !== \"\") query.status = f.status;\n\n if (f.from !== \"\" && isRealDate(f.from)) {\n const { y, m, d } = dateParts(f.from);\n query.from = new Date(y, m - 1, d).toISOString();\n }\n if (f.to !== \"\" && isRealDate(f.to)) {\n const { y, m, d } = dateParts(f.to);\n query.to = new Date(y, m - 1, d + 1).toISOString();\n }\n\n const q = f.q.trim();\n if (q !== \"\") query.q = q;\n\n if (opts.paged) {\n query.limit = String(opts.limit ?? HISTORY_PAGE_SIZE);\n if (f.offset > 0) query.offset = String(f.offset);\n }\n\n return query;\n}\n\n// ── cache keys (ship from here, never from a caller — mirrors `repos/dashboard.ts`) ──\n\n/**\n * Every key this domain reads or invalidates. `list`/`stats` carry the full\n * scope and filters object so two distinct filter sets never collide on the\n * same cache entry (and the identical pair always do) — react-query's own\n * structural key hashing does the rest.\n */\nexport const historyKeys = {\n root: [\"history\"] as const,\n list(scope: HistoryScope, f: HistoryFilters, limit: number): readonly unknown[] {\n return [\"history\", \"list\", scope, f, limit];\n },\n stats(scope: HistoryScope, f: HistoryFilters): readonly unknown[] {\n return [\"history\", \"stats\", scope, f];\n },\n exists(callableId: string): readonly [\"history\", \"exists\", string] {\n return [\"history\", \"exists\", callableId];\n },\n detail(kind: ExecutionKind, id: string): readonly [\"history\", \"detail\", ExecutionKind, string] {\n return [\"history\", \"detail\", kind, id];\n },\n};\n\n// ── fetchers ─────────────────────────────────────────────────────────────\n\n/** `GET /history` — paged. */\nexport function getHistory(\n client: W6WClient,\n scope: HistoryScope,\n f: HistoryFilters,\n limit: number = HISTORY_PAGE_SIZE,\n): Promise<{ executions: ExecutionSummary[]; hasMore: boolean }> {\n return client\n .request<{ executions: ExecutionSummary[]; hasMore: boolean }>({\n method: \"GET\",\n path: \"/history\",\n query: historyRequestQuery(scope, f, { paged: true, limit }),\n })\n .then((response) => response.body);\n}\n\n/** `GET /history/stats` — unpaged (no `limit`/`offset`). */\nexport function getHistoryStats(\n client: W6WClient,\n scope: HistoryScope,\n f: HistoryFilters,\n): Promise<ExecutionStats> {\n return client\n .request<{ stats: ExecutionStats }>({\n method: \"GET\",\n path: \"/history/stats\",\n query: historyRequestQuery(scope, f, { paged: false }),\n })\n .then((response) => response.body.stats);\n}\n\n/** One execution's full detail — the shape `ExecutionDetail` (`@w6w/ui`,\n * T2.2.2) renders. `steps` is present only for a workflow run; a\n * function/endpoint invocation has none. */\nexport interface ExecutionDetailData {\n id: string;\n kind: ExecutionKind;\n callableName: string;\n status: ExecutionStatus;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n steps?: Array<{\n id: string;\n status: \"pending\" | \"running\" | \"succeeded\" | \"failed\" | \"skipped\";\n startedAt?: string;\n finishedAt?: string;\n input?: unknown;\n output?: unknown;\n }>;\n}\n\n/** The `GET /invocations/:id` response body's shape this module reads\n * (context notes: server `db/repos/invocations.ts` `InvocationRow`). */\ninterface InvocationDetailBody {\n status: ExecutionStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n durationMs: number | null;\n startedAt: string;\n finishedAt: string | null;\n}\n\n/**\n * Expand a list row into its full detail. Function/Endpoint invocations are\n * synchronous calls recorded one row per call (`.claude/docs/invocations.md`)\n * — `GET /invocations/:id` by the escape-hatch `client.request` (no typed SDK\n * method exists for this internal route, same reasoning as\n * `repos/callables.ts`'s `archiveCallable`/`deleteCallable` split; A1: no\n * other runtime import needed). A workflow run instead reuses\n * `client.console.workflows.getRun` (`repos/workflows.ts`'s own\n * `getRunState`) — its `variables` become the detail's `input`, and its\n * opaque `steps` map through the SAME `mapRunStateToLogSteps` the live-run\n * overlay uses, so a historical run's step list renders identically to a\n * live one. `callableName` always comes from the summary — neither read\n * carries a human-readable callable name of its own.\n */\nexport async function getExecutionDetail(\n client: W6WClient,\n summary: ExecutionSummary,\n): Promise<ExecutionDetailData> {\n if (summary.kind === \"workflow\") {\n const run = await client.console.workflows.getRun(summary.id);\n return {\n id: summary.id,\n kind: \"workflow\",\n callableName: summary.callableName,\n status: run.status,\n startedAt: summary.startedAt,\n finishedAt: summary.finishedAt,\n durationMs: summary.durationMs,\n input: run.variables,\n output: run.output,\n error: run.error,\n steps: mapRunStateToLogSteps(runNodeMap(run)),\n };\n }\n\n const response = await client.request<{ invocation: InvocationDetailBody }>({\n method: \"GET\",\n path: `/invocations/${encodeURIComponent(summary.id)}`,\n });\n const invocation = response.body.invocation;\n return {\n id: summary.id,\n kind: summary.kind,\n callableName: summary.callableName,\n status: invocation.status,\n startedAt: invocation.startedAt,\n finishedAt: invocation.finishedAt,\n durationMs: invocation.durationMs,\n input: invocation.input,\n output: invocation.output,\n error: invocation.error,\n };\n}\n","/**\n * The run-polling loop, split out of `api/client.ts`'s original `runWorkflow`\n * into its own PURE module — for the SAME mechanical reason\n * `repos/reliability-uptime.ts` exists (read that file's own header comment in\n * full): a `.ts` module that would otherwise transitively import\n * `../api/apiClient.tsx` (a `.tsx` file Node's type-stripping cannot load at\n * all) must be split out to stay reachable by `node --test`.\n *\n * Ported field-for-field from `api/client.ts`'s original `runWorkflow` (same\n * 500 ms interval, same 600-iteration cap, same \"one more fetch after the\n * loop\" shape) — the ONLY change is the injected `getRun`/`sleep` parameters,\n * which is what makes this loop testable on a fake clock instead of a real\n * 5-minute wait. See `../repos/workflows.ts` for the caller.\n */\nimport type { RunState } from \"@w6w/sdk/console\";\n\nconst TERMINAL = new Set([\"succeeded\", \"failed\", \"canceled\"]);\n\nfunction realSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Poll `getRun` until the run reaches a terminal status, or 600 polls (~5\n * minutes at the default 500ms interval) elapse — whichever comes first.\n * Ported verbatim from `api/client.ts`'s `runWorkflow`; see\n * `../repos/workflows.ts` for the caller.\n */\nexport async function pollRunToTerminal(\n getRun: () => Promise<RunState>,\n sleep: (ms: number) => Promise<void> = realSleep,\n): Promise<RunState> {\n for (let i = 0; i < 600; i++) {\n const run = await getRun();\n if (TERMINAL.has(run.status)) return run;\n await sleep(500);\n }\n return getRun();\n}\n","import {\n type UseMutationResult,\n useMutation,\n useQuery,\n useQueryClient,\n} from \"@tanstack/react-query\";\nimport type { W6WClient, WorkflowRunResult } from \"@w6w/sdk\";\nimport type { RunState } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport { historyKeys } from \"../lib/history-query.ts\";\nimport { shouldContinuePolling } from \"../lib/workflow-live-run.ts\";\nimport { pollRunToTerminal } from \"../lib/workflow-poll.ts\";\n\nexport type { RunState, RunSummary } from \"@w6w/sdk/console\";\nexport type { WorkflowStatus, WorkflowSummary } from \"@w6w/sdk\";\n\n// `project` distinguishes a project-scoped entry (WorkflowsPage.tsx) from the\n// unscoped one (TargetSelector.tsx, SubscriptionsPage.tsx) — genuinely DIFFERENT\n// queries (not a spelling split to unify like T2.2.2's appActions fix). Keep them\n// as distinct cache entries.\nexport const workflowsKey = (project?: string) => [\"workflows\", project] as const;\n\nexport function listWorkflows(client: W6WClient, project?: string) {\n return client.workflows.list({ project });\n}\n\nexport function useWorkflowsQuery(project?: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: workflowsKey(project),\n queryFn: () => listWorkflows(apiClient, project),\n enabled,\n });\n}\n\nexport const workflowKey = (id: string) => [\"workflow\", id] as const;\n\nexport function getWorkflow(client: W6WClient, id: string) {\n return client.workflows.get(id);\n}\n\nexport function useWorkflowQuery(id: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: workflowKey(id),\n queryFn: () => getWorkflow(apiClient, id),\n enabled,\n });\n}\n\n/**\n * A missing `project` here is not \"unscoped\" the way a read can legitimately\n * be — the write would silently land in the account's default project\n * instead of the one the caller is looking at. Both mutations refuse rather\n * than risk that; `WorkflowsPage.tsx`'s own `projectId != null` gate on\n * `useWorkflowsQuery` should mean `project` is always set by the time either\n * of these can actually be invoked from the UI, but the guard costs nothing.\n */\nexport function useCreateWorkflowMutation(project?: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (definition: unknown) => {\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return apiClient.console.workflows.upsert(definition, { project });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useSaveWorkflowMutation(project?: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { definition: unknown; ifUnmodifiedSince: string | null }) => {\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return apiClient.console.workflows.upsert(vars.definition, {\n project,\n ifUnmodifiedSince: vars.ifUnmodifiedSince,\n });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useArchiveWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.workflows.archive(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport function useDeleteWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.workflows.delete(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"workflows\"] }),\n });\n}\n\nexport const runsKey = (workflowId: string) => [\"runs\", workflowId] as const;\n\nexport function useRunsQuery(workflowId: string) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: runsKey(workflowId),\n queryFn: () => apiClient.console.workflows.listRuns(workflowId),\n });\n}\n\n/**\n * Start a run and poll it to a terminal state.\n *\n * `input` is the run's START PAYLOAD, and it is a different thing from\n * `variables`: the server hands it to the entry `@w6w/trigger` node as that\n * node's own output, which is what makes `{{ steps.<trigger>.output.<field> }}`\n * resolve in a real run. Omitted, that node outputs `{}` and every reference to\n * a trigger field resolves to the empty string — the failure mode filed as\n * `.ai/projects/backlog/26-07-29-01-trigger-run-payload.md`, where a step tests\n * green and then does nothing in production. `variables` seeds `vars.*` and\n * reaches the trigger node not at all.\n *\n * Goes through the typed `client.workflows.run()` with\n * `allowUnpublished: true`: this call site always runs the STORED draft, and\n * the server exempts a caller that sets the flag from the publish gate\n * (`packages/api/run-workflow.ts`'s `enqueueRun`). The SDK's result is the flat\n * run body, so the `runId` used to poll comes off `res.runId`.\n */\nexport function runWorkflow(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n): Promise<RunState> {\n return client.workflows\n .run(id, { variables, input, allowUnpublished: true })\n .then((res) => pollRunToTerminal(() => client.console.workflows.getRun(res.runId)));\n}\n\nexport function useRunWorkflowMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n variables: Record<string, unknown>;\n input?: Record<string, unknown>;\n }) => runWorkflow(apiClient, vars.id, vars.variables, vars.input),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\n/**\n * Run a Workflow SYNCHRONOUSLY — the `W6WApi.runWorkflow` facade member's\n * backing function (the Workflows tab's Test stage, D-11/D-15(c)). A sibling\n * of {@link runWorkflow}, NOT a replacement: that function's enqueue-then-poll\n * shape is the studio-wide \"Run this workflow\" action and stays exactly as it\n * is. This one instead sends `wait: true` on the SAME base `client.workflows\n * .run` call already published (`?wait=true` — the server polls internally,\n * up to its own timeout) — zero new server code, and no second poll loop:\n * there is no `pollRunToTerminal` here at all. `terminal`/`httpStatus` on the\n * result distinguish \"finished in time\" (`200`) from \"still going when the\n * server's own wait timed out\" (`202`, a legitimate outcome, not an error).\n */\nexport function runWorkflowSync(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n): Promise<WorkflowRunResult> {\n return client.workflows.run(id, { variables, input, wait: true });\n}\n\n/**\n * T2.1.1 — the ENQUEUE half only: starts a run and returns its handle\n * immediately, without polling it to terminal. A genuine sibling of\n * {@link runWorkflow}, NOT a replacement — that function's \"enqueue, then\n * block to a terminal result\" shape is what `WorkflowDetailPage.tsx`'s \"Run\n * now\" panel is built on and stays exactly as it is. This one is for a host\n * that wants the `runId` right away so it can poll it live itself (the\n * visual editor's canvas + execution log panel) — see {@link useLiveRunQuery}.\n *\n * Like {@link runWorkflow}, this calls `client.workflows.run()` with\n * `allowUnpublished: true` unconditionally. Only `{ runId }` is returned, so\n * callers keep reading `runId` off the resolved value exactly as before.\n */\nexport function startWorkflowRun(\n client: W6WClient,\n id: string,\n variables: Record<string, unknown>,\n input?: Record<string, unknown>,\n) {\n return client.workflows\n .run(id, { variables, input, allowUnpublished: true })\n .then((res) => ({ runId: res.runId }));\n}\n\nexport function useStartRunMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n variables: Record<string, unknown>;\n input?: Record<string, unknown>;\n }) => startWorkflowRun(apiClient, vars.id, vars.variables, vars.input),\n onSuccess: (_res, vars) => qc.invalidateQueries({ queryKey: runsKey(vars.id) }),\n onSettled: () => qc.invalidateQueries({ queryKey: historyKeys.root }),\n });\n}\n\n/** What `client.workflows.cancel` resolves to. Named here because the SDK's root entry does not\n * export its `WorkflowCancelResult`: an inferred return type would name it and `vite-plugin-dts`\n * would skip this whole file (TS2742), leaving every `./repos` declaration out of the tarball. */\nexport type WorkflowCancelResult = Awaited<ReturnType<W6WClient[\"workflows\"][\"cancel\"]>>;\n\n/**\n * T2.1.1/A6 — cancel a queued or running run. `client.workflows.cancel`\n * itself never claims the run has stopped (its own doc comment: a `202`\n * means the request was RECORDED, not that the run finished) — the caller\n * keeps polling {@link useLiveRunQuery} until the run actually reaches a\n * terminal status. See `../lib/workflow-live-run.ts`'s `classifyCancelError`\n * for how a `409 run_not_cancelable` (the run beat the cancel to the finish\n * line) is told apart from a real failure.\n */\nexport function cancelWorkflowRun(client: W6WClient, runId: string): Promise<WorkflowCancelResult> {\n return client.workflows.cancel(runId);\n}\n\nexport function useCancelRunMutation(): UseMutationResult<WorkflowCancelResult, Error, string> {\n const apiClient = useEmbedClient();\n return useMutation({\n mutationFn: (runId: string) => cancelWorkflowRun(apiClient, runId),\n });\n}\n\n/** The single-shot half of {@link useLiveRunQuery} — a thin, directly\n * testable wrapper around `client.console.workflows.getRun`, so the polling\n * config below can be pinned without needing to render a hook. */\nexport function getRunState(client: W6WClient, runId: string): Promise<RunState> {\n return client.console.workflows.getRun(runId);\n}\n\n/** Query key for one run's live state — distinct from {@link runsKey}, which\n * is the workflow's run LIST. */\nexport const runStateKey = (runId: string) => [\"run\", runId] as const;\n\n/**\n * T2.1.1/A2/A3 — poll one run's live state at a fixed 500ms interval,\n * stopping once it reaches a terminal status ({@link shouldContinuePolling},\n * `../lib/workflow-live-run.ts`). A genuine sibling of `pollRunToTerminal`\n * (`../lib/workflow-poll.ts`) using the SAME underlying SDK call\n * (`client.console.workflows.getRun`), but publishing every intermediate\n * `RunState` to its caller via TanStack Query's own `data` — unlike\n * `pollRunToTerminal`, which discards every non-terminal result and hands\n * back only the last one. `runId === null` disables the query entirely (no\n * run started yet, or the page navigated to a different workflow).\n */\nexport function useLiveRunQuery(runId: string | null) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: runStateKey(runId ?? \"\"),\n queryFn: () => getRunState(apiClient, runId as string),\n enabled: runId != null,\n refetchInterval: (query) => (shouldContinuePolling(query.state.data?.status) ? 500 : false),\n });\n}\n","/**\n * The `documents` domain repo — wraps `@w6w/sdk`'s `client.documents.*` in\n * react-query (HITL-6). `QueryClientProvider` (`main.tsx`) stays the actual\n * cache; this module only centralizes the query-key factory and the\n * `queryFn`/`mutationFn` pairs so every page reads documents the same way.\n *\n * Documents are project-scoped (`documents.ts`'s `DocumentOptions.project`);\n * every mutation here invalidates the unscoped `[\"documents\"]` key, which\n * prefix-matches every project-scoped query key produced by\n * {@linkcode documentsKey} — the same invalidation shape `DocumentsPage.tsx`\n * used before this migration.\n */\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { path, type Doc, type DocumentCreateInput, type DocumentPatch } from \"@w6w/sdk\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\n/**\n * T1.1.1's wire shape for one document, pinned here ahead of that node\n * merging (this node is dispatched speculatively against it — see this\n * task's contract). `shared` and the six `source*`/`syncedAt` fields are all\n * additive over the SDK's own `Doc`, so a locally-created document simply\n * carries them as `null` (or `false` for `shared`) rather than omitting\n * them. Do not rename a field — the server produces these names verbatim.\n */\nexport interface DocWithProvenance extends Doc {\n shared: boolean;\n /** \"owner/name\" of the bound repository this document was pulled from. */\n sourceRepo: string | null;\n /** Repo-relative file path the document was pulled from. */\n sourcePath: string | null;\n /** The pulled file's content hash — NOT a commit SHA. */\n sourceSha: string | null;\n /** The repository's HEAD commit SHA at pull time — NOT a content hash. */\n sourceRefSha: string | null;\n /** Web link to the file; may be absent even when the rest of provenance is set. */\n sourceUrl: string | null;\n /** ISO-8601. Stamped at the document's last actual change, not at every sync. */\n syncedAt: string | null;\n}\n\n/**\n * Which provenance state `DocumentDetailPage.tsx`'s \"Source\" card should\n * render for `doc`. `shared` (not `sourceRepo`) is the gate: a shared\n * document whose provenance columns haven't been stamped yet (any document\n * synced before this feature shipped, until its next real-content sync —\n * tier-1 \"unchanged\" syncs never restamp provenance) is still shared, and\n * must say so, distinct from a genuinely private document.\n *\n * - `\"private\"` — `doc.shared` is false. No card.\n * - `\"pending\"` — shared, but `sourceRepo` hasn't been stamped yet.\n * - `\"synced\"` — shared, with full provenance available.\n */\nexport function documentProvenanceState(doc: DocWithProvenance): \"private\" | \"pending\" | \"synced\" {\n if (!doc.shared) return \"private\";\n return doc.sourceRepo == null ? \"pending\" : \"synced\";\n}\n\n/** Query key for a documents list, optionally scoped to a project. */\nexport function documentsKey(projectId?: string) {\n return [\"documents\", projectId] as const;\n}\n\n/**\n * Query key for a single document, scoped to a project (mirrors\n * {@linkcode useDocumentsQuery}'s fix at :72-79/:80-87 below — `projectId`\n * belongs in the key itself, not just the `queryFn`, so a render where the\n * key was cached under `projectId === undefined` genuinely changes key once\n * `ProjectContext` resolves the real one, instead of reusing the same cache\n * entry — and its `retry: false` wrong-project 404 — forever). Still sits\n * under the bare `[\"documents\"]` prefix every mutation below invalidates, so\n * an edit/delete refreshes this page too — `\"detail\"` keeps it from\n * colliding with {@linkcode documentsKey}'s own `[\"documents\", projectId]`\n * shape.\n */\nexport function documentKey(id: string, projectId?: string) {\n return [\"documents\", \"detail\", id, projectId] as const;\n}\n\n/**\n * A single document by id, cast to {@link DocWithProvenance} (D-5): the SDK's\n * `Doc` doesn't model T1.1.1's provenance fields yet, and this repo is not\n * the place to fork or extend `@w6w/sdk` (D-4). The `project` option is\n * passed exactly as {@linkcode useDocumentsQuery} passes it — a document in a\n * non-default project 404s without it. `enabled` defaults `true` to preserve\n * that unscoped fallback for a caller that genuinely wants it — same as\n * {@linkcode useDocumentsQuery}'s own `enabled` doc comment below — a\n * project-scoped page should instead pass `enabled: projectId != null` so it\n * never queries (and never renders) against the wrong project while\n * `ProjectContext`'s own project list is still resolving.\n */\nexport function useDocumentQuery(id: string, projectId?: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: documentKey(id, projectId),\n queryFn: async () =>\n (await apiClient.documents.get(id, { project: projectId })) as DocWithProvenance,\n enabled,\n });\n}\n\n/**\n * The current project's documents (or the tenant default when unscoped).\n * `enabled` defaults `true` to preserve that unscoped fallback for a caller\n * that genuinely wants it — a project-scoped page should instead pass\n * `enabled: projectId != null` so it never queries (and never renders)\n * against the wrong project while `ProjectContext`'s own project list is\n * still resolving.\n */\nexport function useDocumentsQuery(projectId?: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: documentsKey(projectId),\n // Cast to DocWithProvenance[], same as useDocumentQuery above: the wire\n // response already carries `shared`/`source*`/`syncedAt` (repo.list()\n // serializes every document the same way repo.get() does), but the SDK's\n // own `Doc` type doesn't declare them yet (D-5). Without this cast,\n // DocumentsPage.tsx's list rows have no type-visible way to branch on\n // `d.shared` the way DocumentDetailPage.tsx already does.\n queryFn: async () =>\n (await apiClient.documents.list({ project: projectId })) as DocWithProvenance[],\n enabled,\n });\n}\n\nexport function useCreateDocumentMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { input: DocumentCreateInput; project?: string }) =>\n apiClient.documents.create(vars.input, { project: vars.project }),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"documents\"] }),\n });\n}\n\nexport function useUpdateDocumentMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; patch: DocumentPatch; project?: string }) =>\n apiClient.documents.update(vars.id, vars.patch, { project: vars.project }),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"documents\"] }),\n });\n}\n\nexport function useDeleteDocumentMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; project?: string }) =>\n apiClient.documents.delete(vars.id, { project: vars.project }),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"documents\"] }),\n });\n}\n\n/**\n * Re-pulls a shared document from its bound repository (\"Sync\" button, T2.1.4)\n * — `POST /documents/:id/sync` (T3.1.1). No SDK method exists for this route\n * yet (D-4/D-5), so this goes through `apiClient.request()` directly, same\n * escape hatch `repo-sync.ts`'s `useSyncRepoNowMutation` uses. The document\n * routes are project-scoped by QUERY param, not a path segment (unlike\n * `repo-binding`'s `/projects/:id/...` shape), so `project` travels in\n * `query`, mirroring {@linkcode useDocumentQuery}'s own `{ project: … }` use.\n */\nexport function useSyncDocumentMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; project?: string }) =>\n apiClient.request<{ document: DocWithProvenance }>({\n method: \"POST\",\n path: path`/documents/${vars.id}/sync`,\n query: { project: vars.project },\n }),\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"documents\"] }),\n });\n}\n","/**\n * The `/spec/import` repo (T3.2.1). A NEW file, deliberately kept out of\n * `repos/functions.ts` / `repos/endpoints.ts` (T3.1.1 owns both) so the two\n * nodes never collide on the same file.\n *\n * **Every operation here goes through `W6WClient.request<T>()`, never\n * `apiClient.console.*`.** `T2.1.2`'s `inputs.touch` has no\n * `packages/wrappers` entry — there is no SDK method for this route — so\n * `request()` is the client's public escape hatch, exactly as\n * `repos/vars.ts`'s own docblock explains for the same reason.\n *\n * The posted `document` is forwarded to the server VERBATIM: this module\n * shapes nothing, validates nothing, and — this is the mechanism pin note 1\n * of the contract states from the side a wrong implementation must break —\n * never falls back to the sibling whole-definition save mutation\n * `FunctionIdentityModal.tsx` uses, on any response. `/spec/import` is where\n * the server-side sealed-secret walker lives (T2.1.2 §B runs\n * `assertNoSecretEnvelopes` over the WHOLE supplied body before any write);\n * a \"helpful\" fallback to that other write path would route a pasted\n * document straight around that check.\n *\n * T1.2.1 generalizes this over all three kinds: `onSuccess` invalidates the\n * ONE list key the imported document's own kind reads (`result.kind`, which\n * the server always echoes), never an unconditional `functionsKey`. The\n * decision of which key that is lives in `../lib/spec-import-invalidation.ts`\n * (a pure, `node --test`-loadable module). The three list keys are INJECTED by the host\n * (`listKeys`): Studio's `functionsKey`/`endpointsKey` live in its own `repos/callables`.\n */\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport {\n type SpecImportListKeys,\n invalidateImportedCallable,\n} from \"../lib/spec-import-invalidation.ts\";\n\n/**\n * Mirrors `T2.1.1`'s `SpecDocument` (`T2.1.1.contract.md:134-141`): the\n * portable document a `GET /<kind>/:id/spec` export produces and this\n * route consumes. Not a bare `FunctionDef` — connection/var references ride\n * as re-bindable `rebind` entries, never live ids.\n */\nexport interface SpecImportDocument {\n specVersion: string;\n kind: \"function\" | \"endpoint\" | \"workflow\";\n callable: Record<string, unknown>;\n rebind: unknown[];\n}\n\n/** One reference site's outcome (T2.1.2 §E's `SpecImportReferenceReport`). */\nexport interface SpecImportReferenceReport {\n path: string;\n kind: string;\n resolved: boolean;\n /** Present only when `resolved` is `true`. */\n boundTo?: string;\n /** Present only when `resolved` is `false`. */\n reason?: string;\n}\n\n/** The `201` body `POST /spec/import` returns (T2.1.2 §E). */\nexport interface SpecImportResult {\n kind: \"function\" | \"endpoint\" | \"workflow\";\n callable: { id: string; key?: string; name?: string };\n references: SpecImportReferenceReport[];\n}\n\n/**\n * `POST /spec/import`. Success is always `201` — including a partially\n * resolved import (T2.1.2 §E: \"report, never fail silently\"). This mutation\n * resolves on ANY `201`; branching on `references.every(r => r.resolved)` is\n * the caller's job (A5), never this repo's.\n *\n * `project` is the caller's current project — only the workflow arm reads it\n * (`listKeys.workflowsKey(project)`), but every caller passes it uniformly rather than branching on kind itself; see\n * `../lib/spec-import-invalidation.ts` for why the key differs by kind.\n */\nexport function useImportSpecMutation(project: string | undefined, listKeys: SpecImportListKeys) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (document: Record<string, unknown>) => {\n const res = await apiClient.request<SpecImportResult>({\n method: \"POST\",\n path: \"/spec/import\",\n body: document,\n });\n return res.body;\n },\n // A row exists in every `201` outcome (T2.1.2 §E creates it even when\n // some references stayed unresolved), so the list is stale either way —\n // but ONLY the list the imported kind actually belongs to (AC-3): the\n // unconditional `functionsKey` this used to invalidate left an imported\n // Endpoint or Workflow's own list stale while pointlessly invalidating\n // Functions.\n onSuccess: (result) => invalidateImportedCallable(qc, result.kind, listKeys, project),\n });\n}\n"],"names":["runNodeMap","run","STEP_FAILED_NO_REASON","RUN_FAILED_NO_REASON","shouldContinuePolling","status","isTerminalRunStatus","isRunInFlight","pollFailed","runButtonLabel","classifyCancelError","code","mapRunStateToLogSteps","steps","id","step","rowError","error","toLogError","raw","o","message","safeJson","runLevelErrors","rows","carried","reasoned","stepErrors","e","own","sameAsOwn","runError","latestFixtureInput","tests","last","_a","resolveHeaderRunInput","triggerStepId","list","EMPTY_HISTORY_FILTERS","HISTORY_PAGE_SIZE","VALID_STATUSES","VALID_KINDS","DATE_RE","isRealDate","s","y","m","d","dateParts","dt","value","filtersFromSearch","search","params","kind","from","to","q","offsetRaw","offset","n","filtersToSearch","f","historyRequestQuery","scope","opts","query","historyKeys","limit","callableId","getHistory","client","response","getHistoryStats","getExecutionDetail","summary","invocation","TERMINAL","realSleep","ms","resolve","pollRunToTerminal","getRun","sleep","i","workflowsKey","project","listWorkflows","useWorkflowsQuery","enabled","apiClient","useEmbedClient","useQuery","workflowKey","getWorkflow","useWorkflowQuery","useCreateWorkflowMutation","qc","useQueryClient","useMutation","definition","useSaveWorkflowMutation","vars","useArchiveWorkflowMutation","useDeleteWorkflowMutation","runsKey","workflowId","useRunsQuery","runWorkflow","variables","input","res","useRunWorkflowMutation","_res","runWorkflowSync","startWorkflowRun","useStartRunMutation","cancelWorkflowRun","runId","useCancelRunMutation","getRunState","runStateKey","useLiveRunQuery","documentProvenanceState","doc","documentsKey","projectId","documentKey","useDocumentQuery","useDocumentsQuery","useCreateDocumentMutation","useUpdateDocumentMutation","useDeleteDocumentMutation","useSyncDocumentMutation","path","useImportSpecMutation","listKeys","document","result","invalidateImportedCallable"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"step-tests-CivICmTq.js","sources":["../src/repos/step-tests.ts"],"sourcesContent":["/**\n * The `step tests` domain repo — wraps `@w6w/sdk`'s `client.console.stepTests.*`\n * (T2.6.1). Unlike every other domain migrated so far, its one read\n * (`listStepTests`) exports ONLY a query-key factory + a plain, explicit-client\n * fetcher — no hook. `WorkflowsPage.tsx`'s `stepTestsQueries` (`useQueries`\n * looping over `testGatedSteps`) is the sole read call site and cannot call a\n * hook inside `.map(...)` (Rules of Hooks); no other studio call site needs a\n * hook form. Mirrors `repos/apps.ts`'s \"build what's needed\" discipline,\n * applied to a query for the first time (every prior no-hook export in this\n * project was a mutation).\n *\n * None of these methods take a `project` scoping parameter — step tests are\n * scoped by workflow/tenant server-side, mirroring `console.connections`'s\n * own host shape.\n */\nimport type { W6WClient } from \"@w6w/sdk\";\nimport type { StepTest } from \"@w6w/sdk/console\";\n\nexport type { StepTest } from \"@w6w/sdk/console\";\n\n// ── step tests (list) — key + plain fetcher ONLY, no hook. See header. ────\n\nexport const stepTestsKey = (workflowId: string, stepId: string) =>\n [\"stepTests\", workflowId, stepId] as const;\n\nexport function listStepTests(\n client: W6WClient,\n workflowId: string,\n stepId: string,\n): Promise<StepTest[]> {\n return client.console.stepTests.list(workflowId, stepId);\n}\n\n// ── mutations (facade-only) ─────────────────────────────────────────────\n\nexport function saveStepTest(\n client: W6WClient,\n workflowId: string,\n stepId: string,\n body: { name?: string; input: Record<string, unknown>; with: Record<string, unknown> },\n): Promise<StepTest> {\n return client.console.stepTests.save(workflowId, stepId, body);\n}\n\n/** Same void-discard reasoning as `recordTestRun` above — see that function's doc comment. */\nexport function recordStepTestRun(\n client: W6WClient,\n workflowId: string,\n stepId: string,\n body: {\n stepTestId?: string | null;\n status: string;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n meta?: unknown;\n },\n): Promise<void> {\n return client.console.stepTests.recordRun(workflowId, stepId, body).then(() => undefined);\n}\n"],"names":["stepTestsKey","workflowId","stepId","listStepTests","client","saveStepTest","body","recordStepTestRun"],"mappings":"AAsBO,MAAMA,IAAe,CAACC,GAAoBC,MAC/C,CAAC,aAAaD,GAAYC,CAAM;AAE3B,SAASC,EACdC,GACAH,GACAC,GACqB;AACrB,SAAOE,EAAO,QAAQ,UAAU,KAAKH,GAAYC,CAAM;AACzD;AAIO,SAASG,EACdD,GACAH,GACAC,GACAI,GACmB;AACnB,SAAOF,EAAO,QAAQ,UAAU,KAAKH,GAAYC,GAAQI,CAAI;AAC/D;AAGO,SAASC,EACdH,GACAH,GACAC,GACAI,GAQe;AACf,SAAOF,EAAO,QAAQ,UAAU,UAAUH,GAAYC,GAAQI,CAAI,EAAE,KAAK,MAAA;AAAA,GAAe;AAC1F;"}