@skaile/workspaces 3.26.0 → 3.27.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 (148) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-ISSC2HYE.js → asset-feeds-AJOUKX55.js} +4 -4
  4. package/dist/{asset-feeds-ISSC2HYE.js.map → asset-feeds-AJOUKX55.js.map} +1 -1
  5. package/dist/asset-manager/index.js +1 -1
  6. package/dist/bridge/drivers/claude-sdk.js +3 -3
  7. package/dist/bridge/drivers/codex.js +1 -1
  8. package/dist/bridge/drivers/continue.js +2 -2
  9. package/dist/bridge/drivers/echo.js +3 -3
  10. package/dist/bridge/drivers/gemini.js +3 -3
  11. package/dist/bridge/drivers/goose.js +2 -2
  12. package/dist/bridge/drivers/omp.js +1 -1
  13. package/dist/bridge/drivers/opencode.js +2 -2
  14. package/dist/bridge/drivers/qwen.js +3 -3
  15. package/dist/bridge/index.js +4 -4
  16. package/dist/{chunk-3DOLXE4Z.js → chunk-3U3ZKYR7.js} +3 -3
  17. package/dist/{chunk-3DOLXE4Z.js.map → chunk-3U3ZKYR7.js.map} +1 -1
  18. package/dist/{chunk-CP62G5PK.js → chunk-53ORCYPJ.js} +347 -16
  19. package/dist/chunk-53ORCYPJ.js.map +1 -0
  20. package/dist/{chunk-S3Z5KF6R.js → chunk-5UWAOYDN.js} +4 -4
  21. package/dist/{chunk-S3Z5KF6R.js.map → chunk-5UWAOYDN.js.map} +1 -1
  22. package/dist/{chunk-U2QALNKX.js → chunk-72DG6GSB.js} +4 -4
  23. package/dist/{chunk-U2QALNKX.js.map → chunk-72DG6GSB.js.map} +1 -1
  24. package/dist/{chunk-EKFFTOQJ.js → chunk-773WLEXL.js} +2 -2
  25. package/dist/{chunk-EKFFTOQJ.js.map → chunk-773WLEXL.js.map} +1 -1
  26. package/dist/{chunk-A565EFTW.js → chunk-7P6ASOFL.js} +3 -3
  27. package/dist/{chunk-A565EFTW.js.map → chunk-7P6ASOFL.js.map} +1 -1
  28. package/dist/{chunk-AY4OKT3U.js → chunk-AEN2UFDN.js} +2 -2
  29. package/dist/{chunk-AY4OKT3U.js.map → chunk-AEN2UFDN.js.map} +1 -1
  30. package/dist/{chunk-DGPCBJNQ.js → chunk-AQW4BWNR.js} +2 -2
  31. package/dist/{chunk-DGPCBJNQ.js.map → chunk-AQW4BWNR.js.map} +1 -1
  32. package/dist/{chunk-GLOHIJ7B.js → chunk-AU4TUVHW.js} +3 -3
  33. package/dist/{chunk-GLOHIJ7B.js.map → chunk-AU4TUVHW.js.map} +1 -1
  34. package/dist/{chunk-ALSDJ6F4.js → chunk-DY5GHUTC.js} +2 -2
  35. package/dist/{chunk-ALSDJ6F4.js.map → chunk-DY5GHUTC.js.map} +1 -1
  36. package/dist/{chunk-UOERRCR3.js → chunk-F2GEM5B3.js} +6 -6
  37. package/dist/{chunk-UOERRCR3.js.map → chunk-F2GEM5B3.js.map} +1 -1
  38. package/dist/{chunk-KFH5GCDB.js → chunk-FFE7YLYO.js} +4 -4
  39. package/dist/{chunk-KFH5GCDB.js.map → chunk-FFE7YLYO.js.map} +1 -1
  40. package/dist/{chunk-XHPWI6XF.js → chunk-FYIHH56K.js} +4 -4
  41. package/dist/{chunk-XHPWI6XF.js.map → chunk-FYIHH56K.js.map} +1 -1
  42. package/dist/{chunk-W5LPG3X6.js → chunk-JMYOJ3PA.js} +5 -3
  43. package/dist/chunk-JMYOJ3PA.js.map +1 -0
  44. package/dist/{chunk-2FDKUKDE.js → chunk-M6VQU5TS.js} +3 -3
  45. package/dist/{chunk-2FDKUKDE.js.map → chunk-M6VQU5TS.js.map} +1 -1
  46. package/dist/{chunk-NQG77HXO.js → chunk-MQASB52N.js} +3 -3
  47. package/dist/{chunk-NQG77HXO.js.map → chunk-MQASB52N.js.map} +1 -1
  48. package/dist/{chunk-NRKEZBVP.js → chunk-N27DSFA7.js} +209 -12
  49. package/dist/chunk-N27DSFA7.js.map +1 -0
  50. package/dist/{chunk-XGO6CP5S.js → chunk-O5JUZIVR.js} +4 -4
  51. package/dist/{chunk-XGO6CP5S.js.map → chunk-O5JUZIVR.js.map} +1 -1
  52. package/dist/{chunk-YCMHWNZA.js → chunk-TIOT3ZOQ.js} +3 -3
  53. package/dist/{chunk-YCMHWNZA.js.map → chunk-TIOT3ZOQ.js.map} +1 -1
  54. package/dist/{chunk-UQTPSVJV.js → chunk-UAEGKCE5.js} +6 -6
  55. package/dist/{chunk-UQTPSVJV.js.map → chunk-UAEGKCE5.js.map} +1 -1
  56. package/dist/{chunk-5SXY4B65.js → chunk-UL4LD7KD.js} +3 -3
  57. package/dist/{chunk-5SXY4B65.js.map → chunk-UL4LD7KD.js.map} +1 -1
  58. package/dist/{chunk-RPE5VYB6.js → chunk-XMULHVKX.js} +4 -4
  59. package/dist/{chunk-RPE5VYB6.js.map → chunk-XMULHVKX.js.map} +1 -1
  60. package/dist/{chunk-Q6SWQEF7.js → chunk-YLL65VXQ.js} +34 -13
  61. package/dist/chunk-YLL65VXQ.js.map +1 -0
  62. package/dist/cli/index.js +37 -37
  63. package/dist/connectors/index.js +8 -8
  64. package/dist/{ensure-sources-YH6X5XI4.js → ensure-sources-DYGQNAJM.js} +4 -4
  65. package/dist/{ensure-sources-YH6X5XI4.js.map → ensure-sources-DYGQNAJM.js.map} +1 -1
  66. package/dist/factory-assets/connectors/box.js +8 -8
  67. package/dist/factory-assets/connectors/deploy.js +8 -8
  68. package/dist/factory-assets/connectors/devserver.js +8 -8
  69. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  70. package/dist/factory-assets/connectors/flow/adapter.js +8 -8
  71. package/dist/factory-assets/connectors/flow/classifier-subprompt-runner.d.ts +40 -0
  72. package/dist/factory-assets/connectors/flow/classifier-subprompt-runner.d.ts.map +1 -0
  73. package/dist/factory-assets/connectors/flow/contract/classifier.d.ts +60 -0
  74. package/dist/factory-assets/connectors/flow/contract/classifier.d.ts.map +1 -0
  75. package/dist/factory-assets/connectors/flow/contract/expression.d.ts +22 -0
  76. package/dist/factory-assets/connectors/flow/contract/expression.d.ts.map +1 -1
  77. package/dist/factory-assets/connectors/flow/contract/index.d.ts +2 -1
  78. package/dist/factory-assets/connectors/flow/contract/index.d.ts.map +1 -1
  79. package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
  80. package/dist/factory-assets/connectors/flow/contract.js +3 -3
  81. package/dist/factory-assets/connectors/flow/engine/engine.d.ts.map +1 -1
  82. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts +9 -1
  83. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts.map +1 -1
  84. package/dist/factory-assets/connectors/flow/engine.js +2 -2
  85. package/dist/factory-assets/connectors/flow/index.d.ts +1 -0
  86. package/dist/factory-assets/connectors/flow/index.d.ts.map +1 -1
  87. package/dist/factory-assets/connectors/flow/run-flow.js +9 -9
  88. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts +7 -0
  89. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts.map +1 -1
  90. package/dist/factory-assets/connectors/flow.js +8 -8
  91. package/dist/factory-assets/connectors/git.js +8 -8
  92. package/dist/factory-assets/connectors/gmail.js +8 -8
  93. package/dist/factory-assets/connectors/googledrive.js +8 -8
  94. package/dist/factory-assets/connectors/local.js +8 -8
  95. package/dist/factory-assets/connectors/mattermost.js +8 -8
  96. package/dist/factory-assets/connectors/memory.js +8 -8
  97. package/dist/factory-assets/connectors/minio.js +8 -8
  98. package/dist/factory-assets/connectors/postgres.js +8 -8
  99. package/dist/factory-assets/connectors/s3.js +8 -8
  100. package/dist/factory-assets/connectors/sharepoint.js +8 -8
  101. package/dist/factory-assets/connectors/sqlite.js +8 -8
  102. package/dist/factory-assets/connectors/static-server.js +8 -8
  103. package/dist/factory-assets/connectors/tunnel.js +8 -8
  104. package/dist/factory-assets/connectors/webdav.js +8 -8
  105. package/dist/factory-assets/connectors/xstate-store.js +8 -8
  106. package/dist/factory-assets/connectors/xstate.js +8 -8
  107. package/dist/{flows-4DYGXE4A.js → flows-MI2VM5JZ.js} +3 -3
  108. package/dist/{flows-4DYGXE4A.js.map → flows-MI2VM5JZ.js.map} +1 -1
  109. package/dist/{helpers-EJEK6NN6.js → helpers-G6XZPN6L.js} +4 -4
  110. package/dist/{helpers-EJEK6NN6.js.map → helpers-G6XZPN6L.js.map} +1 -1
  111. package/dist/{library-publish-66FHWXAA.js → library-publish-WHGKK7G5.js} +8 -8
  112. package/dist/{library-publish-66FHWXAA.js.map → library-publish-WHGKK7G5.js.map} +1 -1
  113. package/dist/{open-library-4W2UGVJN.js → open-library-4JSLGWL6.js} +7 -7
  114. package/dist/{open-library-4W2UGVJN.js.map → open-library-4JSLGWL6.js.map} +1 -1
  115. package/dist/{project-6OECVELE.js → project-LISE6I5O.js} +5 -5
  116. package/dist/{project-6OECVELE.js.map → project-LISE6I5O.js.map} +1 -1
  117. package/dist/runner/index.js +14 -14
  118. package/dist/runner/src/serve.d.ts.map +1 -1
  119. package/dist/sdk/asset-manager.js +1 -1
  120. package/dist/sdk/bridge.js +4 -4
  121. package/dist/sdk/flow.js +2 -2
  122. package/dist/sdk/index.js +14 -14
  123. package/dist/sdk/runner.js +14 -14
  124. package/dist/sdk/session.js +2 -2
  125. package/dist/sdk/types.js +1 -1
  126. package/dist/session/index.js +2 -2
  127. package/dist/{setup-6IEVFDWB.js → setup-CIRH5BYB.js} +6 -6
  128. package/dist/{setup-6IEVFDWB.js.map → setup-CIRH5BYB.js.map} +1 -1
  129. package/dist/{source-HJQNRGTP.js → source-FKVEUOBQ.js} +8 -8
  130. package/dist/{source-HJQNRGTP.js.map → source-FKVEUOBQ.js.map} +1 -1
  131. package/dist/{source-manifest-publish-VU4BGFDU.js → source-manifest-publish-LTRXO2OQ.js} +9 -9
  132. package/dist/{source-manifest-publish-VU4BGFDU.js.map → source-manifest-publish-LTRXO2OQ.js.map} +1 -1
  133. package/dist/tui/index.js +14 -14
  134. package/dist/types/index.js +1 -1
  135. package/dist/types/src/flow.d.ts +94 -0
  136. package/dist/types/src/flow.d.ts.map +1 -1
  137. package/dist/types/src/index.d.ts +1 -1
  138. package/dist/types/src/index.d.ts.map +1 -1
  139. package/dist/types/src/version.d.ts +8 -1
  140. package/dist/types/src/version.d.ts.map +1 -1
  141. package/dist/workspace-plugin/adapters/mcp.js +3 -3
  142. package/dist/workspace-plugin/adapters/omp.js +3 -3
  143. package/dist/workspace-plugin/index.js +1 -1
  144. package/package.json +1 -1
  145. package/dist/chunk-CP62G5PK.js.map +0 -1
  146. package/dist/chunk-NRKEZBVP.js.map +0 -1
  147. package/dist/chunk-Q6SWQEF7.js.map +0 -1
  148. package/dist/chunk-W5LPG3X6.js.map +0 -1
@@ -1,5 +1,189 @@
1
1
  import * as z from 'zod';
2
2
 
3
+ // factory-assets/connectors/flow/contract/classifier.ts
4
+ var RESERVED_CLASSIFIER_FIELDS = ["confidence", "calibrated"];
5
+ var MAX_CHOICE_OPTIONS = 255;
6
+ var MIN_SCORE_LEVELS = 2;
7
+ var MAX_SCORE_LEVELS = 10;
8
+ function declaredOutputProperties(outputSchema) {
9
+ if (typeof outputSchema !== "object" || outputSchema === null) return [];
10
+ const properties = outputSchema.properties;
11
+ if (typeof properties !== "object" || properties === null) return [];
12
+ return Object.keys(properties);
13
+ }
14
+ function declaresReservedClassifierField(outputSchema) {
15
+ const declared = declaredOutputProperties(outputSchema);
16
+ return RESERVED_CLASSIFIER_FIELDS.some((name) => declared.includes(name));
17
+ }
18
+ function isRecord(value) {
19
+ return typeof value === "object" && value !== null && !Array.isArray(value);
20
+ }
21
+ function typeSet(schema) {
22
+ const type = schema.type;
23
+ if (typeof type === "string") return /* @__PURE__ */ new Set([type]);
24
+ if (Array.isArray(type) && type.every((entry) => typeof entry === "string")) {
25
+ return new Set(type);
26
+ }
27
+ return void 0;
28
+ }
29
+ function sameSet(actual, expected) {
30
+ return actual !== void 0 && actual.size === expected.length && expected.every((entry) => actual.has(entry));
31
+ }
32
+ function decisionOf(field, schema) {
33
+ if (!isRecord(schema)) return { issue: `decision property ${field} must be a schema object` };
34
+ const types = typeSet(schema);
35
+ if (sameSet(types, ["boolean"]) && schema.enum === void 0 && schema.oneOf === void 0) {
36
+ return {
37
+ decision: {
38
+ kind: "binary",
39
+ field,
40
+ ...typeof schema.description === "string" ? { description: schema.description } : {}
41
+ }
42
+ };
43
+ }
44
+ if (Array.isArray(schema.enum)) {
45
+ if (types !== void 0 && !sameSet(types, ["string"])) {
46
+ return { issue: `decision property ${field}: an enum decision must be typed string` };
47
+ }
48
+ const labels = schema.enum;
49
+ if (!labels.every((label) => typeof label === "string" && label.length > 0)) {
50
+ return { issue: `decision property ${field}: every enum label must be a non-empty string` };
51
+ }
52
+ if (new Set(labels).size !== labels.length) {
53
+ return { issue: `decision property ${field}: enum labels must be unique` };
54
+ }
55
+ if (labels.length < 2 || labels.length > MAX_CHOICE_OPTIONS) {
56
+ return {
57
+ issue: `decision property ${field}: a choice needs 2\u2013${MAX_CHOICE_OPTIONS} labels`
58
+ };
59
+ }
60
+ return {
61
+ decision: {
62
+ kind: "choice",
63
+ field,
64
+ options: Object.fromEntries(labels.map((label) => [label, null]))
65
+ }
66
+ };
67
+ }
68
+ if (Array.isArray(schema.oneOf)) {
69
+ const entries = schema.oneOf;
70
+ if (!entries.every(
71
+ (entry) => isRecord(entry) && Object.keys(entry).every((key) => key === "const" || key === "description") && "const" in entry && (entry.description === void 0 || typeof entry.description === "string")
72
+ )) {
73
+ return {
74
+ issue: `decision property ${field}: every oneOf entry must be { "const": \u2026, "description": "\u2026" }`
75
+ };
76
+ }
77
+ const consts = entries.map(
78
+ (entry) => entry.const
79
+ );
80
+ if (new Set(consts).size !== consts.length) {
81
+ return { issue: `decision property ${field}: oneOf consts must be unique` };
82
+ }
83
+ if (consts.every((value) => typeof value === "string" && value.length > 0)) {
84
+ if (types !== void 0 && !sameSet(types, ["string"])) {
85
+ return {
86
+ issue: `decision property ${field}: a string-labelled choice must be typed string`
87
+ };
88
+ }
89
+ if (consts.length < 2 || consts.length > MAX_CHOICE_OPTIONS) {
90
+ return {
91
+ issue: `decision property ${field}: a choice needs 2\u2013${MAX_CHOICE_OPTIONS} options`
92
+ };
93
+ }
94
+ return {
95
+ decision: {
96
+ kind: "choice",
97
+ field,
98
+ options: Object.fromEntries(
99
+ entries.map((entry) => [
100
+ entry.const,
101
+ entry.description ?? null
102
+ ])
103
+ )
104
+ }
105
+ };
106
+ }
107
+ if (consts.every((value) => typeof value === "number" && Number.isInteger(value))) {
108
+ if (types !== void 0 && !sameSet(types, ["integer"])) {
109
+ return { issue: `decision property ${field}: a score must be typed integer` };
110
+ }
111
+ if (consts.length < MIN_SCORE_LEVELS || consts.length > MAX_SCORE_LEVELS) {
112
+ return {
113
+ issue: `decision property ${field}: a score needs ${MIN_SCORE_LEVELS}\u2013${MAX_SCORE_LEVELS} levels`
114
+ };
115
+ }
116
+ const ordered = [...entries].sort(
117
+ (a, b) => a.const - b.const
118
+ );
119
+ return {
120
+ decision: {
121
+ kind: "score",
122
+ field,
123
+ levels: ordered.map((entry) => entry.description ?? String(entry.const)),
124
+ values: ordered.map((entry) => entry.const)
125
+ }
126
+ };
127
+ }
128
+ return {
129
+ issue: `decision property ${field}: oneOf consts must be all non-empty strings (choice) or all integers (score)`
130
+ };
131
+ }
132
+ return {
133
+ issue: `decision property ${field} must be a boolean, a string enum, or a oneOf of { const, description }`
134
+ };
135
+ }
136
+ function checkClassifierShape(outputSchema) {
137
+ if (!declaresReservedClassifierField(outputSchema)) return { classifier: false };
138
+ const schema = outputSchema;
139
+ const properties = schema.properties;
140
+ const issues = [];
141
+ if (schema.type !== "object") issues.push('the output schema must be "type": "object"');
142
+ if (schema.additionalProperties !== false) {
143
+ issues.push("the output schema must set additionalProperties: false");
144
+ }
145
+ const confidence = properties.confidence;
146
+ if (!isRecord(confidence) || !sameSet(typeSet(confidence), ["number", "null"])) {
147
+ issues.push('confidence must be typed ["number", "null"]');
148
+ }
149
+ const calibrated = properties.calibrated;
150
+ if (!isRecord(calibrated) || !sameSet(typeSet(calibrated), ["boolean"])) {
151
+ issues.push('calibrated must be typed "boolean"');
152
+ }
153
+ const decisionFields = Object.keys(properties).filter(
154
+ (name) => !RESERVED_CLASSIFIER_FIELDS.includes(name)
155
+ );
156
+ let decision;
157
+ if (decisionFields.length !== 1) {
158
+ issues.push(
159
+ `a classifier node declares exactly one decision property besides confidence and calibrated (found ${decisionFields.length})`
160
+ );
161
+ } else {
162
+ const result = decisionOf(decisionFields[0], properties[decisionFields[0]]);
163
+ if ("issue" in result) issues.push(result.issue);
164
+ else decision = result.decision;
165
+ }
166
+ const required = Array.isArray(schema.required) ? schema.required : [];
167
+ const expectedRequired = [...decisionFields.slice(0, 1), ...RESERVED_CLASSIFIER_FIELDS];
168
+ if (required.length !== expectedRequired.length || !expectedRequired.every((name) => required.includes(name))) {
169
+ issues.push(`required must be exactly [${expectedRequired.map((n) => `"${n}"`).join(", ")}]`);
170
+ }
171
+ if (issues.length > 0 || !decision) return { classifier: true, issues };
172
+ return { classifier: true, decision };
173
+ }
174
+ function classifierDecision(outputSchema) {
175
+ const check = checkClassifierShape(outputSchema);
176
+ return check.classifier && "decision" in check ? check.decision : void 0;
177
+ }
178
+ function withoutReservedClassifierFields(outputSchema) {
179
+ const properties = { ...outputSchema.properties };
180
+ for (const name of RESERVED_CLASSIFIER_FIELDS) delete properties[name];
181
+ const required = Array.isArray(outputSchema.required) ? outputSchema.required.filter(
182
+ (name) => !RESERVED_CLASSIFIER_FIELDS.includes(String(name))
183
+ ) : void 0;
184
+ return { ...outputSchema, properties, ...required ? { required } : {} };
185
+ }
186
+
3
187
  // factory-assets/connectors/flow/contract/expression.ts
4
188
  var FLOW_EXPRESSION_LIMITS = Object.freeze({
5
189
  maxLength: 4096,
@@ -235,20 +419,32 @@ function assertBooleanOperand(value, position) {
235
419
  if (!isBooleanOperand(value)) throw expressionError("requires boolean operands", position);
236
420
  }
237
421
  var Parser = class {
238
- constructor(tokens, context, onPath, onBooleanPath, onEvaluatedPath) {
422
+ constructor(tokens, context, onPath, onBooleanPath, onEvaluatedPath, onComparison) {
239
423
  this.tokens = tokens;
240
424
  this.context = context;
241
425
  this.onPath = onPath;
242
426
  this.onBooleanPath = onBooleanPath;
243
427
  this.onEvaluatedPath = onEvaluatedPath;
428
+ this.onComparison = onComparison;
244
429
  }
245
430
  tokens;
246
431
  context;
247
432
  onPath;
248
433
  onBooleanPath;
249
434
  onEvaluatedPath;
435
+ onComparison;
250
436
  index = 0;
251
437
  nesting = 0;
438
+ /** Literal `path == true` conjuncts already parsed, one frame per enclosing `&&` chain. */
439
+ guardFrames = [];
440
+ /**
441
+ * Guards the operand {@link parseComparison} just parsed establishes when true:
442
+ * its own path for a literal `path == true`, or every guard of a parenthesized
443
+ * `&&` group, which is true only when all its conjuncts are.
444
+ */
445
+ lastGuards = [];
446
+ /** Guards of the `&&` / `||` chain that just finished; empty once a `||` joined it. */
447
+ lastChainGuards = [];
252
448
  parse(evaluate2 = true) {
253
449
  const value = this.parseOr(evaluate2);
254
450
  const trailing = this.peek();
@@ -272,7 +468,9 @@ var Parser = class {
272
468
  }
273
469
  parseOr(evaluate2) {
274
470
  let value = this.parseAnd(evaluate2);
471
+ let disjunction = false;
275
472
  while (this.peek().value === "||") {
473
+ disjunction = true;
276
474
  const operator = this.take();
277
475
  assertBooleanOperand(value, operator.position);
278
476
  if (isStaticPath(value)) this.onBooleanPath?.(value.path);
@@ -282,31 +480,51 @@ var Parser = class {
282
480
  if (isStaticPath(right)) this.onBooleanPath?.(right.path);
283
481
  value = evaluate2 ? value === true || right === true : STATIC_BOOLEAN;
284
482
  }
483
+ if (disjunction) this.lastChainGuards = [];
285
484
  return value;
286
485
  }
287
486
  parseAnd(evaluate2) {
288
- let value = this.parseComparison(evaluate2);
289
- while (this.peek().value === "&&") {
290
- const operator = this.take();
291
- assertBooleanOperand(value, operator.position);
292
- if (isStaticPath(value)) this.onBooleanPath?.(value.path);
293
- const evaluateRight = evaluate2 && value === true;
294
- const right = this.parseComparison(evaluateRight);
295
- assertBooleanOperand(right, operator.position);
296
- if (isStaticPath(right)) this.onBooleanPath?.(right.path);
297
- value = evaluate2 ? value === true && right === true : STATIC_BOOLEAN;
487
+ const guards = [];
488
+ this.guardFrames.push(guards);
489
+ try {
490
+ let value = this.parseComparison(evaluate2);
491
+ guards.push(...this.lastGuards);
492
+ while (this.peek().value === "&&") {
493
+ const operator = this.take();
494
+ assertBooleanOperand(value, operator.position);
495
+ if (isStaticPath(value)) this.onBooleanPath?.(value.path);
496
+ const evaluateRight = evaluate2 && value === true;
497
+ const right = this.parseComparison(evaluateRight);
498
+ guards.push(...this.lastGuards);
499
+ assertBooleanOperand(right, operator.position);
500
+ if (isStaticPath(right)) this.onBooleanPath?.(right.path);
501
+ value = evaluate2 ? value === true && right === true : STATIC_BOOLEAN;
502
+ }
503
+ this.lastChainGuards = [...guards];
504
+ return value;
505
+ } finally {
506
+ this.guardFrames.pop();
298
507
  }
299
- return value;
300
508
  }
301
509
  parseComparison(evaluate2) {
510
+ const group = this.peek().value === "(";
302
511
  const left = this.parseUnary(evaluate2);
303
512
  const token = this.peek();
304
513
  if (token.kind !== "operator" || !["==", "!=", "<", "<=", ">", ">=", "in"].includes(String(token.value))) {
514
+ this.lastGuards = group ? this.lastChainGuards : [];
305
515
  return left;
306
516
  }
307
517
  this.take();
308
518
  const right = this.parseUnary(evaluate2);
309
- return evaluate2 ? compare(String(token.value), left, right, token.position) : STATIC_BOOLEAN;
519
+ const operator = String(token.value);
520
+ this.onComparison?.({
521
+ operator,
522
+ left: isStaticPath(left) ? { path: left.path } : { literal: left },
523
+ right: isStaticPath(right) ? { path: right.path } : { literal: right },
524
+ guards: this.guardFrames.flat()
525
+ });
526
+ this.lastGuards = operator === "==" && isStaticPath(left) && right === true ? [left.path] : [];
527
+ return evaluate2 ? compare(operator, left, right, token.position) : STATIC_BOOLEAN;
310
528
  }
311
529
  parseUnary(evaluate2) {
312
530
  const operator = this.accept("!");
@@ -360,6 +578,21 @@ var Parser = class {
360
578
  }
361
579
  }
362
580
  };
581
+ function inspectFlowExpressionComparisons(expression) {
582
+ const tokens = tokenize(expression);
583
+ if (expression.trim() === "default") return [];
584
+ const comparisons = [];
585
+ const context = { flow: { input: {} }, nodes: {} };
586
+ new Parser(
587
+ tokens,
588
+ context,
589
+ void 0,
590
+ void 0,
591
+ void 0,
592
+ (comparison) => comparisons.push(comparison)
593
+ ).parse(false);
594
+ return comparisons;
595
+ }
363
596
  function inspectFlowExpression(expression, requireBoolean = true) {
364
597
  const tokens = tokenize(expression);
365
598
  if (expression.trim() === "default") return [];
@@ -949,6 +1182,7 @@ var FlowDefinitionSchema = FlowDefinitionObjectSchema.superRefine((flow, context
949
1182
  }
950
1183
  }
951
1184
  }
1185
+ validateClassifierRules(flow, context);
952
1186
  const state = /* @__PURE__ */ new Map();
953
1187
  for (const nodeId of nodeIds) {
954
1188
  if (state.has(nodeId)) continue;
@@ -973,6 +1207,103 @@ var FlowDefinitionSchema = FlowDefinitionObjectSchema.superRefine((flow, context
973
1207
  }
974
1208
  }
975
1209
  });
1210
+ var ORDERING_OPERATORS = /* @__PURE__ */ new Set(["<", "<=", ">", ">="]);
1211
+ function validateClassifierRules(flow, context) {
1212
+ const classifierIds = /* @__PURE__ */ new Set();
1213
+ for (const [nodeIndex, node] of flow.nodes.entries()) {
1214
+ const outputSchema = node.contract?.output?.fields;
1215
+ const path = ["nodes", nodeIndex, "contract", "output", "fields"];
1216
+ if (node.run.kind === "subprompt") {
1217
+ const check = checkClassifierShape(outputSchema);
1218
+ if (!check.classifier) continue;
1219
+ classifierIds.add(node.id);
1220
+ if ("issues" in check) {
1221
+ context.addIssue({
1222
+ code: "custom",
1223
+ path,
1224
+ message: `subprompt ${node.id} declares a reserved classifier field but is not classifier-shaped: ${check.issues.join("; ")}`
1225
+ });
1226
+ }
1227
+ continue;
1228
+ }
1229
+ if ((node.run.kind === "agent" || node.run.kind === "sub-flow") && declaresReservedClassifierField(outputSchema)) {
1230
+ const names = RESERVED_CLASSIFIER_FIELDS.filter(
1231
+ (name) => declaredOutputProperties(outputSchema).includes(name)
1232
+ );
1233
+ context.addIssue({
1234
+ code: "custom",
1235
+ path,
1236
+ message: `${names.join(" and ")} ${names.length > 1 ? "are" : "is"} reserved for classifier-shaped subprompt nodes; ${node.run.kind} node ${node.id} cannot declare ${names.length > 1 ? "them" : "it"}`
1237
+ });
1238
+ }
1239
+ }
1240
+ if (classifierIds.size === 0) return;
1241
+ const reservedRead = (path) => {
1242
+ const segments = path.split(".");
1243
+ if (segments.length !== 5 || segments[0] !== "nodes" || segments[2] !== "output" || segments[3] !== "fields" || !classifierIds.has(segments[1]) || !RESERVED_CLASSIFIER_FIELDS.includes(segments[4])) {
1244
+ return void 0;
1245
+ }
1246
+ return { producer: segments[1], field: segments[4] };
1247
+ };
1248
+ const readsReserved = (expression) => {
1249
+ try {
1250
+ return inspectFlowExpression(expression, false).some(({ path }) => reservedRead(path));
1251
+ } catch {
1252
+ return false;
1253
+ }
1254
+ };
1255
+ const checkGuards = (expression, path) => {
1256
+ let comparisons;
1257
+ try {
1258
+ comparisons = inspectFlowExpressionComparisons(expression);
1259
+ } catch {
1260
+ return;
1261
+ }
1262
+ for (const comparison of comparisons) {
1263
+ if (!ORDERING_OPERATORS.has(comparison.operator)) continue;
1264
+ for (const operand of [comparison.left, comparison.right]) {
1265
+ if (!("path" in operand)) continue;
1266
+ const read = reservedRead(operand.path);
1267
+ if (read?.field !== "confidence") continue;
1268
+ const guard = `nodes.${read.producer}.output.fields.calibrated`;
1269
+ if (comparison.guards.includes(guard)) continue;
1270
+ context.addIssue({
1271
+ code: "custom",
1272
+ path,
1273
+ message: `${operand.path} is null when the classifier is uncalibrated, so an ordering comparison on it must be guarded: put the literal conjunct \`${guard} == true\` earlier in the same && chain, optionally parenthesized (\`true == \u2026\`, \`!= false\` and a guard inside \`||\` are not accepted)`
1274
+ });
1275
+ }
1276
+ }
1277
+ };
1278
+ for (const [nodeIndex, node] of flow.nodes.entries()) {
1279
+ for (const [requireIndex, requirement] of node.contract?.requires?.entries() ?? []) {
1280
+ if (!readsReserved(requirement.expr)) continue;
1281
+ context.addIssue({
1282
+ code: "custom",
1283
+ path: ["nodes", nodeIndex, "contract", "requires", requireIndex, "expr"],
1284
+ message: "a contract.requires guard cannot read a classifier's confidence or calibrated; decide on a classifier's answer at a router, which has a default route"
1285
+ });
1286
+ }
1287
+ for (const [bindingName2, binding] of Object.entries(node.contract?.input ?? {})) {
1288
+ for (const expression of collectFlowBindingExpressions(binding)) {
1289
+ checkGuards(expression, ["nodes", nodeIndex, "contract", "input", bindingName2]);
1290
+ }
1291
+ }
1292
+ if (node.run.kind !== "router") continue;
1293
+ const routes = node.run.routes;
1294
+ for (const [routeIndex, route] of routes.entries()) {
1295
+ checkGuards(route.when, ["nodes", nodeIndex, "run", "routes", routeIndex, "when"]);
1296
+ }
1297
+ const readsAny = routes.some((route) => readsReserved(route.when));
1298
+ if (readsAny && routes.at(-1)?.when.trim() !== "default") {
1299
+ context.addIssue({
1300
+ code: "custom",
1301
+ path: ["nodes", nodeIndex, "run", "routes"],
1302
+ message: `router ${node.id} reads a classifier's confidence or calibrated, so its last route must be the unconditional "default": on the uncalibrated fallback every guarded route is false, and without a default the router would settle nowhere`
1303
+ });
1304
+ }
1305
+ }
1306
+ }
976
1307
  var successfullyParsedDefinitions = /* @__PURE__ */ new WeakMap();
977
1308
  function valueFingerprint(value, ancestors) {
978
1309
  if (value === null) return "null";
@@ -1279,6 +1610,6 @@ function parseFlowDefinition(data) {
1279
1610
  return normalizeV1(data);
1280
1611
  }
1281
1612
 
1282
- export { FLOW_EXPRESSION_LIMITS, FlowDefinitionSchema, FlowExpressionError, InputSchema, collectFlowBindingExpressions, evaluate, evaluateFlowExpression, inspectFlowExpression, normalizeV1, parseFlowDefinition, resolveFlowBindings, stableFlowJson };
1283
- //# sourceMappingURL=chunk-CP62G5PK.js.map
1284
- //# sourceMappingURL=chunk-CP62G5PK.js.map
1613
+ export { FLOW_EXPRESSION_LIMITS, FlowDefinitionSchema, FlowExpressionError, InputSchema, RESERVED_CLASSIFIER_FIELDS, checkClassifierShape, classifierDecision, collectFlowBindingExpressions, declaresReservedClassifierField, evaluate, evaluateFlowExpression, inspectFlowExpression, inspectFlowExpressionComparisons, normalizeV1, parseFlowDefinition, resolveFlowBindings, stableFlowJson, withoutReservedClassifierFields };
1614
+ //# sourceMappingURL=chunk-53ORCYPJ.js.map
1615
+ //# sourceMappingURL=chunk-53ORCYPJ.js.map