@skaile/workspaces 2.1.0 → 2.3.0

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 (198) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +33 -3
  3. package/dist/{asset-feeds-FBGBQEYD.js → asset-feeds-DKNYRLED.js} +10 -10
  4. package/dist/{asset-feeds-FBGBQEYD.js.map → asset-feeds-DKNYRLED.js.map} +1 -1
  5. package/dist/asset-manager/catalog-deployer.js +5 -5
  6. package/dist/asset-manager/index.js +9 -9
  7. package/dist/asset-manager/installer.js +6 -6
  8. package/dist/bridge/drivers/claude-sdk.js +9 -6
  9. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  10. package/dist/bridge/drivers/codex.js +1 -1
  11. package/dist/bridge/drivers/continue.js +2 -2
  12. package/dist/bridge/drivers/echo.js +1 -1
  13. package/dist/bridge/drivers/gemini.js +3 -3
  14. package/dist/bridge/drivers/goose.js +2 -2
  15. package/dist/bridge/drivers/omp.js +1 -1
  16. package/dist/bridge/drivers/opencode.js +2 -2
  17. package/dist/bridge/drivers/qwen.js +3 -3
  18. package/dist/bridge/index.js +2 -2
  19. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  20. package/dist/{chunk-ZWFLEMI4.js → chunk-3F54MH2T.js} +4 -4
  21. package/dist/{chunk-ZWFLEMI4.js.map → chunk-3F54MH2T.js.map} +1 -1
  22. package/dist/{chunk-RTLQAZAE.js → chunk-63ZPKREA.js} +3 -3
  23. package/dist/{chunk-RTLQAZAE.js.map → chunk-63ZPKREA.js.map} +1 -1
  24. package/dist/{chunk-MLYV6WEM.js → chunk-7IRH7MGV.js} +10 -10
  25. package/dist/{chunk-MLYV6WEM.js.map → chunk-7IRH7MGV.js.map} +1 -1
  26. package/dist/{chunk-Y6VSFX2A.js → chunk-7UZGKVSK.js} +3 -3
  27. package/dist/{chunk-Y6VSFX2A.js.map → chunk-7UZGKVSK.js.map} +1 -1
  28. package/dist/{chunk-XQVP6XWR.js → chunk-BFIK6NPZ.js} +3 -3
  29. package/dist/{chunk-XQVP6XWR.js.map → chunk-BFIK6NPZ.js.map} +1 -1
  30. package/dist/{chunk-L26NGI43.js → chunk-BLWNI5KW.js} +2 -2
  31. package/dist/{chunk-L26NGI43.js.map → chunk-BLWNI5KW.js.map} +1 -1
  32. package/dist/{chunk-CTWE7I7Z.js → chunk-CERGXDGG.js} +4 -4
  33. package/dist/{chunk-CTWE7I7Z.js.map → chunk-CERGXDGG.js.map} +1 -1
  34. package/dist/{chunk-VPXBAEWE.js → chunk-CILACPUC.js} +8 -8
  35. package/dist/{chunk-VPXBAEWE.js.map → chunk-CILACPUC.js.map} +1 -1
  36. package/dist/{chunk-43TAGQ3Z.js → chunk-CXX3UGJP.js} +8 -8
  37. package/dist/{chunk-43TAGQ3Z.js.map → chunk-CXX3UGJP.js.map} +1 -1
  38. package/dist/chunk-DZM33LQO.js +38 -0
  39. package/dist/chunk-DZM33LQO.js.map +1 -0
  40. package/dist/{chunk-PSVF3LDU.js → chunk-ETFETLLB.js} +6 -6
  41. package/dist/{chunk-PSVF3LDU.js.map → chunk-ETFETLLB.js.map} +1 -1
  42. package/dist/{chunk-Y662DNQQ.js → chunk-FB4GPWYC.js} +18 -15
  43. package/dist/chunk-FB4GPWYC.js.map +1 -0
  44. package/dist/{chunk-BTR3ZJ7S.js → chunk-G2ILW47R.js} +4 -4
  45. package/dist/{chunk-BTR3ZJ7S.js.map → chunk-G2ILW47R.js.map} +1 -1
  46. package/dist/{chunk-2BSXXTUP.js → chunk-LD6YGIKZ.js} +105 -16
  47. package/dist/chunk-LD6YGIKZ.js.map +1 -0
  48. package/dist/{chunk-HOL5KD7U.js → chunk-PTS3QN5P.js} +67 -25
  49. package/dist/chunk-PTS3QN5P.js.map +1 -0
  50. package/dist/{chunk-YODP3STD.js → chunk-Q26C5GLO.js} +3 -3
  51. package/dist/{chunk-YODP3STD.js.map → chunk-Q26C5GLO.js.map} +1 -1
  52. package/dist/{chunk-GUKMNUQK.js → chunk-RIEXN7WA.js} +2 -2
  53. package/dist/{chunk-GUKMNUQK.js.map → chunk-RIEXN7WA.js.map} +1 -1
  54. package/dist/chunk-SIF5F5SN.js +86 -0
  55. package/dist/chunk-SIF5F5SN.js.map +1 -0
  56. package/dist/{chunk-RBOPTTTK.js → chunk-TAJBFYCT.js} +32 -17
  57. package/dist/chunk-TAJBFYCT.js.map +1 -0
  58. package/dist/{chunk-MAN7AGQJ.js → chunk-TK66CMXV.js} +21 -6
  59. package/dist/chunk-TK66CMXV.js.map +1 -0
  60. package/dist/{chunk-5BGEYZ7I.js → chunk-UFY2HFLO.js} +3 -3
  61. package/dist/{chunk-5BGEYZ7I.js.map → chunk-UFY2HFLO.js.map} +1 -1
  62. package/dist/{chunk-N6TYW6EB.js → chunk-UNP4M5ZZ.js} +4 -4
  63. package/dist/{chunk-N6TYW6EB.js.map → chunk-UNP4M5ZZ.js.map} +1 -1
  64. package/dist/{chunk-HPGV54O4.js → chunk-UQ3RJKDD.js} +41 -23
  65. package/dist/chunk-UQ3RJKDD.js.map +1 -0
  66. package/dist/{chunk-XSIXGVH6.js → chunk-W3Q37HEF.js} +4 -4
  67. package/dist/{chunk-XSIXGVH6.js.map → chunk-W3Q37HEF.js.map} +1 -1
  68. package/dist/{chunk-WVPL4OGD.js → chunk-WG3L5VHF.js} +2 -2
  69. package/dist/{chunk-WVPL4OGD.js.map → chunk-WG3L5VHF.js.map} +1 -1
  70. package/dist/{chunk-SGLGA2AZ.js → chunk-X6BPVUV2.js} +3 -3
  71. package/dist/{chunk-SGLGA2AZ.js.map → chunk-X6BPVUV2.js.map} +1 -1
  72. package/dist/chunk-ZE2KEPE2.js +1002 -0
  73. package/dist/chunk-ZE2KEPE2.js.map +1 -0
  74. package/dist/{chunk-BHLNQ4L5.js → chunk-ZNIHTT22.js} +3 -3
  75. package/dist/{chunk-BHLNQ4L5.js.map → chunk-ZNIHTT22.js.map} +1 -1
  76. package/dist/{chunk-PYYL5XMA.js → chunk-ZR5Q4KZK.js} +3 -3
  77. package/dist/{chunk-PYYL5XMA.js.map → chunk-ZR5Q4KZK.js.map} +1 -1
  78. package/dist/cli/index.js +53 -50
  79. package/dist/cli/index.js.map +1 -1
  80. package/dist/connectors/config.js +6 -6
  81. package/dist/connectors/index.js +11 -9
  82. package/dist/core/index.js +5 -5
  83. package/dist/core/runtime-assets.js +3 -3
  84. package/dist/core/workspace-config.js +2 -2
  85. package/dist/deploy/index.js +5 -5
  86. package/dist/discovery/index.js +1 -1
  87. package/dist/discovery/src/requires-graph.d.ts +1 -1
  88. package/dist/discovery/src/requires-graph.d.ts.map +1 -1
  89. package/dist/{ensure-sources-AVCVX7CV.js → ensure-sources-R6KW7K3M.js} +12 -12
  90. package/dist/{ensure-sources-AVCVX7CV.js.map → ensure-sources-R6KW7K3M.js.map} +1 -1
  91. package/dist/factory-assets/connectors/box.js +11 -9
  92. package/dist/factory-assets/connectors/deploy.js +11 -9
  93. package/dist/factory-assets/connectors/devserver.js +11 -9
  94. package/dist/factory-assets/connectors/flow/CONNECTOR.md +7 -1
  95. package/dist/factory-assets/connectors/flow/adapter.d.ts +2 -3
  96. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  97. package/dist/factory-assets/connectors/flow/adapter.js +11 -9
  98. package/dist/factory-assets/connectors/flow/contract/expression.d.ts +46 -0
  99. package/dist/factory-assets/connectors/flow/contract/expression.d.ts.map +1 -0
  100. package/dist/factory-assets/connectors/flow/contract/flow.v2.schema.json +948 -0
  101. package/dist/factory-assets/connectors/flow/contract/hash.d.ts +6 -0
  102. package/dist/factory-assets/connectors/flow/contract/hash.d.ts.map +1 -0
  103. package/dist/factory-assets/connectors/flow/contract/index.d.ts +6 -0
  104. package/dist/factory-assets/connectors/flow/contract/index.d.ts.map +1 -0
  105. package/dist/factory-assets/connectors/flow/contract/json-schema.d.ts +6 -0
  106. package/dist/factory-assets/connectors/flow/contract/json-schema.d.ts.map +1 -0
  107. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts +38 -0
  108. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -0
  109. package/dist/factory-assets/connectors/flow/contract/schema.d.ts +364 -0
  110. package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -0
  111. package/dist/factory-assets/connectors/flow/contract.d.ts +2 -0
  112. package/dist/factory-assets/connectors/flow/contract.js +5 -0
  113. package/dist/factory-assets/connectors/flow/contract.js.map +1 -0
  114. package/dist/factory-assets/connectors/flow/engine/engine.d.ts +4 -4
  115. package/dist/factory-assets/connectors/flow/engine/engine.d.ts.map +1 -1
  116. package/dist/factory-assets/connectors/flow/engine/flow-kind-provider.d.ts +1 -1
  117. package/dist/factory-assets/connectors/flow/engine/flow-kind-provider.d.ts.map +1 -1
  118. package/dist/factory-assets/connectors/flow/engine/loader.d.ts.map +1 -1
  119. package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts +20 -0
  120. package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts.map +1 -0
  121. package/dist/factory-assets/connectors/flow/engine/types.d.ts +56 -28
  122. package/dist/factory-assets/connectors/flow/engine/types.d.ts.map +1 -1
  123. package/dist/factory-assets/connectors/flow/engine.js +8 -6
  124. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts +4 -6
  125. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts.map +1 -1
  126. package/dist/factory-assets/connectors/flow/prompt-fragments.js +2 -1
  127. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  128. package/dist/factory-assets/connectors/flow/run-flow.js +12 -10
  129. package/dist/factory-assets/connectors/flow.js +11 -9
  130. package/dist/factory-assets/connectors/git.js +11 -9
  131. package/dist/factory-assets/connectors/gmail.js +11 -9
  132. package/dist/factory-assets/connectors/googledrive.js +11 -9
  133. package/dist/factory-assets/connectors/local.js +11 -9
  134. package/dist/factory-assets/connectors/mattermost.js +11 -9
  135. package/dist/factory-assets/connectors/memory.js +11 -9
  136. package/dist/factory-assets/connectors/minio.js +11 -9
  137. package/dist/factory-assets/connectors/postgres.js +11 -9
  138. package/dist/factory-assets/connectors/s3.js +11 -9
  139. package/dist/factory-assets/connectors/sharepoint.js +11 -9
  140. package/dist/factory-assets/connectors/sqlite.js +11 -9
  141. package/dist/factory-assets/connectors/static-server.js +11 -9
  142. package/dist/factory-assets/connectors/tunnel.js +11 -9
  143. package/dist/factory-assets/connectors/webdav.js +11 -9
  144. package/dist/factory-assets/connectors/xstate-store.js +11 -9
  145. package/dist/factory-assets/connectors/xstate.js +11 -9
  146. package/dist/{flows-CXVFGR27.js → flows-F3CJNMK6.js} +8 -8
  147. package/dist/{flows-CXVFGR27.js.map → flows-F3CJNMK6.js.map} +1 -1
  148. package/dist/{helpers-M5SXB4LL.js → helpers-KPOLCGKX.js} +12 -12
  149. package/dist/{helpers-M5SXB4LL.js.map → helpers-KPOLCGKX.js.map} +1 -1
  150. package/dist/library/index.js +7 -7
  151. package/dist/library/install.js +5 -5
  152. package/dist/{library-publish-HVIIQMI6.js → library-publish-ZAPZS64O.js} +18 -16
  153. package/dist/library-publish-ZAPZS64O.js.map +1 -0
  154. package/dist/{open-library-EJQISBWV.js → open-library-I4F2UNOY.js} +16 -14
  155. package/dist/{open-library-EJQISBWV.js.map → open-library-I4F2UNOY.js.map} +1 -1
  156. package/dist/{paths-2HMHL25W.js → paths-KBACHM5B.js} +10 -10
  157. package/dist/{paths-2HMHL25W.js.map → paths-KBACHM5B.js.map} +1 -1
  158. package/dist/{plugin-store-TLBQ5XRS.js → plugin-store-CYSNVZIX.js} +7 -7
  159. package/dist/{plugin-store-TLBQ5XRS.js.map → plugin-store-CYSNVZIX.js.map} +1 -1
  160. package/dist/{project-M2COJFPZ.js → project-SIHZBTGB.js} +13 -13
  161. package/dist/{project-M2COJFPZ.js.map → project-SIHZBTGB.js.map} +1 -1
  162. package/dist/resolver/index.js +5 -5
  163. package/dist/runner/index.js +17 -14
  164. package/dist/runner/src/serve.d.ts.map +1 -1
  165. package/dist/sdk/asset-manager.js +9 -9
  166. package/dist/sdk/bridge.js +2 -2
  167. package/dist/sdk/core.js +5 -5
  168. package/dist/sdk/flow.js +8 -6
  169. package/dist/sdk/index.js +17 -14
  170. package/dist/sdk/index.js.map +1 -1
  171. package/dist/sdk/resolver.js +5 -5
  172. package/dist/sdk/runner.js +17 -14
  173. package/dist/sdk/transport/ws.js +1 -1
  174. package/dist/sdk/transport.js +1 -1
  175. package/dist/{setup-GWXEG3G2.js → setup-KMBXMV25.js} +9 -9
  176. package/dist/{setup-GWXEG3G2.js.map → setup-KMBXMV25.js.map} +1 -1
  177. package/dist/{skills-YTMGG23D.js → skills-LHS4TOKK.js} +7 -7
  178. package/dist/{skills-YTMGG23D.js.map → skills-LHS4TOKK.js.map} +1 -1
  179. package/dist/{source-WMXH2OBW.js → source-X226ZJPR.js} +17 -15
  180. package/dist/{source-WMXH2OBW.js.map → source-X226ZJPR.js.map} +1 -1
  181. package/dist/{source-manifest-publish-MTHUGBAY.js → source-manifest-publish-N2QVUR5U.js} +19 -17
  182. package/dist/source-manifest-publish-N2QVUR5U.js.map +1 -0
  183. package/dist/transport/index.js +1 -1
  184. package/dist/transport/ws.js +1 -1
  185. package/dist/tui/index.js +17 -14
  186. package/dist/tui/index.js.map +1 -1
  187. package/dist/workspace-plugin/adapters/mcp.js +6 -6
  188. package/dist/workspace-plugin/adapters/omp.js +7 -7
  189. package/dist/workspace-plugin/index.js +1 -1
  190. package/package.json +18 -1
  191. package/dist/chunk-2BSXXTUP.js.map +0 -1
  192. package/dist/chunk-HOL5KD7U.js.map +0 -1
  193. package/dist/chunk-HPGV54O4.js.map +0 -1
  194. package/dist/chunk-MAN7AGQJ.js.map +0 -1
  195. package/dist/chunk-RBOPTTTK.js.map +0 -1
  196. package/dist/chunk-Y662DNQQ.js.map +0 -1
  197. package/dist/library-publish-HVIIQMI6.js.map +0 -1
  198. package/dist/source-manifest-publish-MTHUGBAY.js.map +0 -1
@@ -0,0 +1,1002 @@
1
+ import * as z from 'zod';
2
+
3
+ // factory-assets/connectors/flow/contract/expression.ts
4
+ var FLOW_EXPRESSION_LIMITS = Object.freeze({
5
+ maxLength: 4096,
6
+ maxTokens: 256,
7
+ maxNesting: 32,
8
+ maxPathSegments: 32,
9
+ maxCollectionItems: 1024
10
+ });
11
+ var FlowExpressionError = class extends Error {
12
+ /** Stable error name for callers that classify evaluator failures. */
13
+ name = "FlowExpressionError";
14
+ };
15
+ function expressionError(message, position) {
16
+ return new FlowExpressionError(
17
+ position === void 0 ? `Flow expression ${message}` : `Flow expression ${message} at ${position}`
18
+ );
19
+ }
20
+ function parseString(source, start) {
21
+ const quote = source[start];
22
+ let value = "";
23
+ let index = start + 1;
24
+ while (index < source.length) {
25
+ const character = source[index];
26
+ if (character === quote) return { value, end: index + 1 };
27
+ if (character !== "\\") {
28
+ value += character;
29
+ index++;
30
+ continue;
31
+ }
32
+ const escaped = source[index + 1];
33
+ if (escaped === void 0) throw expressionError("has an unterminated string", start);
34
+ const replacements = {
35
+ "\\": "\\",
36
+ "'": "'",
37
+ '"': '"',
38
+ n: "\n",
39
+ r: "\r",
40
+ t: " ",
41
+ b: "\b",
42
+ f: "\f"
43
+ };
44
+ if (escaped === "u") {
45
+ const hex = source.slice(index + 2, index + 6);
46
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
47
+ throw expressionError("has an invalid unicode escape", index);
48
+ }
49
+ value += String.fromCharCode(Number.parseInt(hex, 16));
50
+ index += 6;
51
+ continue;
52
+ }
53
+ if (!(escaped in replacements)) throw expressionError("has an invalid escape", index);
54
+ value += replacements[escaped];
55
+ index += 2;
56
+ }
57
+ throw expressionError("has an unterminated string", start);
58
+ }
59
+ function tokenize(source) {
60
+ if (source.length > FLOW_EXPRESSION_LIMITS.maxLength) {
61
+ throw expressionError(`exceeds the length limit of ${FLOW_EXPRESSION_LIMITS.maxLength}`);
62
+ }
63
+ const tokens = [];
64
+ const add = (token) => {
65
+ tokens.push(token);
66
+ if (tokens.length > FLOW_EXPRESSION_LIMITS.maxTokens) {
67
+ throw expressionError(`exceeds the token limit of ${FLOW_EXPRESSION_LIMITS.maxTokens}`);
68
+ }
69
+ };
70
+ let index = 0;
71
+ while (index < source.length) {
72
+ const character = source[index];
73
+ if (/\s/.test(character)) {
74
+ index++;
75
+ continue;
76
+ }
77
+ const pair = source.slice(index, index + 2);
78
+ if (["&&", "||", "==", "!=", "<=", ">="].includes(pair)) {
79
+ add({ kind: "operator", value: pair, position: index });
80
+ index += 2;
81
+ continue;
82
+ }
83
+ if (["!", "<", ">"].includes(character)) {
84
+ add({ kind: "operator", value: character, position: index });
85
+ index++;
86
+ continue;
87
+ }
88
+ if (["(", ")", "[", "]", ","].includes(character)) {
89
+ add({ kind: "punctuation", value: character, position: index });
90
+ index++;
91
+ continue;
92
+ }
93
+ if (character === "'" || character === '"') {
94
+ const parsed = parseString(source, index);
95
+ add({ kind: "value", value: parsed.value, position: index });
96
+ index = parsed.end;
97
+ continue;
98
+ }
99
+ const number2 = source.slice(index).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/);
100
+ if (number2) {
101
+ add({ kind: "value", value: Number(number2[0]), position: index });
102
+ index += number2[0].length;
103
+ continue;
104
+ }
105
+ const word = source.slice(index).match(/^[A-Za-z_][A-Za-z0-9_.-]*/);
106
+ if (word) {
107
+ const raw = word[0];
108
+ if (raw === "true") add({ kind: "value", value: true, position: index });
109
+ else if (raw === "false") add({ kind: "value", value: false, position: index });
110
+ else if (raw === "null") add({ kind: "value", value: null, position: index });
111
+ else if (raw === "in") add({ kind: "operator", value: raw, position: index });
112
+ else add({ kind: "word", value: raw, position: index });
113
+ index += raw.length;
114
+ continue;
115
+ }
116
+ throw expressionError(`contains unsupported token ${JSON.stringify(character)}`, index);
117
+ }
118
+ tokens.push({ kind: "eof", value: "", position: source.length });
119
+ return tokens;
120
+ }
121
+ var FORBIDDEN_PATH_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
122
+ function ownValue(value, segment, position) {
123
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
124
+ throw expressionError("path does not exist", position);
125
+ }
126
+ if (!Object.hasOwn(value, segment)) throw expressionError("path does not exist", position);
127
+ return value[segment];
128
+ }
129
+ function resolvePath(raw, context, position, traverse) {
130
+ const segments = raw.split(".");
131
+ if (segments.length > FLOW_EXPRESSION_LIMITS.maxPathSegments) {
132
+ throw expressionError(
133
+ `exceeds the path traversal limit of ${FLOW_EXPRESSION_LIMITS.maxPathSegments}`,
134
+ position
135
+ );
136
+ }
137
+ if (segments.some((segment) => segment.length === 0)) {
138
+ throw expressionError("contains an empty path segment", position);
139
+ }
140
+ const forbidden = segments.find((segment) => FORBIDDEN_PATH_SEGMENTS.has(segment));
141
+ if (forbidden) throw expressionError(`contains forbidden path segment ${forbidden}`, position);
142
+ let value;
143
+ let remaining;
144
+ if (segments[0] === "flow" && segments[1] === "input") {
145
+ if (segments.length === 2) {
146
+ throw expressionError("path requires a JSON property suffix", position);
147
+ }
148
+ value = context.flow.input;
149
+ remaining = segments.slice(2);
150
+ } else if (segments[0] === "defaults" && segments.length >= 2) {
151
+ value = context.defaults ?? {};
152
+ remaining = segments.slice(1);
153
+ } else if (segments[0] === "nodes" && segments.length === 3 && segments[2] === "status") {
154
+ value = context.nodes;
155
+ remaining = segments.slice(1);
156
+ } else if (segments[0] === "nodes" && segments.length >= 4 && segments[2] === "output" && segments[3] === "fields") {
157
+ if (segments.length === 4) {
158
+ throw expressionError("path requires a JSON property suffix", position);
159
+ }
160
+ value = context.nodes;
161
+ remaining = segments.slice(1);
162
+ } else {
163
+ throw expressionError(`contains unsupported path ${raw}`, position);
164
+ }
165
+ if (!traverse) return void 0;
166
+ for (const segment of remaining) value = ownValue(value, segment, position);
167
+ return value;
168
+ }
169
+ function compare(operator, left, right, position) {
170
+ if (operator === "==") return Object.is(left, right);
171
+ if (operator === "!=") return !Object.is(left, right);
172
+ if (operator === "in") {
173
+ if (!Array.isArray(right))
174
+ throw expressionError("requires an array on the right of in", position);
175
+ if (right.length > FLOW_EXPRESSION_LIMITS.maxCollectionItems) {
176
+ throw expressionError(
177
+ `exceeds the collection item limit of ${FLOW_EXPRESSION_LIMITS.maxCollectionItems}`,
178
+ position
179
+ );
180
+ }
181
+ return right.some((candidate) => Object.is(candidate, left));
182
+ }
183
+ if (!(typeof left === "number" && typeof right === "number" || typeof left === "string" && typeof right === "string")) {
184
+ throw expressionError(`requires comparable operands for ${operator}`, position);
185
+ }
186
+ if (operator === "<") return left < right;
187
+ if (operator === "<=") return left <= right;
188
+ if (operator === ">") return left > right;
189
+ if (operator === ">=") return left >= right;
190
+ throw expressionError(`contains unsupported operator ${operator}`, position);
191
+ }
192
+ var STATIC_BOOLEAN = /* @__PURE__ */ Symbol("static-boolean");
193
+ var STATIC_PATH = /* @__PURE__ */ Symbol("static-path");
194
+ function isStaticPath(value) {
195
+ return typeof value === "object" && value !== null && value.marker === STATIC_PATH;
196
+ }
197
+ function isBooleanOperand(value) {
198
+ return typeof value === "boolean" || value === STATIC_BOOLEAN || isStaticPath(value);
199
+ }
200
+ function assertBooleanOperand(value, position) {
201
+ if (!isBooleanOperand(value)) throw expressionError("requires boolean operands", position);
202
+ }
203
+ var Parser = class {
204
+ constructor(tokens, context, onPath, onBooleanPath) {
205
+ this.tokens = tokens;
206
+ this.context = context;
207
+ this.onPath = onPath;
208
+ this.onBooleanPath = onBooleanPath;
209
+ }
210
+ tokens;
211
+ context;
212
+ onPath;
213
+ onBooleanPath;
214
+ index = 0;
215
+ nesting = 0;
216
+ parse(evaluate2 = true) {
217
+ const value = this.parseOr(evaluate2);
218
+ const trailing = this.peek();
219
+ if (trailing.kind !== "eof") {
220
+ throw expressionError(
221
+ `contains unexpected token ${String(trailing.value)}`,
222
+ trailing.position
223
+ );
224
+ }
225
+ return value;
226
+ }
227
+ peek() {
228
+ return this.tokens[this.index];
229
+ }
230
+ take() {
231
+ return this.tokens[this.index++];
232
+ }
233
+ accept(value) {
234
+ if (this.peek().value !== value) return void 0;
235
+ return this.take();
236
+ }
237
+ parseOr(evaluate2) {
238
+ let value = this.parseAnd(evaluate2);
239
+ while (this.peek().value === "||") {
240
+ const operator = this.take();
241
+ assertBooleanOperand(value, operator.position);
242
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
243
+ const evaluateRight = evaluate2 && value === false;
244
+ const right = this.parseAnd(evaluateRight);
245
+ assertBooleanOperand(right, operator.position);
246
+ if (isStaticPath(right)) this.onBooleanPath?.(right.path);
247
+ value = evaluate2 ? value === true || right === true : STATIC_BOOLEAN;
248
+ }
249
+ return value;
250
+ }
251
+ parseAnd(evaluate2) {
252
+ let value = this.parseComparison(evaluate2);
253
+ while (this.peek().value === "&&") {
254
+ const operator = this.take();
255
+ assertBooleanOperand(value, operator.position);
256
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
257
+ const evaluateRight = evaluate2 && value === true;
258
+ const right = this.parseComparison(evaluateRight);
259
+ assertBooleanOperand(right, operator.position);
260
+ if (isStaticPath(right)) this.onBooleanPath?.(right.path);
261
+ value = evaluate2 ? value === true && right === true : STATIC_BOOLEAN;
262
+ }
263
+ return value;
264
+ }
265
+ parseComparison(evaluate2) {
266
+ const left = this.parseUnary(evaluate2);
267
+ const token = this.peek();
268
+ if (token.kind !== "operator" || !["==", "!=", "<", "<=", ">", ">=", "in"].includes(String(token.value))) {
269
+ return left;
270
+ }
271
+ this.take();
272
+ const right = this.parseUnary(evaluate2);
273
+ return evaluate2 ? compare(String(token.value), left, right, token.position) : STATIC_BOOLEAN;
274
+ }
275
+ parseUnary(evaluate2) {
276
+ const operator = this.accept("!");
277
+ if (operator) {
278
+ const value = this.parseUnary(evaluate2);
279
+ assertBooleanOperand(value, operator.position);
280
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
281
+ return evaluate2 ? value === false : STATIC_BOOLEAN;
282
+ }
283
+ return this.parsePrimary(evaluate2);
284
+ }
285
+ parsePrimary(evaluate2) {
286
+ const token = this.take();
287
+ if (token.kind === "value") return token.value;
288
+ if (token.kind === "word") {
289
+ this.onPath?.(String(token.value));
290
+ resolvePath(String(token.value), this.context, token.position, false);
291
+ return evaluate2 ? resolvePath(String(token.value), this.context, token.position, true) : { marker: STATIC_PATH, path: String(token.value) };
292
+ }
293
+ if (token.value === "(") {
294
+ this.enterNesting(token.position);
295
+ const value = this.parseOr(evaluate2);
296
+ if (!this.accept(")"))
297
+ throw expressionError("is missing a closing parenthesis", token.position);
298
+ this.nesting--;
299
+ return value;
300
+ }
301
+ if (token.value === "[") {
302
+ this.enterNesting(token.position);
303
+ const values = [];
304
+ if (!this.accept("]")) {
305
+ do
306
+ values.push(this.parsePrimary(evaluate2));
307
+ while (this.accept(","));
308
+ if (!this.accept("]"))
309
+ throw expressionError("is missing a closing bracket", token.position);
310
+ }
311
+ this.nesting--;
312
+ return values;
313
+ }
314
+ throw expressionError(`contains unexpected token ${String(token.value)}`, token.position);
315
+ }
316
+ enterNesting(position) {
317
+ this.nesting++;
318
+ if (this.nesting > FLOW_EXPRESSION_LIMITS.maxNesting) {
319
+ throw expressionError(
320
+ `exceeds the nesting limit of ${FLOW_EXPRESSION_LIMITS.maxNesting}`,
321
+ position
322
+ );
323
+ }
324
+ }
325
+ };
326
+ function inspectFlowExpression(expression, requireBoolean = true) {
327
+ const tokens = tokenize(expression);
328
+ if (expression.trim() === "default") return [];
329
+ const references = /* @__PURE__ */ new Map();
330
+ const record3 = (path, booleanOperand) => {
331
+ references.set(path, (references.get(path) ?? false) || booleanOperand);
332
+ };
333
+ const context = { flow: { input: {} }, nodes: {} };
334
+ const result = new Parser(
335
+ tokens,
336
+ context,
337
+ (path) => record3(path, false),
338
+ (path) => record3(path, true)
339
+ ).parse(false);
340
+ if (requireBoolean && typeof result !== "boolean" && result !== STATIC_BOOLEAN) {
341
+ throw expressionError("must evaluate to a boolean");
342
+ }
343
+ return Array.from(references, ([path, booleanOperand]) => ({ path, booleanOperand }));
344
+ }
345
+ function evaluateFlowExpression(expression, context) {
346
+ const tokens = tokenize(expression);
347
+ if (expression.trim() === "default") return true;
348
+ const result = new Parser(tokens, context).parse();
349
+ if (typeof result !== "boolean") {
350
+ throw expressionError("must evaluate to a boolean");
351
+ }
352
+ return result;
353
+ }
354
+ function evaluate(expression, context) {
355
+ return evaluateFlowExpression(expression, context);
356
+ }
357
+ var nonEmptyString = z.string().min(1);
358
+ var jsonSchema = z.record(z.string(), z.json());
359
+ var FlowInputContractSchema = z.strictObject({
360
+ schema: jsonSchema,
361
+ example: z.json().optional()
362
+ });
363
+ var FlowOutputContractSchema = z.strictObject({
364
+ schema: jsonSchema
365
+ });
366
+ var PreconditionSchema = z.strictObject({
367
+ expr: nonEmptyString,
368
+ message: nonEmptyString.optional()
369
+ });
370
+ var ArtifactContractSchema = z.strictObject({
371
+ kind: nonEmptyString,
372
+ lifetime: z.enum(["session", "persistent"])
373
+ });
374
+ var NodeOutputContractSchema = z.strictObject({
375
+ fields: jsonSchema.optional(),
376
+ artifacts: z.array(ArtifactContractSchema).optional()
377
+ });
378
+ var NodeContractSchema = z.strictObject({
379
+ requires: z.array(PreconditionSchema).optional(),
380
+ input: z.record(z.string(), z.json()).optional(),
381
+ output: NodeOutputContractSchema.optional()
382
+ });
383
+ var NodeGateSchema = z.strictObject({
384
+ approval: z.enum(["none", "optional", "mandatory"])
385
+ });
386
+ var NodeControlSchema = z.strictObject({
387
+ optional: z.boolean().optional(),
388
+ retries: z.number().int().min(0).optional(),
389
+ timeoutSec: z.number().positive().optional(),
390
+ parallelGroup: nonEmptyString.optional()
391
+ });
392
+ var runAssets = { assets: z.array(nonEmptyString).optional() };
393
+ var AgentRunSchema = z.strictObject({
394
+ kind: z.literal("agent"),
395
+ instruction: nonEmptyString,
396
+ ...runAssets
397
+ });
398
+ var SubpromptRunSchema = z.strictObject({
399
+ kind: z.literal("subprompt"),
400
+ instruction: nonEmptyString,
401
+ model: nonEmptyString.optional(),
402
+ ...runAssets
403
+ });
404
+ var deterministicRun = {
405
+ runtime: z.enum(["shell", "node", "python"]).optional(),
406
+ command: nonEmptyString,
407
+ cwd: nonEmptyString.optional(),
408
+ successExit: z.array(z.number().int()).optional(),
409
+ capture: z.strictObject({ stdout: nonEmptyString.optional(), stderr: nonEmptyString.optional() }).optional(),
410
+ ...runAssets
411
+ };
412
+ var FunctionRunSchema = z.strictObject({
413
+ kind: z.literal("function"),
414
+ ...deterministicRun
415
+ });
416
+ var CheckRunSchema = z.strictObject({
417
+ kind: z.literal("check"),
418
+ onFail: z.enum(["escalate", "fail"]).default("escalate"),
419
+ ...deterministicRun
420
+ });
421
+ var InputChoiceSchema = z.strictObject({
422
+ id: nonEmptyString,
423
+ label: nonEmptyString,
424
+ description: nonEmptyString.optional()
425
+ });
426
+ var FormFieldSchema = z.strictObject({
427
+ id: nonEmptyString,
428
+ label: nonEmptyString,
429
+ type: z.enum(["text", "textarea", "number", "choice", "file", "date", "boolean"]),
430
+ required: z.boolean().optional(),
431
+ options: z.array(InputChoiceSchema).optional(),
432
+ accept: z.array(nonEmptyString).optional()
433
+ });
434
+ var InputSchema = z.discriminatedUnion("kind", [
435
+ z.strictObject({ kind: z.literal("text"), multiline: z.boolean().optional() }),
436
+ z.strictObject({
437
+ kind: z.literal("choice"),
438
+ options: z.array(InputChoiceSchema).min(1),
439
+ multiple: z.boolean().optional()
440
+ }),
441
+ z.strictObject({ kind: z.literal("form"), fields: z.array(FormFieldSchema) }),
442
+ z.strictObject({
443
+ kind: z.literal("file"),
444
+ accept: z.array(nonEmptyString).optional(),
445
+ maxSize: z.number().positive().optional(),
446
+ multiple: z.boolean().optional()
447
+ })
448
+ ]);
449
+ var GateRunSchema = z.strictObject({
450
+ kind: z.literal("gate"),
451
+ prompt: nonEmptyString,
452
+ schema: InputSchema,
453
+ ...runAssets
454
+ });
455
+ var RouteSchema = z.strictObject({
456
+ when: nonEmptyString,
457
+ target: nonEmptyString.nullable()
458
+ });
459
+ var RouterRunSchema = z.strictObject({
460
+ kind: z.literal("router"),
461
+ routes: z.array(RouteSchema).min(1),
462
+ ...runAssets
463
+ });
464
+ var RunSchema = z.discriminatedUnion("kind", [
465
+ AgentRunSchema,
466
+ SubpromptRunSchema,
467
+ FunctionRunSchema,
468
+ CheckRunSchema,
469
+ GateRunSchema,
470
+ RouterRunSchema
471
+ ]);
472
+ var NodeSchema = z.strictObject({
473
+ id: nonEmptyString,
474
+ label: nonEmptyString,
475
+ description: nonEmptyString,
476
+ phase: nonEmptyString.optional(),
477
+ run: RunSchema,
478
+ contract: NodeContractSchema.optional(),
479
+ gate: NodeGateSchema.optional(),
480
+ control: NodeControlSchema.optional()
481
+ });
482
+ var EdgeSchema = z.strictObject({
483
+ id: nonEmptyString,
484
+ source: nonEmptyString,
485
+ target: nonEmptyString,
486
+ type: z.enum(["flow", "parallel", "optional"])
487
+ });
488
+ var FlowDefaultsSchema = z.strictObject({
489
+ approval: z.enum(["checkpoint", "auto", "manual"]).optional(),
490
+ researchDepth: nonEmptyString.optional(),
491
+ autoReview: z.boolean().optional(),
492
+ subagentMode: z.boolean().optional(),
493
+ verbosity: nonEmptyString.optional(),
494
+ cliMode: z.boolean().optional(),
495
+ run_input: z.json().optional(),
496
+ parameters: z.record(z.string(), z.json()).optional()
497
+ });
498
+ var FlowMetaSchema = z.strictObject({
499
+ icon: nonEmptyString.optional(),
500
+ category: nonEmptyString.optional(),
501
+ tags: z.array(nonEmptyString).optional(),
502
+ stage: nonEmptyString.optional(),
503
+ onboarding: z.strictObject({
504
+ input_style: z.enum(["freeform", "structured", "repo"]),
505
+ placeholder: nonEmptyString.optional(),
506
+ fields: z.array(nonEmptyString).optional()
507
+ }).optional()
508
+ });
509
+ var FlowDefinitionObjectSchema = z.strictObject({
510
+ $schema: nonEmptyString.optional(),
511
+ schemaVersion: z.literal(2),
512
+ id: nonEmptyString,
513
+ version: nonEmptyString,
514
+ name: nonEmptyString,
515
+ description: nonEmptyString.optional(),
516
+ input: FlowInputContractSchema.optional(),
517
+ output: FlowOutputContractSchema.optional(),
518
+ defaults: FlowDefaultsSchema.optional(),
519
+ entry: nonEmptyString.optional(),
520
+ nodes: z.array(NodeSchema),
521
+ edges: z.array(EdgeSchema),
522
+ meta: FlowMetaSchema.optional()
523
+ });
524
+ function parseFlowDefinitionStructure(data) {
525
+ return FlowDefinitionObjectSchema.safeParse(data);
526
+ }
527
+ function bindingExpressions(value) {
528
+ if (typeof value === "string") {
529
+ return Array.from(value.matchAll(/\$\{([^{}]+)\}/g), (match) => match[1]);
530
+ }
531
+ if (Array.isArray(value)) return value.flatMap(bindingExpressions);
532
+ if (typeof value !== "object" || value === null) return [];
533
+ return Object.values(value).flatMap(bindingExpressions);
534
+ }
535
+ var MISSING_FIELD = /* @__PURE__ */ Symbol("missing-field");
536
+ function declaredFieldSchema(schema, path) {
537
+ let current = schema;
538
+ for (const segment of path) {
539
+ if (typeof current !== "object" || current === null) return MISSING_FIELD;
540
+ const properties = current.properties;
541
+ if (typeof properties !== "object" || properties === null || !Object.hasOwn(properties, segment)) {
542
+ return MISSING_FIELD;
543
+ }
544
+ current = properties[segment];
545
+ }
546
+ return current;
547
+ }
548
+ function knownNonBooleanType(schema) {
549
+ if (typeof schema !== "object" || schema === null) return void 0;
550
+ const type = schema.type;
551
+ if (typeof type === "string") return type === "boolean" ? void 0 : type;
552
+ if (Array.isArray(type) && type.length > 0 && type.every((candidate) => typeof candidate === "string") && type.some((candidate) => candidate !== "boolean")) {
553
+ return type.join(" | ");
554
+ }
555
+ return void 0;
556
+ }
557
+ var FlowDefinitionSchema = FlowDefinitionObjectSchema.superRefine((flow, context) => {
558
+ const nodeIds = /* @__PURE__ */ new Set();
559
+ for (const [index, node] of flow.nodes.entries()) {
560
+ if (nodeIds.has(node.id)) {
561
+ context.addIssue({
562
+ code: "custom",
563
+ path: ["nodes", index, "id"],
564
+ message: `duplicate node id: ${node.id}`
565
+ });
566
+ }
567
+ nodeIds.add(node.id);
568
+ if (node.control?.optional === true && node.gate?.approval === "mandatory") {
569
+ context.addIssue({
570
+ code: "custom",
571
+ path: ["nodes", index, "control", "optional"],
572
+ message: "a node cannot be both optional and a mandatory approval gate"
573
+ });
574
+ }
575
+ }
576
+ if (flow.entry !== void 0 && !nodeIds.has(flow.entry)) {
577
+ context.addIssue({ code: "custom", path: ["entry"], message: `unknown node: ${flow.entry}` });
578
+ }
579
+ const outgoing = /* @__PURE__ */ new Map();
580
+ for (const [edgeIndex, edge] of flow.edges.entries()) {
581
+ if (!nodeIds.has(edge.source)) {
582
+ context.addIssue({
583
+ code: "custom",
584
+ path: ["edges", edgeIndex, "source"],
585
+ message: `unknown node: ${edge.source}`
586
+ });
587
+ }
588
+ if (!nodeIds.has(edge.target)) {
589
+ context.addIssue({
590
+ code: "custom",
591
+ path: ["edges", edgeIndex, "target"],
592
+ message: `unknown node: ${edge.target}`
593
+ });
594
+ }
595
+ if (edge.type === "flow" && nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
596
+ const edges = outgoing.get(edge.source) ?? [];
597
+ edges.push({ target: edge.target, path: ["edges", edgeIndex] });
598
+ outgoing.set(edge.source, edges);
599
+ }
600
+ }
601
+ for (const [nodeIndex, node] of flow.nodes.entries()) {
602
+ if (node.run.kind !== "router") continue;
603
+ for (const [routeIndex, route] of node.run.routes.entries()) {
604
+ if (route.target !== null && !nodeIds.has(route.target)) {
605
+ context.addIssue({
606
+ code: "custom",
607
+ path: ["nodes", nodeIndex, "run", "routes", routeIndex, "target"],
608
+ message: `unknown node: ${route.target}`
609
+ });
610
+ }
611
+ }
612
+ }
613
+ const validateExpression = (expression, path, requireBoolean = true) => {
614
+ let references;
615
+ try {
616
+ references = inspectFlowExpression(expression, requireBoolean);
617
+ } catch (error) {
618
+ context.addIssue({
619
+ code: "custom",
620
+ path,
621
+ message: error instanceof Error ? error.message : "invalid Flow expression"
622
+ });
623
+ return;
624
+ }
625
+ for (const reference of references) {
626
+ const segments = reference.path.split(".");
627
+ if (segments[0] !== "nodes") continue;
628
+ const producer = flow.nodes.find((node) => node.id === segments[1]);
629
+ if (!producer) {
630
+ context.addIssue({
631
+ code: "custom",
632
+ path,
633
+ message: `unknown producer node: ${segments[1]}`
634
+ });
635
+ continue;
636
+ }
637
+ if (segments[2] === "status") {
638
+ if (reference.booleanOperand) {
639
+ context.addIssue({ code: "custom", path, message: "node status is not boolean" });
640
+ }
641
+ continue;
642
+ }
643
+ const outputSchema = producer.contract?.output?.fields;
644
+ if (!outputSchema) {
645
+ context.addIssue({
646
+ code: "custom",
647
+ path,
648
+ message: `node ${producer.id} has no declared output fields`
649
+ });
650
+ continue;
651
+ }
652
+ const fieldPath = segments.slice(4);
653
+ const fieldSchema = declaredFieldSchema(outputSchema, fieldPath);
654
+ if (fieldSchema === MISSING_FIELD) {
655
+ context.addIssue({
656
+ code: "custom",
657
+ path,
658
+ message: `node ${producer.id} does not declare output field ${fieldPath.join(".")}`
659
+ });
660
+ continue;
661
+ }
662
+ const nonBooleanType = reference.booleanOperand ? knownNonBooleanType(fieldSchema) : void 0;
663
+ if (nonBooleanType) {
664
+ context.addIssue({
665
+ code: "custom",
666
+ path,
667
+ message: `node ${producer.id} output field ${fieldPath.join(".")} is ${nonBooleanType}, not boolean`
668
+ });
669
+ }
670
+ }
671
+ };
672
+ for (const [nodeIndex, node] of flow.nodes.entries()) {
673
+ for (const [requireIndex, requirement] of node.contract?.requires?.entries() ?? []) {
674
+ validateExpression(requirement.expr, [
675
+ "nodes",
676
+ nodeIndex,
677
+ "contract",
678
+ "requires",
679
+ requireIndex,
680
+ "expr"
681
+ ]);
682
+ }
683
+ for (const [bindingName, binding] of Object.entries(node.contract?.input ?? {})) {
684
+ for (const expression of bindingExpressions(binding)) {
685
+ validateExpression(
686
+ expression,
687
+ ["nodes", nodeIndex, "contract", "input", bindingName],
688
+ false
689
+ );
690
+ }
691
+ }
692
+ if (node.run.kind === "router") {
693
+ for (const [routeIndex, route] of node.run.routes.entries()) {
694
+ validateExpression(route.when, ["nodes", nodeIndex, "run", "routes", routeIndex, "when"]);
695
+ }
696
+ }
697
+ }
698
+ const state = /* @__PURE__ */ new Map();
699
+ for (const nodeId of nodeIds) {
700
+ if (state.has(nodeId)) continue;
701
+ const stack = [{ nodeId, next: 0 }];
702
+ state.set(nodeId, "active");
703
+ while (stack.length > 0) {
704
+ const frame = stack.at(-1);
705
+ if (!frame) break;
706
+ const arcs = outgoing.get(frame.nodeId) ?? [];
707
+ if (frame.next >= arcs.length) {
708
+ state.set(frame.nodeId, "done");
709
+ stack.pop();
710
+ continue;
711
+ }
712
+ const arc = arcs[frame.next++];
713
+ if (state.get(arc.target) === "active") {
714
+ context.addIssue({ code: "custom", path: arc.path, message: "flow graph must be acyclic" });
715
+ } else if (!state.has(arc.target)) {
716
+ state.set(arc.target, "active");
717
+ stack.push({ nodeId: arc.target, next: 0 });
718
+ }
719
+ }
720
+ }
721
+ });
722
+ var successfullyParsedDefinitions = /* @__PURE__ */ new WeakMap();
723
+ function valueFingerprint(value, ancestors) {
724
+ if (value === null) return "null";
725
+ if (value === void 0) return "undefined";
726
+ if (typeof value === "string") return `string:${JSON.stringify(value)}`;
727
+ if (typeof value === "boolean") return `boolean:${value}`;
728
+ if (typeof value === "number") {
729
+ if (!Number.isFinite(value)) return null;
730
+ return `number:${Object.is(value, -0) ? "-0" : value}`;
731
+ }
732
+ if (typeof value !== "object" || ancestors.has(value)) return null;
733
+ ancestors.add(value);
734
+ try {
735
+ if (Array.isArray(value)) {
736
+ if (Object.getPrototypeOf(value) !== Array.prototype) return null;
737
+ if (Object.getOwnPropertySymbols(value).length > 0) return null;
738
+ const names = Object.getOwnPropertyNames(value);
739
+ if (names.length !== value.length + 1 || !names.includes("length")) return null;
740
+ const items = [];
741
+ for (let index = 0; index < value.length; index += 1) {
742
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
743
+ if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) return null;
744
+ const item = valueFingerprint(descriptor.value, ancestors);
745
+ if (item === null) return null;
746
+ items.push(item);
747
+ }
748
+ return `array:[${items.join(",")}]`;
749
+ }
750
+ const prototype = Object.getPrototypeOf(value);
751
+ if (prototype !== Object.prototype && prototype !== null) return null;
752
+ if (Object.getOwnPropertySymbols(value).length > 0) return null;
753
+ const entries = [];
754
+ for (const key of Object.getOwnPropertyNames(value).sort()) {
755
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
756
+ if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) return null;
757
+ const nested = valueFingerprint(descriptor.value, ancestors);
758
+ if (nested === null) return null;
759
+ entries.push(`${JSON.stringify(key)}:${nested}`);
760
+ }
761
+ return `object:{${entries.join(",")}}`;
762
+ } finally {
763
+ ancestors.delete(value);
764
+ }
765
+ }
766
+ function definitionFingerprint(data) {
767
+ return valueFingerprint(data, /* @__PURE__ */ new Set());
768
+ }
769
+ var LegacyRouteSchema = z.looseObject({
770
+ condition: z.string().min(1),
771
+ target: z.string().min(1).nullable()
772
+ });
773
+ var LegacyNodeDataSchema = z.looseObject({
774
+ skill: z.string().min(1).optional(),
775
+ version: z.string().min(1).optional(),
776
+ label: z.string().min(1).optional(),
777
+ description: z.string().min(1).optional(),
778
+ optional: z.boolean().optional(),
779
+ approval: z.looseObject({ mandatory: z.boolean().optional() }).optional(),
780
+ parameters: z.record(z.string(), z.unknown()).optional(),
781
+ phase: z.string().min(1).optional(),
782
+ parallel_group: z.string().min(1).optional(),
783
+ flow: z.string().min(1).optional(),
784
+ message: z.string().min(1).optional(),
785
+ routes: z.array(LegacyRouteSchema).optional(),
786
+ assets: z.array(z.string().min(1)).optional()
787
+ });
788
+ var LegacyNodeSchema = z.looseObject({
789
+ id: z.string().min(1),
790
+ type: z.string().min(1).optional(),
791
+ skill: z.string().min(1).optional(),
792
+ label: z.string().min(1).optional(),
793
+ description: z.string().min(1).optional(),
794
+ data: LegacyNodeDataSchema.optional()
795
+ });
796
+ var LegacyEdgeSchema = z.looseObject({
797
+ id: z.string().min(1).optional(),
798
+ source: z.string().min(1),
799
+ target: z.string().min(1),
800
+ type: z.string().min(1).optional()
801
+ });
802
+ var LegacyFlowSchema = z.looseObject({
803
+ id: z.string().min(1),
804
+ version: z.string().min(1).optional(),
805
+ name: z.string().min(1),
806
+ description: z.string().min(1).optional(),
807
+ requires: z.array(z.string().min(1)).optional(),
808
+ globals: z.record(z.string(), z.unknown()).optional(),
809
+ entry: z.string().min(1).optional(),
810
+ nodes: z.array(LegacyNodeSchema).optional(),
811
+ edges: z.array(LegacyEdgeSchema).optional(),
812
+ meta: z.record(z.string(), z.unknown()).optional(),
813
+ metadata: z.record(z.string(), z.unknown()).optional()
814
+ });
815
+ function success(data) {
816
+ const fingerprint = definitionFingerprint(data);
817
+ if (fingerprint !== null) successfullyParsedDefinitions.set(data, fingerprint);
818
+ return { ok: true, data };
819
+ }
820
+ function failure(error) {
821
+ return {
822
+ ok: false,
823
+ errors: error.issues.map((issue) => ({
824
+ path: issue.path.map(String).join("."),
825
+ message: issue.message
826
+ }))
827
+ };
828
+ }
829
+ var LEGACY_DEFAULT_KEYS = {
830
+ approval_mode: "approval",
831
+ research_depth: "researchDepth",
832
+ auto_review: "autoReview",
833
+ subagent_mode: "subagentMode",
834
+ verbosity: "verbosity",
835
+ cli_mode: "cliMode",
836
+ run_input: "run_input"
837
+ };
838
+ function normalizeDefaults(globals) {
839
+ if (!globals) return void 0;
840
+ const known = {};
841
+ const parameters = {};
842
+ for (const [key, value] of Object.entries(globals)) {
843
+ const normalizedKey = LEGACY_DEFAULT_KEYS[key];
844
+ if (normalizedKey) {
845
+ known[normalizedKey] = key === "approval_mode" && value === "auto_approve" ? "auto" : value;
846
+ } else {
847
+ parameters[key] = value;
848
+ }
849
+ }
850
+ if (Object.keys(parameters).length > 0) known.parameters = parameters;
851
+ return Object.keys(known).length > 0 ? known : void 0;
852
+ }
853
+ function normalizeMeta(value) {
854
+ if (!value) return void 0;
855
+ const meta = {};
856
+ if (typeof value.icon === "string") meta.icon = value.icon;
857
+ if (typeof value.category === "string") meta.category = value.category;
858
+ if (Array.isArray(value.tags)) meta.tags = value.tags;
859
+ if (typeof value.stage === "string") meta.stage = value.stage;
860
+ if (typeof value.onboarding === "object" && value.onboarding !== null) {
861
+ const onboarding = value.onboarding;
862
+ if (onboarding.input_style === "freeform" || onboarding.input_style === "structured" || onboarding.input_style === "repo") {
863
+ meta.onboarding = {
864
+ input_style: onboarding.input_style,
865
+ ...typeof onboarding.placeholder === "string" ? { placeholder: onboarding.placeholder } : {},
866
+ ...Array.isArray(onboarding.fields) ? { fields: onboarding.fields } : {}
867
+ };
868
+ }
869
+ }
870
+ return Object.keys(meta).length > 0 ? meta : void 0;
871
+ }
872
+ function normalizeLegacyBinding(value) {
873
+ if (typeof value === "string") {
874
+ return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, key) => {
875
+ const normalized = LEGACY_DEFAULT_KEYS[key];
876
+ return `\${defaults.${normalized ?? `parameters.${key}`}}`;
877
+ });
878
+ }
879
+ if (Array.isArray(value)) return value.map(normalizeLegacyBinding);
880
+ if (typeof value !== "object" || value === null) return value;
881
+ return Object.fromEntries(
882
+ Object.entries(value).map(([key, nested]) => [key, normalizeLegacyBinding(nested)])
883
+ );
884
+ }
885
+ function normalizeV1(data) {
886
+ const legacyResult = LegacyFlowSchema.safeParse(data);
887
+ if (!legacyResult.success) return failure(legacyResult.error);
888
+ const legacy = legacyResult.data;
889
+ const contradiction = (legacy.nodes ?? []).findIndex(
890
+ (node) => node.data?.optional === true && node.data.approval?.mandatory === true
891
+ );
892
+ if (contradiction !== -1) {
893
+ return {
894
+ ok: false,
895
+ errors: [
896
+ {
897
+ path: `nodes.${contradiction}.data`,
898
+ message: "a node cannot be both optional and a mandatory approval gate"
899
+ }
900
+ ]
901
+ };
902
+ }
903
+ const nodes = [];
904
+ for (const node of legacy.nodes ?? []) {
905
+ const data2 = node.data ?? {};
906
+ const kind = node.type;
907
+ const label = data2.label ?? node.label ?? data2.skill ?? node.skill ?? node.id;
908
+ const description = node.description ?? data2.description ?? data2.message ?? label;
909
+ if (kind !== "skill") {
910
+ const delegatedAsset = kind === "sub-flow" && data2.flow ? `flow:${data2.flow}` : void 0;
911
+ const assets2 = [...delegatedAsset ? [delegatedAsset] : [], ...data2.assets ?? []];
912
+ const parameters2 = data2.parameters ?? {};
913
+ nodes.push({
914
+ id: node.id,
915
+ label,
916
+ description,
917
+ phase: data2.phase,
918
+ run: {
919
+ kind: "router",
920
+ routes: [{ when: "default", target: null }],
921
+ assets: assets2.length > 0 ? assets2 : void 0
922
+ },
923
+ contract: {
924
+ requires: [{ expr: "false" }],
925
+ input: Object.keys(parameters2).length > 0 ? normalizeLegacyBinding(parameters2) : void 0
926
+ },
927
+ control: { optional: true, parallelGroup: data2.parallel_group }
928
+ });
929
+ continue;
930
+ }
931
+ const parameters = { ...data2.parameters ?? {} };
932
+ const authoredInstruction = parameters.instructions;
933
+ delete parameters.instructions;
934
+ const instruction = typeof authoredInstruction === "string" && authoredInstruction.length > 0 ? authoredInstruction : description;
935
+ const skill = data2.skill ?? node.skill;
936
+ const skillAsset = skill ? `skill:${skill}${data2.version !== void 0 ? `#${data2.version}` : ""}` : void 0;
937
+ const assets = [...skillAsset ? [skillAsset] : [], ...data2.assets ?? []];
938
+ const control = {
939
+ optional: data2.optional,
940
+ parallelGroup: data2.parallel_group
941
+ };
942
+ nodes.push({
943
+ id: node.id,
944
+ label,
945
+ description,
946
+ phase: data2.phase,
947
+ run: {
948
+ kind: "agent",
949
+ instruction,
950
+ assets: assets.length > 0 ? assets : void 0
951
+ },
952
+ contract: Object.keys(parameters).length > 0 ? { input: normalizeLegacyBinding(parameters) } : void 0,
953
+ gate: data2.approval?.mandatory === true ? { approval: "mandatory" } : void 0,
954
+ control: control.optional !== void 0 || control.parallelGroup !== void 0 ? control : void 0
955
+ });
956
+ }
957
+ const nodeIds = new Set(nodes.map((node) => node.id));
958
+ const edges = (legacy.edges ?? []).map((edge, index) => ({
959
+ ...edge,
960
+ id: edge.id ?? `${edge.source}-${edge.target}-${index}`,
961
+ type: edge.type ?? "optional"
962
+ }));
963
+ const anchor = nodes.find((node) => node.id === legacy.entry) ?? (nodes.length > 0 ? nodes[0] : void 0);
964
+ if (anchor && legacy.requires && legacy.requires.length > 0) {
965
+ const run = anchor.run;
966
+ const existingAssets = Array.isArray(run.assets) ? run.assets : [];
967
+ run.assets = [.../* @__PURE__ */ new Set([...existingAssets, ...legacy.requires])];
968
+ }
969
+ const candidate = {
970
+ schemaVersion: 2,
971
+ id: legacy.id,
972
+ version: legacy.version ?? "1.0.0",
973
+ name: legacy.name,
974
+ description: legacy.description,
975
+ defaults: normalizeDefaults(legacy.globals),
976
+ entry: legacy.entry !== void 0 && nodeIds.has(legacy.entry) ? legacy.entry : void 0,
977
+ nodes,
978
+ edges,
979
+ meta: normalizeMeta({ ...legacy.metadata ?? {}, ...legacy.meta ?? {} })
980
+ };
981
+ const normalized = parseFlowDefinitionStructure({ ...candidate, edges: [] });
982
+ if (!normalized.success) return failure(normalized.error);
983
+ const parsed = { ...normalized.data, edges };
984
+ return success(parsed);
985
+ }
986
+ function parseFlowDefinition(data) {
987
+ if (typeof data === "object" && data !== null) {
988
+ const recorded = successfullyParsedDefinitions.get(data);
989
+ if (recorded !== void 0 && definitionFingerprint(data) === recorded) {
990
+ return { ok: true, data };
991
+ }
992
+ }
993
+ if (typeof data === "object" && data !== null && Object.hasOwn(data, "schemaVersion")) {
994
+ const result = FlowDefinitionSchema.safeParse(data);
995
+ return result.success ? success(result.data) : failure(result.error);
996
+ }
997
+ return normalizeV1(data);
998
+ }
999
+
1000
+ export { FLOW_EXPRESSION_LIMITS, FlowDefinitionSchema, FlowExpressionError, evaluate, evaluateFlowExpression, normalizeV1, parseFlowDefinition };
1001
+ //# sourceMappingURL=chunk-ZE2KEPE2.js.map
1002
+ //# sourceMappingURL=chunk-ZE2KEPE2.js.map