@skaile/workspaces 2.2.0 → 2.4.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 (207) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +35 -12
  3. package/dist/{asset-feeds-D2LOXTOS.js → asset-feeds-4AWAT5PW.js} +6 -6
  4. package/dist/{asset-feeds-D2LOXTOS.js.map → asset-feeds-4AWAT5PW.js.map} +1 -1
  5. package/dist/asset-manager/catalog-deployer.js +1 -1
  6. package/dist/asset-manager/index.js +5 -5
  7. package/dist/asset-manager/installer.js +2 -2
  8. package/dist/bridge/drivers/claude-sdk.js +5 -2
  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-CERGXDGG.js → chunk-2OCYS5EP.js} +3 -3
  21. package/dist/{chunk-CERGXDGG.js.map → chunk-2OCYS5EP.js.map} +1 -1
  22. package/dist/{chunk-TQIU4HQG.js → chunk-2QVPCZTL.js} +101 -40
  23. package/dist/chunk-2QVPCZTL.js.map +1 -0
  24. package/dist/{chunk-A67FJ4YT.js → chunk-3HVASHBF.js} +3 -3
  25. package/dist/{chunk-A67FJ4YT.js.map → chunk-3HVASHBF.js.map} +1 -1
  26. package/dist/chunk-4O2RAXKJ.js +446 -0
  27. package/dist/chunk-4O2RAXKJ.js.map +1 -0
  28. package/dist/chunk-4QROZZ5Z.js +50 -0
  29. package/dist/chunk-4QROZZ5Z.js.map +1 -0
  30. package/dist/{chunk-VSSAJYFK.js → chunk-57RFYEVM.js} +3 -3
  31. package/dist/{chunk-VSSAJYFK.js.map → chunk-57RFYEVM.js.map} +1 -1
  32. package/dist/{chunk-SZJCUC52.js → chunk-6BV5NAPD.js} +156 -28
  33. package/dist/chunk-6BV5NAPD.js.map +1 -0
  34. package/dist/{chunk-MAIKGYFR.js → chunk-AKVAZ5CB.js} +2 -2
  35. package/dist/{chunk-MAIKGYFR.js.map → chunk-AKVAZ5CB.js.map} +1 -1
  36. package/dist/{chunk-BFIK6NPZ.js → chunk-AM5LFRXJ.js} +3 -3
  37. package/dist/{chunk-BFIK6NPZ.js.map → chunk-AM5LFRXJ.js.map} +1 -1
  38. package/dist/{chunk-6QSGCHE5.js → chunk-EEHOMCRU.js} +1071 -123
  39. package/dist/chunk-EEHOMCRU.js.map +1 -0
  40. package/dist/{chunk-6I5VRIX3.js → chunk-ENBTXMPL.js} +7 -7
  41. package/dist/{chunk-6I5VRIX3.js.map → chunk-ENBTXMPL.js.map} +1 -1
  42. package/dist/{chunk-Y662DNQQ.js → chunk-FKBQRV4J.js} +68 -24
  43. package/dist/chunk-FKBQRV4J.js.map +1 -0
  44. package/dist/{chunk-BUPFJFGP.js → chunk-G5V6YCHF.js} +3 -3
  45. package/dist/{chunk-BUPFJFGP.js.map → chunk-G5V6YCHF.js.map} +1 -1
  46. package/dist/{chunk-KGIVZOLU.js → chunk-GM2X24Q6.js} +2 -2
  47. package/dist/{chunk-KGIVZOLU.js.map → chunk-GM2X24Q6.js.map} +1 -1
  48. package/dist/{chunk-5BH6ZEGC.js → chunk-IHX2SN35.js} +9 -9
  49. package/dist/{chunk-5BH6ZEGC.js.map → chunk-IHX2SN35.js.map} +1 -1
  50. package/dist/{chunk-6HPTB6KT.js → chunk-JAFEMG7W.js} +4 -4
  51. package/dist/{chunk-6HPTB6KT.js.map → chunk-JAFEMG7W.js.map} +1 -1
  52. package/dist/{chunk-I5ESMJMW.js → chunk-MADO7PH5.js} +2 -2
  53. package/dist/{chunk-I5ESMJMW.js.map → chunk-MADO7PH5.js.map} +1 -1
  54. package/dist/{chunk-BCTU4TN7.js → chunk-MWFYXUFK.js} +3 -3
  55. package/dist/{chunk-BCTU4TN7.js.map → chunk-MWFYXUFK.js.map} +1 -1
  56. package/dist/{chunk-MAN7AGQJ.js → chunk-NU4E7C5I.js} +25 -6
  57. package/dist/chunk-NU4E7C5I.js.map +1 -0
  58. package/dist/{chunk-RKMXBOIO.js → chunk-O7ROIKTF.js} +3 -3
  59. package/dist/{chunk-RKMXBOIO.js.map → chunk-O7ROIKTF.js.map} +1 -1
  60. package/dist/chunk-OEGHKO5N.js +1236 -0
  61. package/dist/chunk-OEGHKO5N.js.map +1 -0
  62. package/dist/{chunk-63ZPKREA.js → chunk-P43HBWKK.js} +11 -4
  63. package/dist/chunk-P43HBWKK.js.map +1 -0
  64. package/dist/{chunk-IR6VPAVH.js → chunk-PJ6INYDD.js} +3 -3
  65. package/dist/{chunk-IR6VPAVH.js.map → chunk-PJ6INYDD.js.map} +1 -1
  66. package/dist/{chunk-DHGMYXOY.js → chunk-UGKOWIRP.js} +4 -4
  67. package/dist/{chunk-DHGMYXOY.js.map → chunk-UGKOWIRP.js.map} +1 -1
  68. package/dist/{chunk-WA7ADYSA.js → chunk-UZYTSIX6.js} +6 -6
  69. package/dist/{chunk-WA7ADYSA.js.map → chunk-UZYTSIX6.js.map} +1 -1
  70. package/dist/chunk-V4ZLZJFN.js +86 -0
  71. package/dist/chunk-V4ZLZJFN.js.map +1 -0
  72. package/dist/{chunk-GPMIXOJJ.js → chunk-WSARNOPP.js} +5 -5
  73. package/dist/{chunk-GPMIXOJJ.js.map → chunk-WSARNOPP.js.map} +1 -1
  74. package/dist/cli/index.js +49 -46
  75. package/dist/cli/index.js.map +1 -1
  76. package/dist/connectors/config.js +1 -1
  77. package/dist/connectors/index.js +6 -4
  78. package/dist/core/index.js +1 -1
  79. package/dist/core/src/subprocess.d.ts +5 -1
  80. package/dist/core/src/subprocess.d.ts.map +1 -1
  81. package/dist/deploy/index.js +1 -1
  82. package/dist/discovery/index.js +1 -1
  83. package/dist/discovery/src/requires-graph.d.ts +1 -1
  84. package/dist/discovery/src/requires-graph.d.ts.map +1 -1
  85. package/dist/{ensure-sources-6QMXRI6D.js → ensure-sources-QF72HVUM.js} +8 -8
  86. package/dist/{ensure-sources-6QMXRI6D.js.map → ensure-sources-QF72HVUM.js.map} +1 -1
  87. package/dist/factory-assets/connectors/box.js +6 -4
  88. package/dist/factory-assets/connectors/deploy.js +6 -4
  89. package/dist/factory-assets/connectors/devserver.js +6 -4
  90. package/dist/factory-assets/connectors/flow/CONNECTOR.md +63 -10
  91. package/dist/factory-assets/connectors/flow/adapter.d.ts +79 -36
  92. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  93. package/dist/factory-assets/connectors/flow/adapter.js +6 -4
  94. package/dist/factory-assets/connectors/flow/contract/expression.d.ts +55 -0
  95. package/dist/factory-assets/connectors/flow/contract/expression.d.ts.map +1 -1
  96. package/dist/factory-assets/connectors/flow/contract/flow.v2.schema.json +61 -134
  97. package/dist/factory-assets/connectors/flow/contract/index.d.ts +1 -1
  98. package/dist/factory-assets/connectors/flow/contract/index.d.ts.map +1 -1
  99. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts +4 -1
  100. package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
  101. package/dist/factory-assets/connectors/flow/contract/schema.d.ts +20 -8
  102. package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
  103. package/dist/factory-assets/connectors/flow/contract.js +2 -1024
  104. package/dist/factory-assets/connectors/flow/contract.js.map +1 -1
  105. package/dist/factory-assets/connectors/flow/engine/bindings.d.ts +9 -0
  106. package/dist/factory-assets/connectors/flow/engine/bindings.d.ts.map +1 -0
  107. package/dist/factory-assets/connectors/flow/engine/engine.d.ts +11 -6
  108. package/dist/factory-assets/connectors/flow/engine/engine.d.ts.map +1 -1
  109. package/dist/factory-assets/connectors/flow/engine/flow-kind-provider.d.ts +1 -1
  110. package/dist/factory-assets/connectors/flow/engine/flow-kind-provider.d.ts.map +1 -1
  111. package/dist/factory-assets/connectors/flow/engine/index.d.ts +2 -0
  112. package/dist/factory-assets/connectors/flow/engine/index.d.ts.map +1 -1
  113. package/dist/factory-assets/connectors/flow/engine/loader.d.ts.map +1 -1
  114. package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts +42 -0
  115. package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts.map +1 -0
  116. package/dist/factory-assets/connectors/flow/engine/output-schema.d.ts +18 -0
  117. package/dist/factory-assets/connectors/flow/engine/output-schema.d.ts.map +1 -0
  118. package/dist/factory-assets/connectors/flow/engine/types.d.ts +67 -33
  119. package/dist/factory-assets/connectors/flow/engine/types.d.ts.map +1 -1
  120. package/dist/factory-assets/connectors/flow/engine.js +4 -2
  121. package/dist/factory-assets/connectors/flow/index.d.ts +3 -0
  122. package/dist/factory-assets/connectors/flow/index.d.ts.map +1 -1
  123. package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts +48 -0
  124. package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts.map +1 -0
  125. package/dist/factory-assets/connectors/flow/node-executor.d.ts +45 -0
  126. package/dist/factory-assets/connectors/flow/node-executor.d.ts.map +1 -0
  127. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts +5 -6
  128. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts.map +1 -1
  129. package/dist/factory-assets/connectors/flow/prompt-fragments.js +2 -1
  130. package/dist/factory-assets/connectors/flow/run-flow.d.ts +10 -9
  131. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  132. package/dist/factory-assets/connectors/flow/run-flow.js +7 -5
  133. package/dist/factory-assets/connectors/flow/sub-flow-runner.d.ts +73 -0
  134. package/dist/factory-assets/connectors/flow/sub-flow-runner.d.ts.map +1 -0
  135. package/dist/factory-assets/connectors/flow.js +6 -4
  136. package/dist/factory-assets/connectors/git.js +6 -4
  137. package/dist/factory-assets/connectors/gmail.js +6 -4
  138. package/dist/factory-assets/connectors/googledrive.js +6 -4
  139. package/dist/factory-assets/connectors/local.js +6 -4
  140. package/dist/factory-assets/connectors/mattermost.js +6 -4
  141. package/dist/factory-assets/connectors/memory.js +6 -4
  142. package/dist/factory-assets/connectors/minio.js +6 -4
  143. package/dist/factory-assets/connectors/postgres.js +6 -4
  144. package/dist/factory-assets/connectors/s3.js +6 -4
  145. package/dist/factory-assets/connectors/sharepoint.js +6 -4
  146. package/dist/factory-assets/connectors/sqlite.js +6 -4
  147. package/dist/factory-assets/connectors/static-server.js +6 -4
  148. package/dist/factory-assets/connectors/tunnel.js +6 -4
  149. package/dist/factory-assets/connectors/webdav.js +6 -4
  150. package/dist/factory-assets/connectors/xstate-store.js +6 -4
  151. package/dist/factory-assets/connectors/xstate.js +6 -4
  152. package/dist/{flows-TDDBCLNF.js → flows-YIW4HL3L.js} +4 -4
  153. package/dist/{flows-TDDBCLNF.js.map → flows-YIW4HL3L.js.map} +1 -1
  154. package/dist/{helpers-COQ7TDD4.js → helpers-LURCZHA4.js} +8 -8
  155. package/dist/{helpers-COQ7TDD4.js.map → helpers-LURCZHA4.js.map} +1 -1
  156. package/dist/library/index.js +3 -3
  157. package/dist/library/install.js +1 -1
  158. package/dist/{library-publish-SNPER6PO.js → library-publish-2GMJM3NZ.js} +14 -12
  159. package/dist/library-publish-2GMJM3NZ.js.map +1 -0
  160. package/dist/{open-library-VH2VEYQ7.js → open-library-POFOXZWH.js} +12 -10
  161. package/dist/{open-library-VH2VEYQ7.js.map → open-library-POFOXZWH.js.map} +1 -1
  162. package/dist/{paths-XZA22IB4.js → paths-ZLX4ITAQ.js} +6 -6
  163. package/dist/{paths-XZA22IB4.js.map → paths-ZLX4ITAQ.js.map} +1 -1
  164. package/dist/{plugin-store-CYSNVZIX.js → plugin-store-YIMNH2FH.js} +3 -3
  165. package/dist/{plugin-store-CYSNVZIX.js.map → plugin-store-YIMNH2FH.js.map} +1 -1
  166. package/dist/{project-FKL7PMJV.js → project-GVOPZEJZ.js} +9 -9
  167. package/dist/{project-FKL7PMJV.js.map → project-GVOPZEJZ.js.map} +1 -1
  168. package/dist/resolver/index.js +1 -1
  169. package/dist/runner/index.js +14 -8
  170. package/dist/runner/src/serve.d.ts +3 -1
  171. package/dist/runner/src/serve.d.ts.map +1 -1
  172. package/dist/sdk/asset-manager.js +5 -5
  173. package/dist/sdk/bridge.js +2 -2
  174. package/dist/sdk/core.js +1 -1
  175. package/dist/sdk/flow.js +4 -2
  176. package/dist/sdk/index.js +14 -8
  177. package/dist/sdk/index.js.map +1 -1
  178. package/dist/sdk/resolver.js +1 -1
  179. package/dist/sdk/runner.js +14 -8
  180. package/dist/{setup-BM6HMYJJ.js → setup-TJYLYT2A.js} +5 -5
  181. package/dist/{setup-BM6HMYJJ.js.map → setup-TJYLYT2A.js.map} +1 -1
  182. package/dist/{skills-LHS4TOKK.js → skills-HGVH6UTA.js} +5 -5
  183. package/dist/{skills-LHS4TOKK.js.map → skills-HGVH6UTA.js.map} +1 -1
  184. package/dist/{source-JIUBJC4F.js → source-FB3T4IHP.js} +13 -11
  185. package/dist/{source-JIUBJC4F.js.map → source-FB3T4IHP.js.map} +1 -1
  186. package/dist/{source-manifest-publish-TLH6UWWU.js → source-manifest-publish-XTRDVPSC.js} +15 -13
  187. package/dist/source-manifest-publish-XTRDVPSC.js.map +1 -0
  188. package/dist/tui/index.js +14 -8
  189. package/dist/tui/index.js.map +1 -1
  190. package/dist/types/src/flow.d.ts +26 -0
  191. package/dist/types/src/flow.d.ts.map +1 -1
  192. package/dist/types/src/index.d.ts +1 -1
  193. package/dist/types/src/index.d.ts.map +1 -1
  194. package/dist/workspace-plugin/adapters/mcp.js +4 -4
  195. package/dist/workspace-plugin/adapters/omp.js +7 -7
  196. package/dist/workspace-plugin/index.js +1 -1
  197. package/package.json +1 -1
  198. package/dist/chunk-63ZPKREA.js.map +0 -1
  199. package/dist/chunk-6QSGCHE5.js.map +0 -1
  200. package/dist/chunk-HPGV54O4.js +0 -301
  201. package/dist/chunk-HPGV54O4.js.map +0 -1
  202. package/dist/chunk-MAN7AGQJ.js.map +0 -1
  203. package/dist/chunk-SZJCUC52.js.map +0 -1
  204. package/dist/chunk-TQIU4HQG.js.map +0 -1
  205. package/dist/chunk-Y662DNQQ.js.map +0 -1
  206. package/dist/library-publish-SNPER6PO.js.map +0 -1
  207. package/dist/source-manifest-publish-TLH6UWWU.js.map +0 -1
@@ -0,0 +1,1236 @@
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 FLOW_BINDING_NAME_PATTERN = /^(?!__proto__$)/;
12
+ function collectFlowBindingExpressions(value) {
13
+ if (typeof value === "string") {
14
+ return Array.from(value.matchAll(/\$\{([^{}]+)\}/g), (match) => match[1]);
15
+ }
16
+ if (Array.isArray(value)) return value.flatMap(collectFlowBindingExpressions);
17
+ if (typeof value !== "object" || value === null) return [];
18
+ return Object.values(value).flatMap(collectFlowBindingExpressions);
19
+ }
20
+ var FlowExpressionError = class extends Error {
21
+ /** Stable error name for callers that classify evaluator failures. */
22
+ name = "FlowExpressionError";
23
+ };
24
+ function expressionError(message, position) {
25
+ return new FlowExpressionError(
26
+ position === void 0 ? `Flow expression ${message}` : `Flow expression ${message} at ${position}`
27
+ );
28
+ }
29
+ function parseString(source, start) {
30
+ const quote = source[start];
31
+ let value = "";
32
+ let index = start + 1;
33
+ while (index < source.length) {
34
+ const character = source[index];
35
+ if (character === quote) return { value, end: index + 1 };
36
+ if (character !== "\\") {
37
+ value += character;
38
+ index++;
39
+ continue;
40
+ }
41
+ const escaped = source[index + 1];
42
+ if (escaped === void 0) throw expressionError("has an unterminated string", start);
43
+ const replacements = {
44
+ "\\": "\\",
45
+ "'": "'",
46
+ '"': '"',
47
+ n: "\n",
48
+ r: "\r",
49
+ t: " ",
50
+ b: "\b",
51
+ f: "\f"
52
+ };
53
+ if (escaped === "u") {
54
+ const hex = source.slice(index + 2, index + 6);
55
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
56
+ throw expressionError("has an invalid unicode escape", index);
57
+ }
58
+ value += String.fromCharCode(Number.parseInt(hex, 16));
59
+ index += 6;
60
+ continue;
61
+ }
62
+ if (!(escaped in replacements)) throw expressionError("has an invalid escape", index);
63
+ value += replacements[escaped];
64
+ index += 2;
65
+ }
66
+ throw expressionError("has an unterminated string", start);
67
+ }
68
+ function tokenize(source) {
69
+ if (source.length > FLOW_EXPRESSION_LIMITS.maxLength) {
70
+ throw expressionError(`exceeds the length limit of ${FLOW_EXPRESSION_LIMITS.maxLength}`);
71
+ }
72
+ const tokens = [];
73
+ const add = (token) => {
74
+ tokens.push(token);
75
+ if (tokens.length > FLOW_EXPRESSION_LIMITS.maxTokens) {
76
+ throw expressionError(`exceeds the token limit of ${FLOW_EXPRESSION_LIMITS.maxTokens}`);
77
+ }
78
+ };
79
+ let index = 0;
80
+ while (index < source.length) {
81
+ const character = source[index];
82
+ if (/\s/.test(character)) {
83
+ index++;
84
+ continue;
85
+ }
86
+ const pair = source.slice(index, index + 2);
87
+ if (["&&", "||", "==", "!=", "<=", ">="].includes(pair)) {
88
+ add({ kind: "operator", value: pair, position: index });
89
+ index += 2;
90
+ continue;
91
+ }
92
+ if (["!", "<", ">"].includes(character)) {
93
+ add({ kind: "operator", value: character, position: index });
94
+ index++;
95
+ continue;
96
+ }
97
+ if (["(", ")", "[", "]", ","].includes(character)) {
98
+ add({ kind: "punctuation", value: character, position: index });
99
+ index++;
100
+ continue;
101
+ }
102
+ if (character === "'" || character === '"') {
103
+ const parsed = parseString(source, index);
104
+ add({ kind: "value", value: parsed.value, position: index });
105
+ index = parsed.end;
106
+ continue;
107
+ }
108
+ const number2 = source.slice(index).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/);
109
+ if (number2) {
110
+ add({ kind: "value", value: Number(number2[0]), position: index });
111
+ index += number2[0].length;
112
+ continue;
113
+ }
114
+ const word = source.slice(index).match(/^[A-Za-z_][A-Za-z0-9_.-]*/);
115
+ if (word) {
116
+ const raw = word[0];
117
+ if (raw === "true") add({ kind: "value", value: true, position: index });
118
+ else if (raw === "false") add({ kind: "value", value: false, position: index });
119
+ else if (raw === "null") add({ kind: "value", value: null, position: index });
120
+ else if (raw === "in") add({ kind: "operator", value: raw, position: index });
121
+ else add({ kind: "word", value: raw, position: index });
122
+ index += raw.length;
123
+ continue;
124
+ }
125
+ throw expressionError(`contains unsupported token ${JSON.stringify(character)}`, index);
126
+ }
127
+ tokens.push({ kind: "eof", value: "", position: source.length });
128
+ return tokens;
129
+ }
130
+ var FORBIDDEN_PATH_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
131
+ function ownValue(value, segment, position) {
132
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
133
+ throw expressionError("path does not exist", position);
134
+ }
135
+ if (!Object.hasOwn(value, segment)) throw expressionError("path does not exist", position);
136
+ return value[segment];
137
+ }
138
+ function resolvePath(raw, context, position, traverse) {
139
+ const segments = raw.split(".");
140
+ if (segments.length > FLOW_EXPRESSION_LIMITS.maxPathSegments) {
141
+ throw expressionError(
142
+ `exceeds the path traversal limit of ${FLOW_EXPRESSION_LIMITS.maxPathSegments}`,
143
+ position
144
+ );
145
+ }
146
+ if (segments.some((segment) => segment.length === 0)) {
147
+ throw expressionError("contains an empty path segment", position);
148
+ }
149
+ const forbidden = segments.find((segment) => FORBIDDEN_PATH_SEGMENTS.has(segment));
150
+ if (forbidden) throw expressionError(`contains forbidden path segment ${forbidden}`, position);
151
+ let value;
152
+ let remaining;
153
+ if (segments[0] === "flow" && segments[1] === "input") {
154
+ if (segments.length === 2) {
155
+ throw expressionError("path requires a JSON property suffix", position);
156
+ }
157
+ value = context.flow.input;
158
+ remaining = segments.slice(2);
159
+ } else if (segments[0] === "defaults" && segments.length >= 2) {
160
+ value = context.defaults ?? {};
161
+ remaining = segments.slice(1);
162
+ } else if (segments[0] === "nodes" && segments.length === 3 && segments[2] === "status") {
163
+ value = context.nodes;
164
+ remaining = segments.slice(1);
165
+ } else if (segments[0] === "nodes" && segments.length >= 4 && segments[2] === "output" && segments[3] === "fields") {
166
+ if (segments.length === 4) {
167
+ throw expressionError("path requires a JSON property suffix", position);
168
+ }
169
+ value = context.nodes;
170
+ remaining = segments.slice(1);
171
+ } else {
172
+ throw expressionError(`contains unsupported path ${raw}`, position);
173
+ }
174
+ if (!traverse) return void 0;
175
+ for (const segment of remaining) value = ownValue(value, segment, position);
176
+ return value;
177
+ }
178
+ function compare(operator, left, right, position) {
179
+ if (operator === "==") return Object.is(left, right);
180
+ if (operator === "!=") return !Object.is(left, right);
181
+ if (operator === "in") {
182
+ if (!Array.isArray(right))
183
+ throw expressionError("requires an array on the right of in", position);
184
+ if (right.length > FLOW_EXPRESSION_LIMITS.maxCollectionItems) {
185
+ throw expressionError(
186
+ `exceeds the collection item limit of ${FLOW_EXPRESSION_LIMITS.maxCollectionItems}`,
187
+ position
188
+ );
189
+ }
190
+ return right.some((candidate) => Object.is(candidate, left));
191
+ }
192
+ if (!(typeof left === "number" && typeof right === "number" || typeof left === "string" && typeof right === "string")) {
193
+ throw expressionError(`requires comparable operands for ${operator}`, position);
194
+ }
195
+ if (operator === "<") return left < right;
196
+ if (operator === "<=") return left <= right;
197
+ if (operator === ">") return left > right;
198
+ if (operator === ">=") return left >= right;
199
+ throw expressionError(`contains unsupported operator ${operator}`, position);
200
+ }
201
+ var STATIC_BOOLEAN = /* @__PURE__ */ Symbol("static-boolean");
202
+ var STATIC_PATH = /* @__PURE__ */ Symbol("static-path");
203
+ function isStaticPath(value) {
204
+ return typeof value === "object" && value !== null && value.marker === STATIC_PATH;
205
+ }
206
+ function isBooleanOperand(value) {
207
+ return typeof value === "boolean" || value === STATIC_BOOLEAN || isStaticPath(value);
208
+ }
209
+ function assertBooleanOperand(value, position) {
210
+ if (!isBooleanOperand(value)) throw expressionError("requires boolean operands", position);
211
+ }
212
+ var Parser = class {
213
+ constructor(tokens, context, onPath, onBooleanPath, onEvaluatedPath) {
214
+ this.tokens = tokens;
215
+ this.context = context;
216
+ this.onPath = onPath;
217
+ this.onBooleanPath = onBooleanPath;
218
+ this.onEvaluatedPath = onEvaluatedPath;
219
+ }
220
+ tokens;
221
+ context;
222
+ onPath;
223
+ onBooleanPath;
224
+ onEvaluatedPath;
225
+ index = 0;
226
+ nesting = 0;
227
+ parse(evaluate2 = true) {
228
+ const value = this.parseOr(evaluate2);
229
+ const trailing = this.peek();
230
+ if (trailing.kind !== "eof") {
231
+ throw expressionError(
232
+ `contains unexpected token ${String(trailing.value)}`,
233
+ trailing.position
234
+ );
235
+ }
236
+ return value;
237
+ }
238
+ peek() {
239
+ return this.tokens[this.index];
240
+ }
241
+ take() {
242
+ return this.tokens[this.index++];
243
+ }
244
+ accept(value) {
245
+ if (this.peek().value !== value) return void 0;
246
+ return this.take();
247
+ }
248
+ parseOr(evaluate2) {
249
+ let value = this.parseAnd(evaluate2);
250
+ while (this.peek().value === "||") {
251
+ const operator = this.take();
252
+ assertBooleanOperand(value, operator.position);
253
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
254
+ const evaluateRight = evaluate2 && value === false;
255
+ const right = this.parseAnd(evaluateRight);
256
+ assertBooleanOperand(right, operator.position);
257
+ if (isStaticPath(right)) this.onBooleanPath?.(right.path);
258
+ value = evaluate2 ? value === true || right === true : STATIC_BOOLEAN;
259
+ }
260
+ return value;
261
+ }
262
+ parseAnd(evaluate2) {
263
+ let value = this.parseComparison(evaluate2);
264
+ while (this.peek().value === "&&") {
265
+ const operator = this.take();
266
+ assertBooleanOperand(value, operator.position);
267
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
268
+ const evaluateRight = evaluate2 && value === true;
269
+ const right = this.parseComparison(evaluateRight);
270
+ assertBooleanOperand(right, operator.position);
271
+ if (isStaticPath(right)) this.onBooleanPath?.(right.path);
272
+ value = evaluate2 ? value === true && right === true : STATIC_BOOLEAN;
273
+ }
274
+ return value;
275
+ }
276
+ parseComparison(evaluate2) {
277
+ const left = this.parseUnary(evaluate2);
278
+ const token = this.peek();
279
+ if (token.kind !== "operator" || !["==", "!=", "<", "<=", ">", ">=", "in"].includes(String(token.value))) {
280
+ return left;
281
+ }
282
+ this.take();
283
+ const right = this.parseUnary(evaluate2);
284
+ return evaluate2 ? compare(String(token.value), left, right, token.position) : STATIC_BOOLEAN;
285
+ }
286
+ parseUnary(evaluate2) {
287
+ const operator = this.accept("!");
288
+ if (operator) {
289
+ const value = this.parseUnary(evaluate2);
290
+ assertBooleanOperand(value, operator.position);
291
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
292
+ return evaluate2 ? value === false : STATIC_BOOLEAN;
293
+ }
294
+ return this.parsePrimary(evaluate2);
295
+ }
296
+ parsePrimary(evaluate2) {
297
+ const token = this.take();
298
+ if (token.kind === "value") return token.value;
299
+ if (token.kind === "word") {
300
+ this.onPath?.(String(token.value));
301
+ resolvePath(String(token.value), this.context, token.position, false);
302
+ if (evaluate2) this.onEvaluatedPath?.(String(token.value));
303
+ return evaluate2 ? resolvePath(String(token.value), this.context, token.position, true) : { marker: STATIC_PATH, path: String(token.value) };
304
+ }
305
+ if (token.value === "(") {
306
+ this.enterNesting(token.position);
307
+ const value = this.parseOr(evaluate2);
308
+ if (!this.accept(")"))
309
+ throw expressionError("is missing a closing parenthesis", token.position);
310
+ this.nesting--;
311
+ return value;
312
+ }
313
+ if (token.value === "[") {
314
+ this.enterNesting(token.position);
315
+ const values = [];
316
+ if (!this.accept("]")) {
317
+ do
318
+ values.push(this.parsePrimary(evaluate2));
319
+ while (this.accept(","));
320
+ if (!this.accept("]"))
321
+ throw expressionError("is missing a closing bracket", token.position);
322
+ }
323
+ this.nesting--;
324
+ return values;
325
+ }
326
+ throw expressionError(`contains unexpected token ${String(token.value)}`, token.position);
327
+ }
328
+ enterNesting(position) {
329
+ this.nesting++;
330
+ if (this.nesting > FLOW_EXPRESSION_LIMITS.maxNesting) {
331
+ throw expressionError(
332
+ `exceeds the nesting limit of ${FLOW_EXPRESSION_LIMITS.maxNesting}`,
333
+ position
334
+ );
335
+ }
336
+ }
337
+ };
338
+ function inspectFlowExpression(expression, requireBoolean = true) {
339
+ const tokens = tokenize(expression);
340
+ if (expression.trim() === "default") return [];
341
+ const references = /* @__PURE__ */ new Map();
342
+ const record3 = (path, booleanOperand) => {
343
+ references.set(path, (references.get(path) ?? false) || booleanOperand);
344
+ };
345
+ const context = { flow: { input: {} }, nodes: {} };
346
+ const result = new Parser(
347
+ tokens,
348
+ context,
349
+ (path) => record3(path, false),
350
+ (path) => record3(path, true)
351
+ ).parse(false);
352
+ if (requireBoolean && typeof result !== "boolean" && result !== STATIC_BOOLEAN) {
353
+ throw expressionError("must evaluate to a boolean");
354
+ }
355
+ return Array.from(references, ([path, booleanOperand]) => ({ path, booleanOperand }));
356
+ }
357
+ function evaluateFlowExpression(expression, context) {
358
+ const tokens = tokenize(expression);
359
+ if (expression.trim() === "default") return true;
360
+ const result = new Parser(tokens, context).parse();
361
+ if (typeof result !== "boolean") {
362
+ throw expressionError("must evaluate to a boolean");
363
+ }
364
+ return result;
365
+ }
366
+ function evaluate(expression, context) {
367
+ return evaluateFlowExpression(expression, context);
368
+ }
369
+ function evaluateFlowExpressionValue(expression, context) {
370
+ const tokens = tokenize(expression);
371
+ if (expression.trim() === "default") return { value: true, paths: [] };
372
+ const paths = [];
373
+ const value = new Parser(
374
+ tokens,
375
+ context,
376
+ void 0,
377
+ void 0,
378
+ (path) => paths.push(path)
379
+ ).parse();
380
+ return { value, paths };
381
+ }
382
+ function originsForPath(path, nodeOutputOrigin, flowInputOrigins) {
383
+ if (path.startsWith("flow.input.")) {
384
+ const inputName = path.split(".")[2];
385
+ const inherited = flowInputOrigins[inputName];
386
+ return inherited ?? [{ source: "flow-input", path, obtainedBy: "runtime" }];
387
+ }
388
+ if (path.startsWith("defaults.")) {
389
+ return [{ source: "default", path, obtainedBy: "runtime" }];
390
+ }
391
+ const segments = path.split(".");
392
+ const nodeId = segments[1];
393
+ if (segments.length === 3 && segments[0] === "nodes" && segments[2] === "status") {
394
+ return [{ source: "node-status", nodeId, path, obtainedBy: "runtime" }];
395
+ }
396
+ if (segments.length >= 5 && segments[0] === "nodes" && segments[2] === "output" && segments[3] === "fields") {
397
+ const obtainedBy = nodeOutputOrigin[nodeId];
398
+ if (!obtainedBy) {
399
+ throw expressionError(`has no output origin for node ${nodeId}`);
400
+ }
401
+ return [{ source: "node-output", nodeId, path, obtainedBy }];
402
+ }
403
+ throw expressionError(`contains unsupported path ${path}`);
404
+ }
405
+ function stableFlowJson(value) {
406
+ if (value === void 0) return "null";
407
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
408
+ if (Array.isArray(value)) return `[${value.map(stableFlowJson).join(",")}]`;
409
+ const object = value;
410
+ return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableFlowJson(object[key])}`).join(",")}}`;
411
+ }
412
+ function interpolationText(value) {
413
+ if (typeof value === "string") return value;
414
+ return stableFlowJson(value);
415
+ }
416
+ function deduplicateOrigins(origins) {
417
+ const seen = /* @__PURE__ */ new Set();
418
+ return origins.filter((origin) => {
419
+ const key = JSON.stringify(origin);
420
+ if (seen.has(key)) return false;
421
+ seen.add(key);
422
+ return true;
423
+ });
424
+ }
425
+ function resolveBindingValue(authored, bindingPath, context, nodeOutputOrigin, flowInputOrigins, depth) {
426
+ if (depth > FLOW_EXPRESSION_LIMITS.maxNesting) {
427
+ throw expressionError(`exceeds the nesting limit of ${FLOW_EXPRESSION_LIMITS.maxNesting}`);
428
+ }
429
+ if (typeof authored === "string") {
430
+ const exact = authored.match(/^\$\{([^{}]+)\}$/);
431
+ if (exact) {
432
+ const evaluated = evaluateFlowExpressionValue(exact[1], context);
433
+ return {
434
+ value: evaluated.value,
435
+ origins: deduplicateOrigins(
436
+ evaluated.paths.flatMap(
437
+ (path) => originsForPath(path, nodeOutputOrigin, flowInputOrigins)
438
+ )
439
+ )
440
+ };
441
+ }
442
+ const matches = Array.from(authored.matchAll(/\$\{([^{}]+)\}/g));
443
+ if (matches.length === 0) {
444
+ return {
445
+ value: authored,
446
+ origins: [{ source: "literal", path: bindingPath, obtainedBy: "runtime" }]
447
+ };
448
+ }
449
+ const origins = [
450
+ { source: "literal", path: bindingPath, obtainedBy: "runtime" }
451
+ ];
452
+ const value = authored.replace(/\$\{([^{}]+)\}/g, (_placeholder, expression) => {
453
+ const evaluated = evaluateFlowExpressionValue(expression, context);
454
+ origins.push(
455
+ ...evaluated.paths.flatMap(
456
+ (path) => originsForPath(path, nodeOutputOrigin, flowInputOrigins)
457
+ )
458
+ );
459
+ return interpolationText(evaluated.value);
460
+ });
461
+ return { value, origins: deduplicateOrigins(origins) };
462
+ }
463
+ if (Array.isArray(authored)) {
464
+ if (authored.length > FLOW_EXPRESSION_LIMITS.maxCollectionItems) {
465
+ throw expressionError(
466
+ `exceeds the collection item limit of ${FLOW_EXPRESSION_LIMITS.maxCollectionItems}`
467
+ );
468
+ }
469
+ const resolved = authored.map(
470
+ (value) => resolveBindingValue(
471
+ value,
472
+ bindingPath,
473
+ context,
474
+ nodeOutputOrigin,
475
+ flowInputOrigins,
476
+ depth + 1
477
+ )
478
+ );
479
+ return {
480
+ value: resolved.map(({ value }) => value),
481
+ origins: deduplicateOrigins([
482
+ { source: "literal", path: bindingPath, obtainedBy: "runtime" },
483
+ ...resolved.flatMap(({ origins }) => origins)
484
+ ])
485
+ };
486
+ }
487
+ if (typeof authored === "object" && authored !== null) {
488
+ const entries = Object.entries(authored);
489
+ if (entries.length > FLOW_EXPRESSION_LIMITS.maxCollectionItems) {
490
+ throw expressionError(
491
+ `exceeds the collection item limit of ${FLOW_EXPRESSION_LIMITS.maxCollectionItems}`
492
+ );
493
+ }
494
+ const resolved = entries.map(
495
+ ([key, value]) => [
496
+ key,
497
+ resolveBindingValue(
498
+ value,
499
+ bindingPath,
500
+ context,
501
+ nodeOutputOrigin,
502
+ flowInputOrigins,
503
+ depth + 1
504
+ )
505
+ ]
506
+ );
507
+ return {
508
+ value: Object.fromEntries(resolved.map(([key, result]) => [key, result.value])),
509
+ origins: deduplicateOrigins([
510
+ { source: "literal", path: bindingPath, obtainedBy: "runtime" },
511
+ ...resolved.flatMap(([, result]) => result.origins)
512
+ ])
513
+ };
514
+ }
515
+ return {
516
+ value: authored,
517
+ origins: [{ source: "literal", path: bindingPath, obtainedBy: "runtime" }]
518
+ };
519
+ }
520
+ function resolveFlowBindings(bindings, context, nodeOutputOrigin = {}, flowInputOrigins = {}) {
521
+ const values = {};
522
+ const origins = {};
523
+ const entries = Object.entries(bindings ?? {});
524
+ for (const [name] of entries) {
525
+ if (!FLOW_BINDING_NAME_PATTERN.test(name)) {
526
+ throw expressionError(`contains reserved binding name input.${name}`);
527
+ }
528
+ }
529
+ for (const [name, authored] of entries) {
530
+ const resolved = resolveBindingValue(
531
+ authored,
532
+ `input.${name}`,
533
+ context,
534
+ nodeOutputOrigin,
535
+ flowInputOrigins,
536
+ 0
537
+ );
538
+ values[name] = resolved.value;
539
+ origins[name] = resolved.origins;
540
+ }
541
+ return { values, origins };
542
+ }
543
+ var nonEmptyString = z.string().min(1);
544
+ var flowAssetIdentity = z.string().regex(
545
+ /^[a-z0-9]+(?:-[a-z0-9]+)*$/,
546
+ "Flow identity must be lowercase kebab-case without path separators"
547
+ );
548
+ var jsonSchema = z.record(z.string(), z.json());
549
+ var bindingName = z.string().regex(FLOW_BINDING_NAME_PATTERN, "Binding name is reserved");
550
+ var nodeBindings = z.preprocess(
551
+ (value, context) => {
552
+ if (typeof value === "object" && value !== null) {
553
+ for (const key of Object.keys(value)) {
554
+ if (!FLOW_BINDING_NAME_PATTERN.test(key)) {
555
+ context.addIssue({ code: "custom", path: [key], message: "Binding name is reserved" });
556
+ }
557
+ }
558
+ }
559
+ return value;
560
+ },
561
+ z.record(bindingName, z.json())
562
+ );
563
+ var FlowInputContractSchema = z.strictObject({
564
+ schema: jsonSchema,
565
+ example: z.json().optional()
566
+ });
567
+ var FlowOutputContractSchema = z.strictObject({
568
+ schema: jsonSchema
569
+ });
570
+ var PreconditionSchema = z.strictObject({
571
+ expr: nonEmptyString,
572
+ message: nonEmptyString.optional()
573
+ });
574
+ var ArtifactContractSchema = z.strictObject({
575
+ kind: nonEmptyString,
576
+ lifetime: z.enum(["session", "persistent"])
577
+ });
578
+ var NodeOutputContractSchema = z.strictObject({
579
+ fields: jsonSchema.optional(),
580
+ artifacts: z.array(ArtifactContractSchema).optional()
581
+ });
582
+ var NodeContractSchema = z.strictObject({
583
+ requires: z.array(PreconditionSchema).optional(),
584
+ input: nodeBindings.optional(),
585
+ output: NodeOutputContractSchema.optional()
586
+ });
587
+ var NodeGateSchema = z.strictObject({
588
+ approval: z.enum(["none", "optional", "mandatory"])
589
+ });
590
+ var NodeControlSchema = z.strictObject({
591
+ optional: z.boolean().optional(),
592
+ retries: z.number().int().min(0).optional(),
593
+ timeoutSec: z.number().positive().optional(),
594
+ parallelGroup: nonEmptyString.optional(),
595
+ subagent: z.boolean().optional()
596
+ });
597
+ var runAssets = { assets: z.array(nonEmptyString).optional() };
598
+ var AgentRunSchema = z.strictObject({
599
+ kind: z.literal("agent"),
600
+ instruction: nonEmptyString,
601
+ ...runAssets
602
+ });
603
+ var SubpromptRunSchema = z.strictObject({
604
+ kind: z.literal("subprompt"),
605
+ instruction: nonEmptyString,
606
+ model: nonEmptyString.optional(),
607
+ ...runAssets
608
+ });
609
+ var deterministicRun = {
610
+ runtime: z.enum(["shell", "node", "python"]).optional(),
611
+ command: nonEmptyString,
612
+ cwd: nonEmptyString.optional(),
613
+ successExit: z.array(z.number().int()).optional(),
614
+ capture: z.strictObject({ stdout: nonEmptyString.optional(), stderr: nonEmptyString.optional() }).optional(),
615
+ ...runAssets
616
+ };
617
+ var FunctionRunSchema = z.strictObject({
618
+ kind: z.literal("function"),
619
+ ...deterministicRun
620
+ });
621
+ var CheckRunSchema = z.strictObject({
622
+ kind: z.literal("check"),
623
+ onFail: z.enum(["escalate", "fail"]).default("escalate"),
624
+ ...deterministicRun
625
+ });
626
+ var InputChoiceSchema = z.strictObject({
627
+ id: nonEmptyString,
628
+ label: nonEmptyString,
629
+ description: nonEmptyString.optional()
630
+ });
631
+ var FormFieldSchema = z.strictObject({
632
+ id: nonEmptyString,
633
+ label: nonEmptyString,
634
+ type: z.enum(["text", "textarea", "number", "choice", "file", "date", "boolean"]),
635
+ required: z.boolean().optional(),
636
+ options: z.array(InputChoiceSchema).optional(),
637
+ accept: z.array(nonEmptyString).optional()
638
+ });
639
+ var InputSchema = z.discriminatedUnion("kind", [
640
+ z.strictObject({ kind: z.literal("text"), multiline: z.boolean().optional() }),
641
+ z.strictObject({
642
+ kind: z.literal("choice"),
643
+ options: z.array(InputChoiceSchema).min(1),
644
+ multiple: z.boolean().optional()
645
+ }),
646
+ z.strictObject({ kind: z.literal("form"), fields: z.array(FormFieldSchema) }),
647
+ z.strictObject({
648
+ kind: z.literal("file"),
649
+ accept: z.array(nonEmptyString).optional(),
650
+ maxSize: z.number().positive().optional(),
651
+ multiple: z.boolean().optional()
652
+ })
653
+ ]);
654
+ var GateRunSchema = z.strictObject({
655
+ kind: z.literal("gate"),
656
+ prompt: nonEmptyString,
657
+ schema: InputSchema,
658
+ ...runAssets
659
+ });
660
+ var RouteSchema = z.strictObject({
661
+ when: nonEmptyString,
662
+ target: nonEmptyString.nullable()
663
+ });
664
+ var RouterRunSchema = z.strictObject({
665
+ kind: z.literal("router"),
666
+ routes: z.array(RouteSchema).min(1),
667
+ ...runAssets
668
+ });
669
+ var SubFlowRunSchema = z.strictObject({
670
+ kind: z.literal("sub-flow"),
671
+ flow: flowAssetIdentity,
672
+ passContext: z.boolean().optional(),
673
+ ...runAssets
674
+ });
675
+ var RunSchema = z.discriminatedUnion("kind", [
676
+ AgentRunSchema,
677
+ SubpromptRunSchema,
678
+ FunctionRunSchema,
679
+ CheckRunSchema,
680
+ GateRunSchema,
681
+ RouterRunSchema,
682
+ SubFlowRunSchema
683
+ ]);
684
+ var NodeSchema = z.strictObject({
685
+ id: nonEmptyString,
686
+ label: nonEmptyString,
687
+ description: nonEmptyString,
688
+ phase: nonEmptyString.optional(),
689
+ run: RunSchema,
690
+ contract: NodeContractSchema.optional(),
691
+ gate: NodeGateSchema.optional(),
692
+ control: NodeControlSchema.optional()
693
+ });
694
+ var EdgeSchema = z.strictObject({
695
+ id: nonEmptyString,
696
+ source: nonEmptyString,
697
+ target: nonEmptyString,
698
+ type: z.enum(["flow", "parallel", "optional"])
699
+ });
700
+ var FlowDefaultsSchema = z.strictObject({
701
+ approval: z.enum(["checkpoint", "auto", "manual"]).optional(),
702
+ researchDepth: nonEmptyString.optional(),
703
+ autoReview: z.boolean().optional(),
704
+ subagentMode: z.boolean().optional(),
705
+ verbosity: nonEmptyString.optional(),
706
+ cliMode: z.boolean().optional(),
707
+ run_input: z.json().optional(),
708
+ parameters: z.record(z.string(), z.json()).optional()
709
+ });
710
+ var FlowMetaSchema = z.strictObject({
711
+ icon: nonEmptyString.optional(),
712
+ category: nonEmptyString.optional(),
713
+ tags: z.array(nonEmptyString).optional(),
714
+ stage: nonEmptyString.optional(),
715
+ onboarding: z.strictObject({
716
+ input_style: z.enum(["freeform", "structured", "repo"]),
717
+ placeholder: nonEmptyString.optional(),
718
+ fields: z.array(nonEmptyString).optional()
719
+ }).optional()
720
+ });
721
+ var FlowDefinitionObjectSchema = z.strictObject({
722
+ $schema: nonEmptyString.optional(),
723
+ schemaVersion: z.literal(2),
724
+ id: nonEmptyString,
725
+ version: nonEmptyString,
726
+ name: nonEmptyString,
727
+ description: nonEmptyString.optional(),
728
+ input: FlowInputContractSchema.optional(),
729
+ output: FlowOutputContractSchema.optional(),
730
+ defaults: FlowDefaultsSchema.optional(),
731
+ entry: nonEmptyString.optional(),
732
+ nodes: z.array(NodeSchema),
733
+ edges: z.array(EdgeSchema),
734
+ meta: FlowMetaSchema.optional()
735
+ });
736
+ function parseFlowDefinitionStructure(data) {
737
+ return FlowDefinitionObjectSchema.safeParse(data);
738
+ }
739
+ var MISSING_FIELD = /* @__PURE__ */ Symbol("missing-field");
740
+ function declaredFieldSchema(schema, path) {
741
+ let current = schema;
742
+ for (const segment of path) {
743
+ if (typeof current !== "object" || current === null) return MISSING_FIELD;
744
+ const properties = current.properties;
745
+ if (typeof properties !== "object" || properties === null || !Object.hasOwn(properties, segment)) {
746
+ return MISSING_FIELD;
747
+ }
748
+ current = properties[segment];
749
+ }
750
+ return current;
751
+ }
752
+ function knownNonBooleanType(schema) {
753
+ if (typeof schema !== "object" || schema === null) return void 0;
754
+ const type = schema.type;
755
+ if (typeof type === "string") return type === "boolean" ? void 0 : type;
756
+ if (Array.isArray(type) && type.length > 0 && type.every((candidate) => typeof candidate === "string") && type.some((candidate) => candidate !== "boolean")) {
757
+ return type.join(" | ");
758
+ }
759
+ return void 0;
760
+ }
761
+ var FlowDefinitionSchema = FlowDefinitionObjectSchema.superRefine((flow, context) => {
762
+ const nodeIds = /* @__PURE__ */ new Set();
763
+ for (const [index, node] of flow.nodes.entries()) {
764
+ if (nodeIds.has(node.id)) {
765
+ context.addIssue({
766
+ code: "custom",
767
+ path: ["nodes", index, "id"],
768
+ message: `duplicate node id: ${node.id}`
769
+ });
770
+ }
771
+ nodeIds.add(node.id);
772
+ if (node.control?.optional === true && (node.gate?.approval === "mandatory" || node.run.kind === "gate")) {
773
+ context.addIssue({
774
+ code: "custom",
775
+ path: ["nodes", index, "control", "optional"],
776
+ message: node.run.kind === "gate" ? "a first-class gate node cannot be optional" : "a node cannot be both optional and a mandatory approval gate"
777
+ });
778
+ }
779
+ }
780
+ if (flow.entry !== void 0 && !nodeIds.has(flow.entry)) {
781
+ context.addIssue({ code: "custom", path: ["entry"], message: `unknown node: ${flow.entry}` });
782
+ }
783
+ const outgoing = /* @__PURE__ */ new Map();
784
+ for (const [edgeIndex, edge] of flow.edges.entries()) {
785
+ if (!nodeIds.has(edge.source)) {
786
+ context.addIssue({
787
+ code: "custom",
788
+ path: ["edges", edgeIndex, "source"],
789
+ message: `unknown node: ${edge.source}`
790
+ });
791
+ }
792
+ if (!nodeIds.has(edge.target)) {
793
+ context.addIssue({
794
+ code: "custom",
795
+ path: ["edges", edgeIndex, "target"],
796
+ message: `unknown node: ${edge.target}`
797
+ });
798
+ }
799
+ if (edge.type === "flow" && nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
800
+ const edges = outgoing.get(edge.source) ?? [];
801
+ edges.push({ target: edge.target, path: ["edges", edgeIndex] });
802
+ outgoing.set(edge.source, edges);
803
+ }
804
+ }
805
+ for (const [nodeIndex, node] of flow.nodes.entries()) {
806
+ if (node.run.kind !== "router") continue;
807
+ for (const [routeIndex, route] of node.run.routes.entries()) {
808
+ if (route.target !== null && !nodeIds.has(route.target)) {
809
+ context.addIssue({
810
+ code: "custom",
811
+ path: ["nodes", nodeIndex, "run", "routes", routeIndex, "target"],
812
+ message: `unknown node: ${route.target}`
813
+ });
814
+ }
815
+ }
816
+ }
817
+ const validateExpression = (expression, path, requireBoolean = true) => {
818
+ let references;
819
+ try {
820
+ references = inspectFlowExpression(expression, requireBoolean);
821
+ } catch (error) {
822
+ context.addIssue({
823
+ code: "custom",
824
+ path,
825
+ message: error instanceof Error ? error.message : "invalid Flow expression"
826
+ });
827
+ return;
828
+ }
829
+ for (const reference of references) {
830
+ const segments = reference.path.split(".");
831
+ if (segments[0] !== "nodes") continue;
832
+ const producer = flow.nodes.find((node) => node.id === segments[1]);
833
+ if (!producer) {
834
+ context.addIssue({
835
+ code: "custom",
836
+ path,
837
+ message: `unknown producer node: ${segments[1]}`
838
+ });
839
+ continue;
840
+ }
841
+ if (segments[2] === "status") {
842
+ if (reference.booleanOperand) {
843
+ context.addIssue({ code: "custom", path, message: "node status is not boolean" });
844
+ }
845
+ continue;
846
+ }
847
+ const outputSchema = producer.contract?.output?.fields;
848
+ if (!outputSchema) {
849
+ context.addIssue({
850
+ code: "custom",
851
+ path,
852
+ message: `node ${producer.id} has no declared output fields`
853
+ });
854
+ continue;
855
+ }
856
+ const fieldPath = segments.slice(4);
857
+ const fieldSchema = declaredFieldSchema(outputSchema, fieldPath);
858
+ if (fieldSchema === MISSING_FIELD) {
859
+ context.addIssue({
860
+ code: "custom",
861
+ path,
862
+ message: `node ${producer.id} does not declare output field ${fieldPath.join(".")}`
863
+ });
864
+ continue;
865
+ }
866
+ const nonBooleanType = reference.booleanOperand ? knownNonBooleanType(fieldSchema) : void 0;
867
+ if (nonBooleanType) {
868
+ context.addIssue({
869
+ code: "custom",
870
+ path,
871
+ message: `node ${producer.id} output field ${fieldPath.join(".")} is ${nonBooleanType}, not boolean`
872
+ });
873
+ }
874
+ }
875
+ };
876
+ for (const [nodeIndex, node] of flow.nodes.entries()) {
877
+ for (const [requireIndex, requirement] of node.contract?.requires?.entries() ?? []) {
878
+ validateExpression(requirement.expr, [
879
+ "nodes",
880
+ nodeIndex,
881
+ "contract",
882
+ "requires",
883
+ requireIndex,
884
+ "expr"
885
+ ]);
886
+ }
887
+ for (const [bindingName2, binding] of Object.entries(node.contract?.input ?? {})) {
888
+ for (const expression of collectFlowBindingExpressions(binding)) {
889
+ validateExpression(
890
+ expression,
891
+ ["nodes", nodeIndex, "contract", "input", bindingName2],
892
+ false
893
+ );
894
+ }
895
+ }
896
+ if (node.run.kind === "router") {
897
+ for (const [routeIndex, route] of node.run.routes.entries()) {
898
+ validateExpression(route.when, ["nodes", nodeIndex, "run", "routes", routeIndex, "when"]);
899
+ }
900
+ }
901
+ }
902
+ const state = /* @__PURE__ */ new Map();
903
+ for (const nodeId of nodeIds) {
904
+ if (state.has(nodeId)) continue;
905
+ const stack = [{ nodeId, next: 0 }];
906
+ state.set(nodeId, "active");
907
+ while (stack.length > 0) {
908
+ const frame = stack.at(-1);
909
+ if (!frame) break;
910
+ const arcs = outgoing.get(frame.nodeId) ?? [];
911
+ if (frame.next >= arcs.length) {
912
+ state.set(frame.nodeId, "done");
913
+ stack.pop();
914
+ continue;
915
+ }
916
+ const arc = arcs[frame.next++];
917
+ if (state.get(arc.target) === "active") {
918
+ context.addIssue({ code: "custom", path: arc.path, message: "flow graph must be acyclic" });
919
+ } else if (!state.has(arc.target)) {
920
+ state.set(arc.target, "active");
921
+ stack.push({ nodeId: arc.target, next: 0 });
922
+ }
923
+ }
924
+ }
925
+ });
926
+ var successfullyParsedDefinitions = /* @__PURE__ */ new WeakMap();
927
+ function valueFingerprint(value, ancestors) {
928
+ if (value === null) return "null";
929
+ if (value === void 0) return "undefined";
930
+ if (typeof value === "string") return `string:${JSON.stringify(value)}`;
931
+ if (typeof value === "boolean") return `boolean:${value}`;
932
+ if (typeof value === "number") {
933
+ if (!Number.isFinite(value)) return null;
934
+ return `number:${Object.is(value, -0) ? "-0" : value}`;
935
+ }
936
+ if (typeof value !== "object" || ancestors.has(value)) return null;
937
+ ancestors.add(value);
938
+ try {
939
+ if (Array.isArray(value)) {
940
+ if (Object.getPrototypeOf(value) !== Array.prototype) return null;
941
+ if (Object.getOwnPropertySymbols(value).length > 0) return null;
942
+ const names = Object.getOwnPropertyNames(value);
943
+ if (names.length !== value.length + 1 || !names.includes("length")) return null;
944
+ const items = [];
945
+ for (let index = 0; index < value.length; index += 1) {
946
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
947
+ if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) return null;
948
+ const item = valueFingerprint(descriptor.value, ancestors);
949
+ if (item === null) return null;
950
+ items.push(item);
951
+ }
952
+ return `array:[${items.join(",")}]`;
953
+ }
954
+ const prototype = Object.getPrototypeOf(value);
955
+ if (prototype !== Object.prototype && prototype !== null) return null;
956
+ if (Object.getOwnPropertySymbols(value).length > 0) return null;
957
+ const entries = [];
958
+ for (const key of Object.getOwnPropertyNames(value).sort()) {
959
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
960
+ if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) return null;
961
+ const nested = valueFingerprint(descriptor.value, ancestors);
962
+ if (nested === null) return null;
963
+ entries.push(`${JSON.stringify(key)}:${nested}`);
964
+ }
965
+ return `object:{${entries.join(",")}}`;
966
+ } finally {
967
+ ancestors.delete(value);
968
+ }
969
+ }
970
+ function definitionFingerprint(data) {
971
+ return valueFingerprint(data, /* @__PURE__ */ new Set());
972
+ }
973
+ var LegacyRouteSchema = z.looseObject({
974
+ condition: z.string().min(1),
975
+ target: z.string().min(1).nullable()
976
+ });
977
+ var LegacyNodeDataSchema = z.looseObject({
978
+ skill: z.string().min(1).optional(),
979
+ version: z.string().min(1).optional(),
980
+ label: z.string().min(1).optional(),
981
+ description: z.string().min(1).optional(),
982
+ optional: z.boolean().optional(),
983
+ approval: z.looseObject({ mandatory: z.boolean().optional() }).optional(),
984
+ parameters: z.record(z.string(), z.unknown()).optional(),
985
+ phase: z.string().min(1).optional(),
986
+ parallel_group: z.string().min(1).optional(),
987
+ flow: z.string().min(1).optional(),
988
+ pass_context: z.boolean().optional(),
989
+ subagent: z.boolean().optional(),
990
+ message: z.string().min(1).optional(),
991
+ routes: z.array(LegacyRouteSchema).optional(),
992
+ assets: z.array(z.string().min(1)).optional()
993
+ });
994
+ var LegacyNodeSchema = z.looseObject({
995
+ id: z.string().min(1),
996
+ type: z.string().min(1).optional(),
997
+ skill: z.string().min(1).optional(),
998
+ label: z.string().min(1).optional(),
999
+ description: z.string().min(1).optional(),
1000
+ data: LegacyNodeDataSchema.optional()
1001
+ });
1002
+ var LegacyEdgeSchema = z.looseObject({
1003
+ id: z.string().min(1).optional(),
1004
+ source: z.string().min(1),
1005
+ target: z.string().min(1),
1006
+ type: z.string().min(1).optional()
1007
+ });
1008
+ var LegacyFlowSchema = z.looseObject({
1009
+ id: z.string().min(1),
1010
+ version: z.string().min(1).optional(),
1011
+ name: z.string().min(1),
1012
+ description: z.string().min(1).optional(),
1013
+ requires: z.array(z.string().min(1)).optional(),
1014
+ globals: z.record(z.string(), z.unknown()).optional(),
1015
+ entry: z.string().min(1).optional(),
1016
+ nodes: z.array(LegacyNodeSchema).optional(),
1017
+ edges: z.array(LegacyEdgeSchema).optional(),
1018
+ meta: z.record(z.string(), z.unknown()).optional(),
1019
+ metadata: z.record(z.string(), z.unknown()).optional()
1020
+ });
1021
+ function success(data) {
1022
+ const fingerprint = definitionFingerprint(data);
1023
+ if (fingerprint !== null) successfullyParsedDefinitions.set(data, fingerprint);
1024
+ return { ok: true, data };
1025
+ }
1026
+ function failure(error) {
1027
+ return {
1028
+ ok: false,
1029
+ errors: error.issues.map((issue) => ({
1030
+ path: issue.path.map(String).join("."),
1031
+ message: issue.message
1032
+ }))
1033
+ };
1034
+ }
1035
+ var LEGACY_DEFAULT_KEYS = {
1036
+ approval_mode: "approval",
1037
+ research_depth: "researchDepth",
1038
+ auto_review: "autoReview",
1039
+ subagent_mode: "subagentMode",
1040
+ verbosity: "verbosity",
1041
+ cli_mode: "cliMode",
1042
+ run_input: "run_input"
1043
+ };
1044
+ function normalizeDefaults(globals) {
1045
+ if (!globals) return void 0;
1046
+ const known = {};
1047
+ const parameters = {};
1048
+ for (const [key, value] of Object.entries(globals)) {
1049
+ const normalizedKey = LEGACY_DEFAULT_KEYS[key];
1050
+ if (normalizedKey) {
1051
+ known[normalizedKey] = key === "approval_mode" && value === "auto_approve" ? "auto" : value;
1052
+ } else {
1053
+ parameters[key] = value;
1054
+ }
1055
+ }
1056
+ if (Object.keys(parameters).length > 0) known.parameters = parameters;
1057
+ return Object.keys(known).length > 0 ? known : void 0;
1058
+ }
1059
+ function normalizeMeta(value) {
1060
+ if (!value) return void 0;
1061
+ const meta = {};
1062
+ if (typeof value.icon === "string") meta.icon = value.icon;
1063
+ if (typeof value.category === "string") meta.category = value.category;
1064
+ if (Array.isArray(value.tags)) meta.tags = value.tags;
1065
+ if (typeof value.stage === "string") meta.stage = value.stage;
1066
+ if (typeof value.onboarding === "object" && value.onboarding !== null) {
1067
+ const onboarding = value.onboarding;
1068
+ if (onboarding.input_style === "freeform" || onboarding.input_style === "structured" || onboarding.input_style === "repo") {
1069
+ meta.onboarding = {
1070
+ input_style: onboarding.input_style,
1071
+ ...typeof onboarding.placeholder === "string" ? { placeholder: onboarding.placeholder } : {},
1072
+ ...Array.isArray(onboarding.fields) ? { fields: onboarding.fields } : {}
1073
+ };
1074
+ }
1075
+ }
1076
+ return Object.keys(meta).length > 0 ? meta : void 0;
1077
+ }
1078
+ function normalizeLegacyBinding(value) {
1079
+ if (typeof value === "string") {
1080
+ return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, key) => {
1081
+ const normalized = LEGACY_DEFAULT_KEYS[key];
1082
+ return `\${defaults.${normalized ?? `parameters.${key}`}}`;
1083
+ });
1084
+ }
1085
+ if (Array.isArray(value)) return value.map(normalizeLegacyBinding);
1086
+ if (typeof value !== "object" || value === null) return value;
1087
+ return Object.fromEntries(
1088
+ Object.entries(value).map(([key, nested]) => [key, normalizeLegacyBinding(nested)])
1089
+ );
1090
+ }
1091
+ function normalizeV1(data) {
1092
+ const legacyResult = LegacyFlowSchema.safeParse(data);
1093
+ if (!legacyResult.success) return failure(legacyResult.error);
1094
+ const legacy = legacyResult.data;
1095
+ const contradiction = (legacy.nodes ?? []).findIndex(
1096
+ (node) => node.data?.optional === true && node.data.approval?.mandatory === true
1097
+ );
1098
+ if (contradiction !== -1) {
1099
+ return {
1100
+ ok: false,
1101
+ errors: [
1102
+ {
1103
+ path: `nodes.${contradiction}.data`,
1104
+ message: "a node cannot be both optional and a mandatory approval gate"
1105
+ }
1106
+ ]
1107
+ };
1108
+ }
1109
+ const nodes = [];
1110
+ for (const node of legacy.nodes ?? []) {
1111
+ const data2 = node.data ?? {};
1112
+ const kind = node.type;
1113
+ const label = data2.label ?? node.label ?? data2.skill ?? node.skill ?? node.id;
1114
+ const description = node.description ?? data2.description ?? data2.message ?? label;
1115
+ if (kind === "sub-flow" && data2.flow) {
1116
+ const delegatedAsset = `flow:${data2.flow}`;
1117
+ const assets2 = [.../* @__PURE__ */ new Set([delegatedAsset, ...data2.assets ?? []])];
1118
+ const parameters2 = data2.parameters ?? {};
1119
+ const control2 = {
1120
+ optional: data2.optional,
1121
+ parallelGroup: data2.parallel_group,
1122
+ subagent: data2.subagent
1123
+ };
1124
+ nodes.push({
1125
+ id: node.id,
1126
+ label,
1127
+ description,
1128
+ phase: data2.phase,
1129
+ run: {
1130
+ kind: "sub-flow",
1131
+ flow: data2.flow,
1132
+ passContext: data2.pass_context,
1133
+ assets: assets2
1134
+ },
1135
+ contract: Object.keys(parameters2).length > 0 ? { input: normalizeLegacyBinding(parameters2) } : void 0,
1136
+ control: Object.values(control2).some((value) => value !== void 0) ? control2 : void 0
1137
+ });
1138
+ continue;
1139
+ }
1140
+ if (kind !== "skill") {
1141
+ const delegatedAsset = kind === "sub-flow" && data2.flow ? `flow:${data2.flow}` : void 0;
1142
+ const assets2 = [
1143
+ .../* @__PURE__ */ new Set([...delegatedAsset ? [delegatedAsset] : [], ...data2.assets ?? []])
1144
+ ];
1145
+ const parameters2 = data2.parameters ?? {};
1146
+ nodes.push({
1147
+ id: node.id,
1148
+ label,
1149
+ description,
1150
+ phase: data2.phase,
1151
+ run: {
1152
+ kind: "router",
1153
+ routes: [{ when: "default", target: null }],
1154
+ assets: assets2.length > 0 ? assets2 : void 0
1155
+ },
1156
+ contract: {
1157
+ requires: [{ expr: "false" }],
1158
+ input: Object.keys(parameters2).length > 0 ? normalizeLegacyBinding(parameters2) : void 0
1159
+ },
1160
+ control: { optional: true, parallelGroup: data2.parallel_group, subagent: data2.subagent }
1161
+ });
1162
+ continue;
1163
+ }
1164
+ const parameters = { ...data2.parameters ?? {} };
1165
+ const authoredInstruction = parameters.instructions;
1166
+ delete parameters.instructions;
1167
+ const instruction = typeof authoredInstruction === "string" && authoredInstruction.length > 0 ? authoredInstruction : description;
1168
+ const skill = data2.skill ?? node.skill;
1169
+ const skillAsset = skill ? `skill:${skill}${data2.version !== void 0 ? `#${data2.version}` : ""}` : void 0;
1170
+ const assets = [...skillAsset ? [skillAsset] : [], ...data2.assets ?? []];
1171
+ const control = {
1172
+ optional: data2.optional,
1173
+ parallelGroup: data2.parallel_group,
1174
+ subagent: data2.subagent
1175
+ };
1176
+ nodes.push({
1177
+ id: node.id,
1178
+ label,
1179
+ description,
1180
+ phase: data2.phase,
1181
+ run: {
1182
+ kind: "agent",
1183
+ instruction,
1184
+ assets: assets.length > 0 ? assets : void 0
1185
+ },
1186
+ contract: Object.keys(parameters).length > 0 ? { input: normalizeLegacyBinding(parameters) } : void 0,
1187
+ gate: data2.approval?.mandatory === true ? { approval: "mandatory" } : void 0,
1188
+ control: Object.values(control).some((value) => value !== void 0) ? control : void 0
1189
+ });
1190
+ }
1191
+ const nodeIds = new Set(nodes.map((node) => node.id));
1192
+ const edges = (legacy.edges ?? []).map((edge, index) => ({
1193
+ ...edge,
1194
+ id: edge.id ?? `${edge.source}-${edge.target}-${index}`,
1195
+ type: edge.type ?? "optional"
1196
+ }));
1197
+ const anchor = nodes.find((node) => node.id === legacy.entry) ?? (nodes.length > 0 ? nodes[0] : void 0);
1198
+ if (anchor && legacy.requires && legacy.requires.length > 0) {
1199
+ const run = anchor.run;
1200
+ const existingAssets = Array.isArray(run.assets) ? run.assets : [];
1201
+ run.assets = [.../* @__PURE__ */ new Set([...existingAssets, ...legacy.requires])];
1202
+ }
1203
+ const candidate = {
1204
+ schemaVersion: 2,
1205
+ id: legacy.id,
1206
+ version: legacy.version ?? "1.0.0",
1207
+ name: legacy.name,
1208
+ description: legacy.description,
1209
+ defaults: normalizeDefaults(legacy.globals),
1210
+ entry: legacy.entry !== void 0 && nodeIds.has(legacy.entry) ? legacy.entry : void 0,
1211
+ nodes,
1212
+ edges,
1213
+ meta: normalizeMeta({ ...legacy.metadata ?? {}, ...legacy.meta ?? {} })
1214
+ };
1215
+ const normalized = parseFlowDefinitionStructure({ ...candidate, edges: [] });
1216
+ if (!normalized.success) return failure(normalized.error);
1217
+ const parsed = { ...normalized.data, edges };
1218
+ return success(parsed);
1219
+ }
1220
+ function parseFlowDefinition(data) {
1221
+ if (typeof data === "object" && data !== null) {
1222
+ const recorded = successfullyParsedDefinitions.get(data);
1223
+ if (recorded !== void 0 && definitionFingerprint(data) === recorded) {
1224
+ return { ok: true, data };
1225
+ }
1226
+ }
1227
+ if (typeof data === "object" && data !== null && Object.hasOwn(data, "schemaVersion")) {
1228
+ const result = FlowDefinitionSchema.safeParse(data);
1229
+ return result.success ? success(result.data) : failure(result.error);
1230
+ }
1231
+ return normalizeV1(data);
1232
+ }
1233
+
1234
+ export { FLOW_EXPRESSION_LIMITS, FlowDefinitionSchema, FlowExpressionError, collectFlowBindingExpressions, evaluate, evaluateFlowExpression, inspectFlowExpression, normalizeV1, parseFlowDefinition, resolveFlowBindings, stableFlowJson };
1235
+ //# sourceMappingURL=chunk-OEGHKO5N.js.map
1236
+ //# sourceMappingURL=chunk-OEGHKO5N.js.map