@fluidgrids/workflows 2026.1028.2 → 2026.1030.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +181 -11
  2. package/dist/{activation-BBh1p82z.d.cts → activation-DqUfpHzk.d.cts} +1 -1
  3. package/dist/{activation-DnhG7SmF.d.ts → activation-xpx1oWuo.d.ts} +1 -1
  4. package/dist/{chunk-VRHHBPT6.js → chunk-2D3MYIIF.js} +1212 -128
  5. package/dist/chunk-3U2NU7YC.cjs +124 -0
  6. package/dist/{chunk-NEIUQASE.cjs → chunk-4QKB4ARC.cjs} +3 -3
  7. package/dist/{chunk-GBQ33SIZ.cjs → chunk-54FLQNUM.cjs} +12 -1
  8. package/dist/chunk-5HIVIV53.js +330 -0
  9. package/dist/chunk-5MFVJM76.js +1222 -0
  10. package/dist/{chunk-JD2VQIDZ.cjs → chunk-672KMMBK.cjs} +2 -2
  11. package/dist/{chunk-C5OLWZ42.js → chunk-6A2FGSUS.js} +22 -14
  12. package/dist/{chunk-XKJA7KX3.js → chunk-6OLN6BMB.js} +52 -3
  13. package/dist/{chunk-6FSHT5IL.js → chunk-7EZIANC7.js} +1 -1
  14. package/dist/{chunk-2J6TF7YI.cjs → chunk-A5SXCA62.cjs} +10 -3
  15. package/dist/{chunk-BO6OVILK.js → chunk-AC6ZEXVR.js} +10 -4
  16. package/dist/{chunk-ABFZWYHT.js → chunk-AE5Q6ZAJ.js} +315 -50
  17. package/dist/chunk-C4F5KJTI.js +293 -0
  18. package/dist/{chunk-IISBRUWJ.js → chunk-G5H32GIG.js} +1 -1
  19. package/dist/chunk-GEQDGUGB.cjs +2719 -0
  20. package/dist/{chunk-XHXIDVEC.js → chunk-HCM7ZC7Q.js} +1 -1
  21. package/dist/chunk-HMZUGSMU.cjs +1554 -0
  22. package/dist/{chunk-SAOBPYYJ.cjs → chunk-IQPXHQQQ.cjs} +8 -4
  23. package/dist/{chunk-P6TA5EZT.cjs → chunk-ISOIA7NV.cjs} +335 -58
  24. package/dist/chunk-JSC75O5C.cjs +167 -0
  25. package/dist/chunk-M272AHEX.js +25 -0
  26. package/dist/{chunk-BD7ZPG53.js → chunk-NWQ5WRLE.js} +10 -2
  27. package/dist/chunk-ODZ2IAR2.cjs +1247 -0
  28. package/dist/chunk-Q4MWQNJK.cjs +28 -0
  29. package/dist/{chunk-HWJZVOG7.js → chunk-SR7TR5KX.js} +6 -2
  30. package/dist/{chunk-FEW3JBYA.cjs → chunk-TCTE7DX5.cjs} +3 -3
  31. package/dist/{chunk-623FVQSN.cjs → chunk-TYF56RGB.cjs} +123 -0
  32. package/dist/chunk-VA4OFR72.cjs +324 -0
  33. package/dist/chunk-VU5S5A7V.js +150 -0
  34. package/dist/chunk-YEHR4NNE.js +1522 -0
  35. package/dist/{chunk-FMSW2HDF.cjs → chunk-ZCGKGDCL.cjs} +23 -15
  36. package/dist/codegen/index.d.cts +2 -2
  37. package/dist/codegen/index.d.ts +2 -2
  38. package/dist/collect-6NIEufHd.d.ts +103 -0
  39. package/dist/collect-CcTCKqx6.d.cts +103 -0
  40. package/dist/{file-BOoHZgoQ.d.cts → file-BxYpwjRQ.d.cts} +1007 -21
  41. package/dist/{file-yuPCFU5b.d.ts → file-CFdPQJI9.d.ts} +1007 -21
  42. package/dist/history/index.cjs +375 -86
  43. package/dist/history/index.d.cts +590 -12
  44. package/dist/history/index.d.ts +590 -12
  45. package/dist/history/index.js +50 -4
  46. package/dist/index.cjs +156 -50
  47. package/dist/index.d.cts +38 -58
  48. package/dist/index.d.ts +38 -58
  49. package/dist/index.js +6 -4
  50. package/dist/interceptors-CNcr2dlk.d.ts +159 -0
  51. package/dist/interceptors-CqkNZVfI.d.cts +159 -0
  52. package/dist/ir/index.cjs +362 -38
  53. package/dist/ir/index.d.cts +282 -7
  54. package/dist/ir/index.d.ts +282 -7
  55. package/dist/ir/index.js +329 -23
  56. package/dist/{lower-BzmUz0sq.d.cts → lower-BtRfIW2A.d.cts} +56 -8
  57. package/dist/{lower-_-iT4HYs.d.ts → lower-CpsMFOFX.d.ts} +56 -8
  58. package/dist/{manifest-C8N6HDYl.d.ts → manifest-D-I_twys.d.ts} +1 -1
  59. package/dist/{manifest-0OLw0i7k.d.cts → manifest-DahBQVM8.d.cts} +1 -1
  60. package/dist/node-evaluator-DGQDPSPI.cjs +24 -0
  61. package/dist/node-evaluator-LEEVD7H7.js +14 -0
  62. package/dist/payload-fields-BVRQn2yH.d.cts +122 -0
  63. package/dist/payload-fields-oOBWxDiG.d.ts +122 -0
  64. package/dist/quickjs/index.cjs +28 -27
  65. package/dist/quickjs/index.d.cts +6 -6
  66. package/dist/quickjs/index.d.ts +6 -6
  67. package/dist/quickjs/index.js +10 -9
  68. package/dist/roundtrip/index.cjs +259 -51
  69. package/dist/roundtrip/index.d.cts +100 -9
  70. package/dist/roundtrip/index.d.ts +100 -9
  71. package/dist/roundtrip/index.js +177 -11
  72. package/dist/runtime/index.cjs +21 -20
  73. package/dist/runtime/index.d.cts +184 -15
  74. package/dist/runtime/index.d.ts +184 -15
  75. package/dist/runtime/index.js +8 -7
  76. package/dist/testing/index.cjs +1122 -115
  77. package/dist/testing/index.d.cts +294 -13
  78. package/dist/testing/index.d.ts +294 -13
  79. package/dist/testing/index.js +1086 -84
  80. package/dist/{types-DV-HX_Gt.d.ts → types-Bv2i4cBX.d.cts} +244 -33
  81. package/dist/{types-CpBBjaGX.d.cts → types-DGx-b9eq.d.ts} +244 -33
  82. package/dist/{types-BGoPzgcl.d.ts → types-V7jEEUaL.d.cts} +20 -1
  83. package/dist/{types-BGoPzgcl.d.cts → types-V7jEEUaL.d.ts} +20 -1
  84. package/dist/{workflow-Bpr3vnA_.d.ts → workflow-B18OeF7g.d.ts} +2 -2
  85. package/dist/workflow-BGnv8SS6.d.ts +803 -0
  86. package/dist/{workflow-FXUkpIBc.d.cts → workflow-BJPFv3cp.d.cts} +2 -2
  87. package/dist/workflow-DS32Gtws.d.cts +803 -0
  88. package/fixtures/histories/activity-options-updated.history.json +159 -0
  89. package/fixtures/histories/activity-paused-unpaused.history.json +160 -0
  90. package/fixtures/histories/auto-upgrade-patched.history.json +276 -0
  91. package/fixtures/histories/benign-failure.history.json +146 -0
  92. package/fixtures/histories/cancel-activity-try-cancel.history.json +150 -0
  93. package/fixtures/histories/child-cancel-wait-requested.history.json +217 -0
  94. package/fixtures/histories/child-options-roundtrip.history.json +192 -0
  95. package/fixtures/histories/codec-opaque.history.json +229 -0
  96. package/fixtures/histories/continue-as-new-last-result.history.json +86 -0
  97. package/fixtures/histories/continue-as-new-options.history.json +99 -0
  98. package/fixtures/histories/continue-as-new-r1-long-task-queue.history.json +78 -0
  99. package/fixtures/histories/continue-as-new-r1-retry-options.history.json +83 -0
  100. package/fixtures/histories/dynamic-workflow.history.json +150 -0
  101. package/fixtures/histories/execution-timeout-chain.history.json +98 -0
  102. package/fixtures/histories/external-cancel-resolved.history.json +123 -0
  103. package/fixtures/histories/external-cancel-unknown-target.history.json +127 -0
  104. package/fixtures/histories/failure-error-types-fails-run.history.json +144 -0
  105. package/fixtures/histories/handler-drain-warn.history.json +222 -0
  106. package/fixtures/histories/heartbeat-details-on-retry.history.json +145 -0
  107. package/fixtures/histories/interceptor-headers.history.json +339 -0
  108. package/fixtures/histories/local-activity-abandoned-at-completion.history.json +73 -0
  109. package/fixtures/histories/local-activity-cancelled-in-scope.history.json +118 -0
  110. package/fixtures/histories/local-activity-completed.history.json +157 -0
  111. package/fixtures/histories/local-activity-failed.history.json +93 -0
  112. package/fixtures/histories/local-activity-retry-in-task.history.json +88 -0
  113. package/fixtures/histories/query-custom.history.json +213 -0
  114. package/fixtures/histories/query-default-handler.history.json +120 -0
  115. package/fixtures/histories/reset-forked-reapplied-signals.history.json +239 -0
  116. package/fixtures/histories/reset-reapplied-update-admitted.history.json +228 -0
  117. package/fixtures/histories/run-retry-last-failure.history.json +90 -0
  118. package/fixtures/histories/run-timeout.history.json +159 -0
  119. package/fixtures/histories/schedule-to-start-timeout.history.json +132 -0
  120. package/fixtures/histories/search-attributes-upserted.history.json +177 -0
  121. package/fixtures/histories/start-delay-signal-ends-delay.history.json +155 -0
  122. package/fixtures/histories/typeerror-task-retry-100.history.json +137 -0
  123. package/fixtures/histories/update-accepted-completed.history.json +45 -30
  124. package/fixtures/histories/update-default-handler.history.json +246 -0
  125. package/fixtures/histories/update-handler-awaits-activity.history.json +196 -0
  126. package/fixtures/histories/update-not-handled.history.json +138 -0
  127. package/fixtures/histories/update-rejected-no-event.history.json +190 -0
  128. package/fixtures/histories/update-with-start-admitted.history.json +150 -0
  129. package/fixtures/histories/user-activity-cancel.history.json +149 -0
  130. package/fixtures/histories/user-activity-retry.history.json +143 -0
  131. package/fixtures/histories/user-activity.history.json +149 -0
  132. package/package.json +1 -1
  133. package/schema/bridge-v2.schema.json +1062 -0
  134. package/schema/history-file.schema.json +538 -83
  135. package/schema/ir-v2.schema.json +290 -0
  136. package/schema/payload-fields.json +162 -0
  137. package/schema/run-event.schema.json +503 -82
  138. package/schema/workflow-command.schema.json +372 -69
  139. package/schema/workflow-task.schema.json +924 -171
  140. package/dist/assemble-BLqQ8lSu.d.cts +0 -39
  141. package/dist/assemble-DWgaXHd-.d.ts +0 -39
  142. package/dist/chunk-DHTLALBL.cjs +0 -80
  143. package/dist/chunk-DJYMDLV5.js +0 -227
  144. package/dist/chunk-I5LR3D2K.js +0 -869
  145. package/dist/chunk-M4BBAERY.cjs +0 -1635
  146. package/dist/chunk-N23SKIG4.js +0 -73
  147. package/dist/chunk-PZCVF76Q.cjs +0 -868
  148. package/dist/chunk-QQ6ULXHI.cjs +0 -885
  149. package/dist/chunk-UK3WM7YZ.cjs +0 -75
  150. package/dist/chunk-VOKMAAJP.js +0 -848
  151. package/dist/node-evaluator-4MSDKWOG.cjs +0 -22
  152. package/dist/node-evaluator-SX4LEYQC.js +0 -12
  153. package/dist/workflow-C2a05WUJ.d.ts +0 -444
  154. package/dist/workflow-J-yYixny.d.cts +0 -444
package/dist/ir/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkNEIUQASE_cjs = require('../chunk-NEIUQASE.cjs');
3
+ var chunk4QKB4ARC_cjs = require('../chunk-4QKB4ARC.cjs');
4
4
  var chunkCPDK3K5N_cjs = require('../chunk-CPDK3K5N.cjs');
5
- var chunkGBQ33SIZ_cjs = require('../chunk-GBQ33SIZ.cjs');
5
+ var chunk54FLQNUM_cjs = require('../chunk-54FLQNUM.cjs');
6
6
  var chunkG4UEPUGO_cjs = require('../chunk-G4UEPUGO.cjs');
7
7
  var chunkQKZL3ONM_cjs = require('../chunk-QKZL3ONM.cjs');
8
8
  var chunkTBDXTV22_cjs = require('../chunk-TBDXTV22.cjs');
@@ -12,8 +12,41 @@ require('../chunk-Z2Y65YOY.cjs');
12
12
  var _2020_js = require('ajv/dist/2020.js');
13
13
  var cronParser = require('cron-parser');
14
14
 
15
+ // src/ir/schedule-fields.ts
16
+ var SCHEDULE_OVERLAP_POLICIES = [
17
+ "SKIP",
18
+ "BUFFER_ONE",
19
+ "BUFFER_ALL",
20
+ "CANCEL_OTHER",
21
+ "TERMINATE_OTHER",
22
+ "ALLOW_ALL"
23
+ ];
24
+ var DEFAULT_NEW_SCHEDULE_OVERLAP_POLICY = "SKIP";
25
+ var DEFAULT_SCHEDULE_CATCHUP_WINDOW_SECONDS = 3600;
26
+ var SCHEDULE_POLICY_FIELDS = [
27
+ "overlapPolicy",
28
+ "catchupWindow",
29
+ "pauseOnFailure",
30
+ "limitedActions",
31
+ "scheduleContext",
32
+ "scheduleSearchAttributes"
33
+ ];
34
+ var SCHEDULE_SPEC_FIELDS = [
35
+ "excludeCalendars",
36
+ "startAt",
37
+ "endAt",
38
+ "timezone",
39
+ "jitter"
40
+ ];
41
+
15
42
  // src/ir/schema.ts
16
43
  var JSON_SCHEMA_OBJECT = { type: "object" };
44
+ var DURATION = {
45
+ oneOf: [
46
+ { type: "number", minimum: 0 },
47
+ { type: "string", minLength: 1 }
48
+ ]
49
+ };
17
50
  var IR_V2_SCHEMA_ID = "https://docs.fluidgrids.ai/schemas/workflow-ir-v2.schema.json";
18
51
  var IR_V2_SCHEMA = {
19
52
  $schema: "https://json-schema.org/draft/2020-12/schema",
@@ -181,6 +214,118 @@ var IR_V2_SCHEMA = {
181
214
  }
182
215
  }
183
216
  }
217
+ },
218
+ {
219
+ if: { properties: { type: { const: "internal:signal-run" } }, required: ["type"] },
220
+ then: {
221
+ description: "Phase C (fluidgrids.run-control): signal another run of the workspace (05 \xA74). A retried node delivers once (dedupe key signal-node:<nodeStateId>:<attempt>).",
222
+ required: ["args"],
223
+ properties: {
224
+ args: {
225
+ required: ["state"],
226
+ properties: {
227
+ state: {
228
+ type: "object",
229
+ required: ["signalName", "target"],
230
+ properties: {
231
+ signalName: { type: "string", minLength: 1 },
232
+ target: {
233
+ description: "The run to signal: { runId }, { workflowKey, workflowId, firstRunId? } (the open run of that workflow id) or { parent: true }. Values may be expressions.",
234
+ oneOf: [
235
+ {
236
+ type: "object",
237
+ required: ["runId"],
238
+ properties: { runId: { type: "string", minLength: 1 } },
239
+ additionalProperties: false
240
+ },
241
+ {
242
+ type: "object",
243
+ required: ["workflowKey", "workflowId"],
244
+ properties: {
245
+ workflowKey: { type: "string", minLength: 1 },
246
+ workflowId: { type: "string", minLength: 1 },
247
+ firstRunId: { type: "string", minLength: 1 }
248
+ },
249
+ additionalProperties: false
250
+ },
251
+ {
252
+ type: "object",
253
+ required: ["parent"],
254
+ properties: { parent: { const: true } },
255
+ additionalProperties: false
256
+ }
257
+ ]
258
+ },
259
+ payload: {},
260
+ failOnUndelivered: {
261
+ type: "boolean",
262
+ description: "Default true: an undelivered signal fails the node."
263
+ }
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ },
271
+ {
272
+ if: {
273
+ properties: { type: { const: "internal:set-search-attributes" } },
274
+ required: ["type"]
275
+ },
276
+ then: {
277
+ description: "Phase C (fluidgrids.search-attributes): upsert the run search attributes (11 \xA72.8); a null value removes one. Values may be expressions; the service validates them against the workspace definitions.",
278
+ required: ["args"],
279
+ properties: {
280
+ args: {
281
+ required: ["state"],
282
+ properties: {
283
+ state: {
284
+ type: "object",
285
+ required: ["attributes"],
286
+ properties: {
287
+ attributes: { type: "object", minProperties: 1 }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ }
293
+ }
294
+ },
295
+ {
296
+ if: { properties: { type: { const: "internal:schedule" } }, required: ["type"] },
297
+ then: {
298
+ properties: {
299
+ args: {
300
+ properties: {
301
+ state: {
302
+ description: "Phase C schedule policies (11 \xA72.16, \xA72.33; fluidgrids.schedule-policies). Every field is optional; a trigger without overlapPolicy keeps the ALLOW_ALL behaviour of earlier versions.",
303
+ properties: {
304
+ overlapPolicy: { enum: [...SCHEDULE_OVERLAP_POLICIES] },
305
+ catchupWindow: DURATION,
306
+ pauseOnFailure: { type: "boolean" },
307
+ limitedActions: { type: "integer", minimum: 1 },
308
+ scheduleContext: { type: "object" },
309
+ scheduleSearchAttributes: { type: "object" },
310
+ spec: {
311
+ description: "One of cron, calendar or interval, plus excludeCalendars (calendar entries whose matches are skipped), startAt, endAt (ISO 8601), timezone and jitter.",
312
+ properties: {
313
+ cron: { type: "string" },
314
+ calendar: { type: "array", items: { type: "object" } },
315
+ interval: { type: "array", items: { type: "object" } },
316
+ excludeCalendars: { type: "array", items: { type: "object" } },
317
+ startAt: { type: "string", minLength: 1 },
318
+ endAt: { type: "string", minLength: 1 },
319
+ timezone: { type: "string" },
320
+ jitter: DURATION
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
184
329
  }
185
330
  ]
186
331
  },
@@ -212,7 +357,18 @@ var IR_V2_SCHEMA = {
212
357
  type: ["number", "string"],
213
358
  description: "Seconds or a duration string."
214
359
  },
215
- versioningBehavior: { enum: ["PINNED", "AUTO_UPGRADE"] }
360
+ versioningBehavior: { enum: ["PINNED", "AUTO_UPGRADE"] },
361
+ retry: {
362
+ type: "object",
363
+ description: "Run-level retry of DURABLE_FN runs (11 \xA72.17); delays are seconds or duration strings. Graph runs keep their own meaning of retry.",
364
+ properties: {
365
+ maxAttempts: { type: "integer", minimum: 1 },
366
+ initialDelay: { type: ["number", "string"] },
367
+ backoffMultiplier: { type: "number", minimum: 1 },
368
+ maxDelay: { type: ["number", "string"] },
369
+ nonRetryableErrorTypes: { type: "array", items: { type: "string" } }
370
+ }
371
+ }
216
372
  }
217
373
  },
218
374
  interface: {
@@ -285,7 +441,11 @@ var IR_V2_SCHEMA = {
285
441
  type: "object",
286
442
  properties: {
287
443
  interface: { $ref: "#/$defs/interface" },
288
- taskQueue: { type: "string" }
444
+ taskQueue: { type: "string" },
445
+ config: {
446
+ $ref: "#/$defs/config",
447
+ description: "R2: the run-level settings of this function's workflow() declaration (retry, timeout, executionTimeout, workflowTaskTimeout, versioningBehavior). The service resolves run options per workflowFn from this table, never from the definition-level config, so a same-bundle child started on its parent's definition gets its own settings. Absent: the function declares none."
448
+ }
289
449
  }
290
450
  }
291
451
  },
@@ -302,7 +462,13 @@ var IR_V2_SCHEMA = {
302
462
  }
303
463
  }
304
464
  },
305
- determinism: { enum: ["isolate", "worker"] }
465
+ determinism: { enum: ["isolate", "worker"] },
466
+ features: {
467
+ type: "array",
468
+ items: { type: "string", minLength: 1 },
469
+ uniqueItems: true,
470
+ description: "Runtime features the bundle uses (C-FEATURES): localActivity, externalCancel, childOptions, canOptions, autoUpgrade, runRetry, timeouts (SDK R2); userActivity, updates, queries, searchAttributes, dynamic and interceptors (Phase C, C-R1). A bundle without the field was built before R2 and uses none."
471
+ }
306
472
  }
307
473
  },
308
474
  authoring: {
@@ -346,7 +512,7 @@ function executorNodeView(node) {
346
512
  const args = chunkSAENRNBJ_cjs.isRecord(record["args"]) ? record["args"] : void 0;
347
513
  const dataArgs = chunkSAENRNBJ_cjs.isRecord(data?.["args"]) ? data["args"] : void 0;
348
514
  const type = typeof record["type"] === "string" ? record["type"] : "";
349
- const merged = chunkGBQ33SIZ_cjs.usesMergedParameters(type);
515
+ const merged = chunk54FLQNUM_cjs.usesMergedParameters(type);
350
516
  let parameters;
351
517
  if (merged) {
352
518
  const config = chunkSAENRNBJ_cjs.isRecord(record["config"]) ? record["config"] : {};
@@ -446,23 +612,71 @@ function cronTimes(expression, now, tz, accept) {
446
612
  for (let i = 0; i < MAX_ITERATIONS && out.length < FIRE_TIMES; i++) {
447
613
  if (!interval.hasNext()) break;
448
614
  const date = interval.next().toDate();
449
- if (accept(date)) out.push(date.toISOString());
615
+ const verdict = accept(date);
616
+ if (verdict === "stop") break;
617
+ if (verdict === "keep") out.push(date.toISOString());
450
618
  }
451
619
  return out;
452
620
  }
453
- function localParts(date, tz) {
454
- if (!tz) return { weekday: date.getUTCDay(), year: date.getUTCFullYear() };
621
+ var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
622
+ function localFields(date, tz) {
623
+ if (!tz)
624
+ return {
625
+ second: date.getUTCSeconds(),
626
+ minute: date.getUTCMinutes(),
627
+ hour: date.getUTCHours(),
628
+ dayOfMonth: date.getUTCDate(),
629
+ month: date.getUTCMonth() + 1,
630
+ dayOfWeek: date.getUTCDay(),
631
+ year: date.getUTCFullYear()
632
+ };
455
633
  const parts = new Intl.DateTimeFormat("en-US", {
456
634
  timeZone: tz,
457
635
  weekday: "short",
458
- year: "numeric"
636
+ year: "numeric",
637
+ month: "numeric",
638
+ day: "numeric",
639
+ hour: "numeric",
640
+ minute: "numeric",
641
+ second: "numeric",
642
+ hourCycle: "h23"
459
643
  }).formatToParts(date);
460
- const weekdayName = parts.find((part) => part.type === "weekday")?.value ?? "Sun";
461
- const year = Number(parts.find((part) => part.type === "year")?.value ?? date.getUTCFullYear());
462
- const weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].indexOf(weekdayName);
463
- return { weekday, year };
644
+ const part = (type) => parts.find((entry) => entry.type === type)?.value ?? "0";
645
+ return {
646
+ second: Number(part("second")),
647
+ minute: Number(part("minute")),
648
+ hour: Number(part("hour")) % 24,
649
+ dayOfMonth: Number(part("day")),
650
+ month: Number(part("month")),
651
+ dayOfWeek: WEEKDAYS.indexOf(part("weekday")),
652
+ year: Number(part("year"))
653
+ };
654
+ }
655
+ function localParts(date, tz) {
656
+ const fields = localFields(date, tz);
657
+ return { weekday: fields["dayOfWeek"] ?? 0, year: fields["year"] ?? 0 };
464
658
  }
465
- function calendarTimes(entries, now, tz) {
659
+ var MATCH_FIELDS = [
660
+ { name: "second", min: 0, max: 59, fallback: "0", defaultZero: true },
661
+ { name: "minute", min: 0, max: 59, fallback: "0", defaultZero: true },
662
+ { name: "hour", min: 0, max: 23, fallback: "0", defaultZero: true },
663
+ { name: "dayOfMonth", min: 1, max: 31, fallback: "*", defaultZero: false },
664
+ { name: "month", min: 1, max: 12, fallback: "*", defaultZero: false },
665
+ { name: "dayOfWeek", min: 0, max: 6, fallback: "*", defaultZero: false },
666
+ { name: "year", min: 1970, max: 9999, fallback: "*", defaultZero: false }
667
+ ];
668
+ function calendarMatcher(entry) {
669
+ if (!chunkSAENRNBJ_cjs.isRecord(entry)) throw new Error("each excludeCalendars entry must be an object");
670
+ return MATCH_FIELDS.map((field) => {
671
+ const value = entry[field.name];
672
+ if (value === void 0) return [field.name, field.defaultZero ? /* @__PURE__ */ new Set([0]) : void 0];
673
+ return [field.name, new Set(rangeValues(value, field.min, field.max, field.name))];
674
+ });
675
+ }
676
+ function matches(matcher, fields) {
677
+ return matcher.every(([name, values]) => values === void 0 || values.has(fields[name] ?? -1));
678
+ }
679
+ function calendarTimes(entries, now, tz, accept) {
466
680
  const all = [];
467
681
  for (const entry of entries) {
468
682
  if (!chunkSAENRNBJ_cjs.isRecord(entry)) throw new Error("each calendar entry must be an object");
@@ -475,13 +689,15 @@ function calendarTimes(entries, now, tz) {
475
689
  all.push(
476
690
  ...cronTimes(`${expression} *`, now, tz, (date) => {
477
691
  const local = localParts(date, tz);
478
- return (!weekdays || weekdays.has(local.weekday)) && (!years || years.has(local.year));
692
+ if (!((!weekdays || weekdays.has(local.weekday)) && (!years || years.has(local.year))))
693
+ return "skip";
694
+ return accept(date);
479
695
  })
480
696
  );
481
697
  }
482
698
  return [...new Set(all)].sort().slice(0, FIRE_TIMES);
483
699
  }
484
- function intervalTimes(entries, now) {
700
+ function intervalTimes(entries, now, accept) {
485
701
  const all = [];
486
702
  for (const entry of entries) {
487
703
  if (!chunkSAENRNBJ_cjs.isRecord(entry)) throw new Error("each interval entry must be an object");
@@ -493,10 +709,24 @@ function intervalTimes(entries, now) {
493
709
  throw new Error("interval.offset must be a duration below every");
494
710
  let next = Math.floor((now.getTime() - offset) / every) * every + offset;
495
711
  if (next <= now.getTime()) next += every;
496
- for (let i = 0; i < FIRE_TIMES; i++) all.push(next + i * every);
712
+ let kept = 0;
713
+ for (let i = 0; i < MAX_ITERATIONS && kept < FIRE_TIMES; i++, next += every) {
714
+ const verdict = accept(new Date(next));
715
+ if (verdict === "stop") break;
716
+ if (verdict === "skip") continue;
717
+ all.push(next);
718
+ kept += 1;
719
+ }
497
720
  }
498
721
  return [...new Set(all)].sort((a, b) => a - b).slice(0, FIRE_TIMES).map((time) => new Date(time).toISOString());
499
722
  }
723
+ function dateField(spec, field) {
724
+ const value = spec[field];
725
+ if (value === void 0) return void 0;
726
+ const ms = typeof value === "string" ? Date.parse(value) : Number.NaN;
727
+ if (Number.isNaN(ms)) throw new Error(`${field} must be an ISO 8601 date-time`);
728
+ return new Date(ms);
729
+ }
500
730
  function checkScheduleSpec(spec, options = {}) {
501
731
  const now = options.now ?? /* @__PURE__ */ new Date();
502
732
  if (!chunkSAENRNBJ_cjs.isRecord(spec)) return { ok: false, problem: "spec must be an object", nextFireTimes: [] };
@@ -510,20 +740,37 @@ function checkScheduleSpec(spec, options = {}) {
510
740
  }
511
741
  const tz = timezoneOf(spec, options.timezone);
512
742
  try {
743
+ const startAt = dateField(spec, "startAt");
744
+ const endAt = dateField(spec, "endAt");
745
+ if (startAt && endAt && endAt.getTime() <= startAt.getTime())
746
+ throw new Error("endAt must be after startAt");
747
+ if (spec["jitter"] !== void 0 && chunkFR7KYWRO_cjs.durationMs(spec["jitter"], "s") === void 0)
748
+ throw new Error("jitter must be a duration");
749
+ const excludes = spec["excludeCalendars"];
750
+ if (excludes !== void 0 && !Array.isArray(excludes))
751
+ throw new Error("excludeCalendars must be a list");
752
+ const matchers = (excludes ?? []).map(calendarMatcher);
753
+ const from = startAt && startAt.getTime() > now.getTime() ? new Date(startAt.getTime() - 1) : now;
754
+ const accept = (date) => {
755
+ if (endAt && date.getTime() > endAt.getTime()) return "stop";
756
+ if (matchers.length === 0) return "keep";
757
+ const fields = localFields(date, tz);
758
+ return matchers.some((matcher) => matches(matcher, fields)) ? "skip" : "keep";
759
+ };
513
760
  let times;
514
761
  if (kinds[0] === "cron") {
515
762
  if (typeof spec["cron"] !== "string") throw new Error("cron must be a string");
516
- times = cronTimes(spec["cron"], now, tz, () => true);
763
+ times = cronTimes(spec["cron"], from, tz, accept);
517
764
  } else if (kinds[0] === "calendar") {
518
765
  if (!Array.isArray(spec["calendar"]) || spec["calendar"].length === 0) {
519
766
  throw new Error("calendar must be a non-empty list");
520
767
  }
521
- times = calendarTimes(spec["calendar"], now, tz);
768
+ times = calendarTimes(spec["calendar"], from, tz, accept);
522
769
  } else {
523
770
  if (!Array.isArray(spec["interval"]) || spec["interval"].length === 0) {
524
771
  throw new Error("interval must be a non-empty list");
525
772
  }
526
- times = intervalTimes(spec["interval"], now);
773
+ times = intervalTimes(spec["interval"], from, accept);
527
774
  }
528
775
  if (times.length === 0)
529
776
  return { ok: false, problem: "the spec never fires", nextFireTimes: [] };
@@ -536,6 +783,26 @@ function checkScheduleSpec(spec, options = {}) {
536
783
  };
537
784
  }
538
785
  }
786
+ function checkSchedulePolicy(state) {
787
+ const policy = state["overlapPolicy"];
788
+ if (policy !== void 0 && !(typeof policy === "string" && SCHEDULE_OVERLAP_POLICIES.includes(policy)))
789
+ return {
790
+ field: "overlapPolicy",
791
+ message: `overlapPolicy must be one of ${SCHEDULE_OVERLAP_POLICIES.join(", ")}`
792
+ };
793
+ const window = state["catchupWindow"];
794
+ if (window !== void 0 && chunkFR7KYWRO_cjs.durationMs(window, "s") === void 0)
795
+ return { field: "catchupWindow", message: "catchupWindow must be a duration" };
796
+ if (state["pauseOnFailure"] !== void 0 && typeof state["pauseOnFailure"] !== "boolean")
797
+ return { field: "pauseOnFailure", message: "pauseOnFailure must be true or false" };
798
+ const limited = state["limitedActions"];
799
+ if (limited !== void 0 && !(typeof limited === "number" && Number.isInteger(limited) && limited >= 1))
800
+ return { field: "limitedActions", message: "limitedActions must be a positive integer" };
801
+ for (const field of ["scheduleContext", "scheduleSearchAttributes"])
802
+ if (state[field] !== void 0 && !chunkSAENRNBJ_cjs.isRecord(state[field]))
803
+ return { field, message: `${field} must be an object` };
804
+ return void 0;
805
+ }
539
806
 
540
807
  // src/ir/validate.ts
541
808
  var SLUG = /^[a-z][a-z0-9-]{0,62}$/;
@@ -605,7 +872,7 @@ function isHardSchemaError(error) {
605
872
  function legacyMirrors(node) {
606
873
  const found = [];
607
874
  const type = typeof node["type"] === "string" ? node["type"] : "";
608
- const merged = chunkGBQ33SIZ_cjs.usesMergedParameters(type);
875
+ const merged = chunk54FLQNUM_cjs.usesMergedParameters(type);
609
876
  const data = chunkSAENRNBJ_cjs.isRecord(node["data"]) ? node["data"] : void 0;
610
877
  const dataArgs = chunkSAENRNBJ_cjs.isRecord(data?.["args"]) ? data["args"] : void 0;
611
878
  if (data) {
@@ -769,7 +1036,7 @@ function validate(definition, options = {}) {
769
1036
  const type = typeof node["type"] === "string" ? node["type"] : "";
770
1037
  const args = chunkSAENRNBJ_cjs.isRecord(node["args"]) ? node["args"] : void 0;
771
1038
  const state = chunkSAENRNBJ_cjs.isRecord(args?.["state"]) ? args["state"] : void 0;
772
- if (type === chunkGBQ33SIZ_cjs.CODE_WORKFLOW_NODE_TYPE) {
1039
+ if (type === chunk54FLQNUM_cjs.CODE_WORKFLOW_NODE_TYPE) {
773
1040
  const workflowFn = state?.["workflowFn"];
774
1041
  if (!code) {
775
1042
  fail({
@@ -777,7 +1044,8 @@ function validate(definition, options = {}) {
777
1044
  message: "A code-workflow node needs a code bundle on the definition",
778
1045
  ...at
779
1046
  });
780
- } else if (typeof workflowFn !== "string" || !Object.hasOwn(workflowExports, workflowFn)) {
1047
+ } else if (typeof workflowFn !== "string" || workflowFn === "" || // A dynamic workflow ("*", 11 §2.29) serves every other name.
1048
+ !(Object.hasOwn(workflowExports, workflowFn) || Object.hasOwn(workflowExports, "*"))) {
781
1049
  fail({
782
1050
  code: "codeWorkflow.unknownFunction",
783
1051
  message: `workflowFn "${String(workflowFn)}" is not exported by the bundle`,
@@ -802,7 +1070,7 @@ function validate(definition, options = {}) {
802
1070
  path: "args.state.timeout"
803
1071
  });
804
1072
  }
805
- if (type === chunkGBQ33SIZ_cjs.WAIT_FOR_SIGNAL_NODE_TYPE) {
1073
+ if (type === chunk54FLQNUM_cjs.WAIT_FOR_SIGNAL_NODE_TYPE) {
806
1074
  const until = state?.["limitWaitUntil"];
807
1075
  if (until !== void 0 && (typeof until !== "string" || Number.isNaN(Date.parse(until))))
808
1076
  fail({
@@ -812,7 +1080,7 @@ function validate(definition, options = {}) {
812
1080
  path: "args.state.limitWaitUntil"
813
1081
  });
814
1082
  }
815
- const isTrigger = chunkGBQ33SIZ_cjs.INTERNAL_TRIGGER_TYPES.has(type) || id !== void 0 && (incoming.get(id) ?? 0) === 0;
1083
+ const isTrigger = chunk54FLQNUM_cjs.INTERNAL_TRIGGER_TYPES.has(type) || id !== void 0 && (incoming.get(id) ?? 0) === 0;
816
1084
  if (isTrigger && state?.["startDelay"] !== void 0) {
817
1085
  const delay = chunkFR7KYWRO_cjs.durationMs(state["startDelay"], "s");
818
1086
  if (delay === void 0) {
@@ -845,6 +1113,44 @@ function validate(definition, options = {}) {
845
1113
  });
846
1114
  }
847
1115
  }
1116
+ if (type === "internal:schedule" && state !== void 0) {
1117
+ const problem = checkSchedulePolicy(state);
1118
+ if (problem !== void 0)
1119
+ fail({
1120
+ code: "schedule.invalidPolicy",
1121
+ message: `Schedule policy: ${problem.message}`,
1122
+ ...at,
1123
+ path: `args.state.${problem.field}`
1124
+ });
1125
+ }
1126
+ if (type === chunk54FLQNUM_cjs.SIGNAL_RUN_NODE_TYPE) {
1127
+ const target = state?.["target"];
1128
+ const valid = chunkSAENRNBJ_cjs.isRecord(target) && (typeof target["runId"] === "string" || target["parent"] === true || typeof target["workflowKey"] === "string" && typeof target["workflowId"] === "string");
1129
+ if (typeof state?.["signalName"] !== "string" || state["signalName"] === "")
1130
+ fail({
1131
+ code: "signalRun.signalNameRequired",
1132
+ message: "A signal-run node needs a signalName",
1133
+ ...at,
1134
+ path: "args.state.signalName"
1135
+ });
1136
+ if (!valid)
1137
+ fail({
1138
+ code: "signalRun.invalidTarget",
1139
+ message: "A signal-run node needs a target: { runId }, { workflowKey, workflowId } or { parent: true }",
1140
+ ...at,
1141
+ path: "args.state.target"
1142
+ });
1143
+ }
1144
+ if (type === chunk54FLQNUM_cjs.SET_SEARCH_ATTRIBUTES_NODE_TYPE) {
1145
+ const attributes = state?.["attributes"];
1146
+ if (!chunkSAENRNBJ_cjs.isRecord(attributes) || Object.keys(attributes).length === 0)
1147
+ fail({
1148
+ code: "setSearchAttributes.attributesRequired",
1149
+ message: "A set-search-attributes node needs at least one attribute",
1150
+ ...at,
1151
+ path: "args.state.attributes"
1152
+ });
1153
+ }
848
1154
  if (strict) {
849
1155
  if (id && !SLUG.test(id)) {
850
1156
  fail({
@@ -1002,14 +1308,14 @@ function isV2Definition(definition) {
1002
1308
  const data = definition["data"];
1003
1309
  const nodes = chunkSAENRNBJ_cjs.isRecord(data) && Array.isArray(data["nodes"]) ? data["nodes"] : [];
1004
1310
  return nodes.some(
1005
- (node) => chunkSAENRNBJ_cjs.isRecord(node) && typeof node["type"] === "string" && chunkGBQ33SIZ_cjs.V2_NODE_TYPES.has(node["type"])
1311
+ (node) => chunkSAENRNBJ_cjs.isRecord(node) && typeof node["type"] === "string" && chunk54FLQNUM_cjs.V2_NODE_TYPES.has(node["type"])
1006
1312
  );
1007
1313
  }
1008
1314
  function envelopeSchemaVersion(definition) {
1009
1315
  return isV2Definition(definition) ? 2 : 1;
1010
1316
  }
1011
1317
  function exportDefinition(definition) {
1012
- return isV2Definition(definition) ? chunkGBQ33SIZ_cjs.normalizeDefinition(definition) : definition;
1318
+ return isV2Definition(definition) ? chunk54FLQNUM_cjs.normalizeDefinition(definition) : definition;
1013
1319
  }
1014
1320
  function buildExportDocument(input) {
1015
1321
  return {
@@ -1111,7 +1417,7 @@ function deriveInterface(definition, options = {}) {
1111
1417
 
1112
1418
  Object.defineProperty(exports, "diffDefinitions", {
1113
1419
  enumerable: true,
1114
- get: function () { return chunkNEIUQASE_cjs.diffDefinitions; }
1420
+ get: function () { return chunk4QKB4ARC_cjs.diffDefinitions; }
1115
1421
  });
1116
1422
  Object.defineProperty(exports, "fieldSchema", {
1117
1423
  enumerable: true,
@@ -1135,39 +1441,51 @@ Object.defineProperty(exports, "operationsOf", {
1135
1441
  });
1136
1442
  Object.defineProperty(exports, "CODE_WORKFLOW_NODE_TYPE", {
1137
1443
  enumerable: true,
1138
- get: function () { return chunkGBQ33SIZ_cjs.CODE_WORKFLOW_NODE_TYPE; }
1444
+ get: function () { return chunk54FLQNUM_cjs.CODE_WORKFLOW_NODE_TYPE; }
1139
1445
  });
1140
1446
  Object.defineProperty(exports, "INTERNAL_TRIGGER_TYPES", {
1141
1447
  enumerable: true,
1142
- get: function () { return chunkGBQ33SIZ_cjs.INTERNAL_TRIGGER_TYPES; }
1448
+ get: function () { return chunk54FLQNUM_cjs.INTERNAL_TRIGGER_TYPES; }
1449
+ });
1450
+ Object.defineProperty(exports, "PHASE_C_NODE_TYPES", {
1451
+ enumerable: true,
1452
+ get: function () { return chunk54FLQNUM_cjs.PHASE_C_NODE_TYPES; }
1453
+ });
1454
+ Object.defineProperty(exports, "SET_SEARCH_ATTRIBUTES_NODE_TYPE", {
1455
+ enumerable: true,
1456
+ get: function () { return chunk54FLQNUM_cjs.SET_SEARCH_ATTRIBUTES_NODE_TYPE; }
1457
+ });
1458
+ Object.defineProperty(exports, "SIGNAL_RUN_NODE_TYPE", {
1459
+ enumerable: true,
1460
+ get: function () { return chunk54FLQNUM_cjs.SIGNAL_RUN_NODE_TYPE; }
1143
1461
  });
1144
1462
  Object.defineProperty(exports, "WAIT_FOR_SIGNAL_NODE_TYPE", {
1145
1463
  enumerable: true,
1146
- get: function () { return chunkGBQ33SIZ_cjs.WAIT_FOR_SIGNAL_NODE_TYPE; }
1464
+ get: function () { return chunk54FLQNUM_cjs.WAIT_FOR_SIGNAL_NODE_TYPE; }
1147
1465
  });
1148
1466
  Object.defineProperty(exports, "buildIdOf", {
1149
1467
  enumerable: true,
1150
- get: function () { return chunkGBQ33SIZ_cjs.buildIdOf; }
1468
+ get: function () { return chunk54FLQNUM_cjs.buildIdOf; }
1151
1469
  });
1152
1470
  Object.defineProperty(exports, "hashedProjection", {
1153
1471
  enumerable: true,
1154
- get: function () { return chunkGBQ33SIZ_cjs.hashedProjection; }
1472
+ get: function () { return chunk54FLQNUM_cjs.hashedProjection; }
1155
1473
  });
1156
1474
  Object.defineProperty(exports, "irHash", {
1157
1475
  enumerable: true,
1158
- get: function () { return chunkGBQ33SIZ_cjs.irHash; }
1476
+ get: function () { return chunk54FLQNUM_cjs.irHash; }
1159
1477
  });
1160
1478
  Object.defineProperty(exports, "normalizeDefinition", {
1161
1479
  enumerable: true,
1162
- get: function () { return chunkGBQ33SIZ_cjs.normalizeDefinition; }
1480
+ get: function () { return chunk54FLQNUM_cjs.normalizeDefinition; }
1163
1481
  });
1164
1482
  Object.defineProperty(exports, "sourceHash", {
1165
1483
  enumerable: true,
1166
- get: function () { return chunkGBQ33SIZ_cjs.sourceHash; }
1484
+ get: function () { return chunk54FLQNUM_cjs.sourceHash; }
1167
1485
  });
1168
1486
  Object.defineProperty(exports, "usesMergedParameters", {
1169
1487
  enumerable: true,
1170
- get: function () { return chunkGBQ33SIZ_cjs.usesMergedParameters; }
1488
+ get: function () { return chunk54FLQNUM_cjs.usesMergedParameters; }
1171
1489
  });
1172
1490
  Object.defineProperty(exports, "LAYOUT_COLUMN_WIDTH", {
1173
1491
  enumerable: true,
@@ -1221,10 +1539,16 @@ Object.defineProperty(exports, "durationMs", {
1221
1539
  enumerable: true,
1222
1540
  get: function () { return chunkFR7KYWRO_cjs.durationMs; }
1223
1541
  });
1542
+ exports.DEFAULT_NEW_SCHEDULE_OVERLAP_POLICY = DEFAULT_NEW_SCHEDULE_OVERLAP_POLICY;
1543
+ exports.DEFAULT_SCHEDULE_CATCHUP_WINDOW_SECONDS = DEFAULT_SCHEDULE_CATCHUP_WINDOW_SECONDS;
1224
1544
  exports.IR_V2_SCHEMA = IR_V2_SCHEMA;
1225
1545
  exports.IR_V2_SCHEMA_ID = IR_V2_SCHEMA_ID;
1546
+ exports.SCHEDULE_OVERLAP_POLICIES = SCHEDULE_OVERLAP_POLICIES;
1547
+ exports.SCHEDULE_POLICY_FIELDS = SCHEDULE_POLICY_FIELDS;
1548
+ exports.SCHEDULE_SPEC_FIELDS = SCHEDULE_SPEC_FIELDS;
1226
1549
  exports.WORKFLOW_DOCUMENT_FORMAT = WORKFLOW_DOCUMENT_FORMAT;
1227
1550
  exports.buildExportDocument = buildExportDocument;
1551
+ exports.checkSchedulePolicy = checkSchedulePolicy;
1228
1552
  exports.checkScheduleSpec = checkScheduleSpec;
1229
1553
  exports.deriveInterface = deriveInterface;
1230
1554
  exports.envelopeSchemaVersion = envelopeSchemaVersion;