@fluidgrids/workflows 2026.1028.2 → 2026.1029.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 (118) hide show
  1. package/README.md +72 -10
  2. package/dist/{activation-DnhG7SmF.d.ts → activation-BnVQMv9y.d.ts} +1 -1
  3. package/dist/{activation-BBh1p82z.d.cts → activation-CESehfYi.d.cts} +1 -1
  4. package/dist/{chunk-XHXIDVEC.js → chunk-25BKWR2O.js} +1 -1
  5. package/dist/{chunk-UK3WM7YZ.cjs → chunk-2B37XAFQ.cjs} +44 -8
  6. package/dist/{chunk-DJYMDLV5.js → chunk-2DDULZFM.js} +93 -1
  7. package/dist/{chunk-623FVQSN.cjs → chunk-3FIDHONL.cjs} +104 -0
  8. package/dist/chunk-6QPOJZT6.cjs +1180 -0
  9. package/dist/chunk-7ILGCUI6.js +154 -0
  10. package/dist/chunk-A2OHX3UQ.js +1156 -0
  11. package/dist/{chunk-VOKMAAJP.js → chunk-A36CCOWS.js} +188 -19
  12. package/dist/{chunk-FMSW2HDF.cjs → chunk-ELL2RBML.cjs} +0 -14
  13. package/dist/{chunk-JD2VQIDZ.cjs → chunk-EWYADREB.cjs} +2 -2
  14. package/dist/{chunk-HWJZVOG7.js → chunk-FQSJI5NV.js} +1 -1
  15. package/dist/{chunk-ABFZWYHT.js → chunk-FWBRQWRX.js} +156 -48
  16. package/dist/{chunk-PZCVF76Q.cjs → chunk-I47EENR4.cjs} +209 -40
  17. package/dist/chunk-J3PYFGKA.cjs +166 -0
  18. package/dist/{chunk-C5OLWZ42.js → chunk-KXJDRQ6G.js} +1 -13
  19. package/dist/chunk-M272AHEX.js +25 -0
  20. package/dist/{chunk-VRHHBPT6.js → chunk-MJ5TGYVG.js} +333 -65
  21. package/dist/{chunk-SAOBPYYJ.cjs → chunk-NXFBVDOI.cjs} +3 -3
  22. package/dist/{chunk-XKJA7KX3.js → chunk-OIX4O6UR.js} +38 -2
  23. package/dist/{chunk-FEW3JBYA.cjs → chunk-OKX3FYIM.cjs} +3 -3
  24. package/dist/{chunk-M4BBAERY.cjs → chunk-OMY3CKUZ.cjs} +404 -136
  25. package/dist/chunk-PWIUEWC3.js +81 -0
  26. package/dist/chunk-Q4MWQNJK.cjs +28 -0
  27. package/dist/{chunk-P6TA5EZT.cjs → chunk-RUQIMTN5.cjs} +171 -57
  28. package/dist/{chunk-IISBRUWJ.js → chunk-WXXNCHUY.js} +1 -1
  29. package/dist/chunk-YHBVMOMK.cjs +87 -0
  30. package/dist/codegen/index.d.cts +2 -2
  31. package/dist/codegen/index.d.ts +2 -2
  32. package/dist/collect-BTHjQaSp.d.ts +86 -0
  33. package/dist/collect-CSyOg5XC.d.cts +86 -0
  34. package/dist/{file-BOoHZgoQ.d.cts → file-cgL9l9l8.d.cts} +765 -14
  35. package/dist/{file-yuPCFU5b.d.ts → file-olQudcx5.d.ts} +765 -14
  36. package/dist/history/index.cjs +198 -86
  37. package/dist/history/index.d.cts +49 -10
  38. package/dist/history/index.d.ts +49 -10
  39. package/dist/history/index.js +49 -4
  40. package/dist/index.cjs +64 -51
  41. package/dist/index.d.cts +9 -53
  42. package/dist/index.d.ts +9 -53
  43. package/dist/index.js +5 -4
  44. package/dist/ir/index.cjs +24 -3
  45. package/dist/ir/index.d.cts +43 -4
  46. package/dist/ir/index.d.ts +43 -4
  47. package/dist/ir/index.js +24 -3
  48. package/dist/{lower-BzmUz0sq.d.cts → lower-3S6PsqjJ.d.cts} +40 -6
  49. package/dist/{lower-_-iT4HYs.d.ts → lower-DmZpQ8hJ.d.ts} +40 -6
  50. package/dist/{manifest-C8N6HDYl.d.ts → manifest-BJjrQt77.d.ts} +1 -1
  51. package/dist/{manifest-0OLw0i7k.d.cts → manifest-gRI2Q5Fj.d.cts} +1 -1
  52. package/dist/node-evaluator-SOADN23V.js +14 -0
  53. package/dist/node-evaluator-YGDEXK4U.cjs +24 -0
  54. package/dist/quickjs/index.cjs +25 -24
  55. package/dist/quickjs/index.d.cts +6 -6
  56. package/dist/quickjs/index.d.ts +6 -6
  57. package/dist/quickjs/index.js +8 -7
  58. package/dist/roundtrip/index.cjs +245 -43
  59. package/dist/roundtrip/index.d.cts +86 -9
  60. package/dist/roundtrip/index.d.ts +86 -9
  61. package/dist/roundtrip/index.js +172 -8
  62. package/dist/runtime/index.cjs +21 -20
  63. package/dist/runtime/index.d.cts +49 -7
  64. package/dist/runtime/index.d.ts +49 -7
  65. package/dist/runtime/index.js +8 -7
  66. package/dist/testing/index.cjs +514 -74
  67. package/dist/testing/index.d.cts +127 -10
  68. package/dist/testing/index.d.ts +127 -10
  69. package/dist/testing/index.js +480 -42
  70. package/dist/{types-BGoPzgcl.d.ts → types-Bb2wRnJ5.d.cts} +20 -1
  71. package/dist/{types-BGoPzgcl.d.cts → types-Bb2wRnJ5.d.ts} +20 -1
  72. package/dist/{types-DV-HX_Gt.d.ts → types-CQKOhPTa.d.cts} +122 -14
  73. package/dist/{types-CpBBjaGX.d.cts → types-CnIOinoz.d.ts} +122 -14
  74. package/dist/{workflow-Bpr3vnA_.d.ts → workflow-8uRU9rhL.d.ts} +2 -2
  75. package/dist/{workflow-FXUkpIBc.d.cts → workflow-CZOXUlQ5.d.cts} +2 -2
  76. package/dist/{workflow-C2a05WUJ.d.ts → workflow-DWTPHFbt.d.ts} +124 -12
  77. package/dist/{workflow-J-yYixny.d.cts → workflow-O6e64ZcG.d.cts} +124 -12
  78. package/fixtures/histories/auto-upgrade-patched.history.json +276 -0
  79. package/fixtures/histories/benign-failure.history.json +146 -0
  80. package/fixtures/histories/cancel-activity-try-cancel.history.json +150 -0
  81. package/fixtures/histories/child-cancel-wait-requested.history.json +217 -0
  82. package/fixtures/histories/child-options-roundtrip.history.json +192 -0
  83. package/fixtures/histories/continue-as-new-last-result.history.json +86 -0
  84. package/fixtures/histories/continue-as-new-options.history.json +99 -0
  85. package/fixtures/histories/continue-as-new-r1-long-task-queue.history.json +78 -0
  86. package/fixtures/histories/continue-as-new-r1-retry-options.history.json +83 -0
  87. package/fixtures/histories/execution-timeout-chain.history.json +98 -0
  88. package/fixtures/histories/external-cancel-resolved.history.json +123 -0
  89. package/fixtures/histories/external-cancel-unknown-target.history.json +127 -0
  90. package/fixtures/histories/failure-error-types-fails-run.history.json +144 -0
  91. package/fixtures/histories/handler-drain-warn.history.json +222 -0
  92. package/fixtures/histories/heartbeat-details-on-retry.history.json +145 -0
  93. package/fixtures/histories/local-activity-abandoned-at-completion.history.json +73 -0
  94. package/fixtures/histories/local-activity-cancelled-in-scope.history.json +118 -0
  95. package/fixtures/histories/local-activity-completed.history.json +157 -0
  96. package/fixtures/histories/local-activity-failed.history.json +93 -0
  97. package/fixtures/histories/local-activity-retry-in-task.history.json +88 -0
  98. package/fixtures/histories/run-retry-last-failure.history.json +90 -0
  99. package/fixtures/histories/run-timeout.history.json +159 -0
  100. package/fixtures/histories/schedule-to-start-timeout.history.json +132 -0
  101. package/fixtures/histories/start-delay-signal-ends-delay.history.json +155 -0
  102. package/fixtures/histories/typeerror-task-retry-100.history.json +137 -0
  103. package/package.json +1 -1
  104. package/schema/history-file.schema.json +283 -2
  105. package/schema/ir-v2.schema.json +45 -0
  106. package/schema/run-event.schema.json +264 -2
  107. package/schema/workflow-command.schema.json +178 -1
  108. package/schema/workflow-task.schema.json +392 -4
  109. package/dist/assemble-BLqQ8lSu.d.cts +0 -39
  110. package/dist/assemble-DWgaXHd-.d.ts +0 -39
  111. package/dist/chunk-2J6TF7YI.cjs +0 -86
  112. package/dist/chunk-BO6OVILK.js +0 -79
  113. package/dist/chunk-DHTLALBL.cjs +0 -80
  114. package/dist/chunk-I5LR3D2K.js +0 -869
  115. package/dist/chunk-N23SKIG4.js +0 -73
  116. package/dist/chunk-QQ6ULXHI.cjs +0 -885
  117. package/dist/node-evaluator-4MSDKWOG.cjs +0 -22
  118. package/dist/node-evaluator-SX4LEYQC.js +0 -12
@@ -1,7 +1,6 @@
1
1
  import { isRecord } from './chunk-PMCM2OH4.js';
2
- import { isWorkflowCommandEnabled } from './chunk-ABFZWYHT.js';
3
- import { CHILD_CANCELLATION_TYPES, PARENT_CLOSE_POLICIES, ERROR_TYPES, ACTIVITY_CANCELLATION_TYPES, TASK_FAILURE_CAUSES, EVENT_TYPES, COMMAND_TYPES, BUILT_IN_QUERIES, HISTORY_PROTOCOL, TERMINAL_COMMANDS } from './chunk-DJYMDLV5.js';
4
- import { isActivityNodeTypeAllowed } from './chunk-BO6OVILK.js';
2
+ import { isWorkflowCommandEnabled, isReliefCommand, unsupportedMessage } from './chunk-FWBRQWRX.js';
3
+ import { VERSIONING_BEHAVIORS, WORKFLOW_ID_CONFLICT_POLICIES, WORKFLOW_ID_REUSE_POLICIES, CHILD_CANCELLATION_TYPES, PARENT_CLOSE_POLICIES, ERROR_TYPES, ACTIVITY_CANCELLATION_TYPES, WORKFLOW_TIMEOUT_TYPES, TASK_FAILURE_CAUSES, EVENT_TYPES, COMMAND_TYPES, BUILT_IN_QUERIES, HISTORY_PROTOCOL, LOCAL_ACTIVITY_MAX_TIMEOUT_MS, TERMINAL_COMMANDS, isActivityNodeTypeAllowed } from './chunk-2DDULZFM.js';
5
4
  import { Ajv2020 } from 'ajv/dist/2020.js';
6
5
 
7
6
  // src/history/schema.ts
@@ -73,11 +72,36 @@ var SHARED_DEFS = {
73
72
  {
74
73
  type: "object",
75
74
  required: ["workflowKey", "workflowId"],
76
- properties: { workflowKey: ID, workflowId: ID },
75
+ description: "The open run of a workflow id, following its continue-as-new chain; firstRunId pins the chain (R2).",
76
+ properties: { workflowKey: ID, workflowId: ID, firstRunId: ID },
77
77
  additionalProperties: false
78
78
  }
79
79
  ]
80
80
  },
81
+ runRetryPolicy: {
82
+ type: "object",
83
+ required: ["initialDelayMs"],
84
+ description: "Run-level retry (11 \xA72.17), in milliseconds. maxAttempts counts every attempt; absent means unlimited, bounded by the execution timeout.",
85
+ properties: {
86
+ maxAttempts: { type: "integer", minimum: 1 },
87
+ initialDelayMs: NON_NEGATIVE_MS,
88
+ backoffMultiplier: { type: "number", minimum: 1 },
89
+ maxDelayMs: NON_NEGATIVE_MS,
90
+ retryOnErrorTypes: { type: "array", items: { enum: [...ERROR_TYPES] } },
91
+ nonRetryableErrorTypes: { type: "array", items: { type: "string" } }
92
+ },
93
+ additionalProperties: false
94
+ },
95
+ timeouts: {
96
+ type: "object",
97
+ description: "The three workflow timeouts (11 \xA72.20), in milliseconds.",
98
+ properties: {
99
+ executionTimeout: NON_NEGATIVE_MS,
100
+ runTimeout: NON_NEGATIVE_MS,
101
+ workflowTaskTimeout: NON_NEGATIVE_MS
102
+ },
103
+ additionalProperties: false
104
+ },
81
105
  childOptions: {
82
106
  type: "object",
83
107
  required: ["parentClosePolicy"],
@@ -93,9 +117,41 @@ var SHARED_DEFS = {
93
117
  executionTimeout: NON_NEGATIVE_MS,
94
118
  runTimeout: NON_NEGATIVE_MS,
95
119
  workflowTaskTimeout: NON_NEGATIVE_MS,
96
- startDelay: NON_NEGATIVE_MS
120
+ startDelay: NON_NEGATIVE_MS,
121
+ retry: { $ref: "#/$defs/runRetryPolicy" },
122
+ versioningBehavior: { enum: [...VERSIONING_BEHAVIORS] },
123
+ idReusePolicy: { enum: [...WORKFLOW_ID_REUSE_POLICIES] },
124
+ idConflictPolicy: { enum: [...WORKFLOW_ID_CONFLICT_POLICIES] }
97
125
  }
98
126
  },
127
+ legacyCanRetryPolicy: {
128
+ type: "object",
129
+ required: ["retryDelay"],
130
+ description: "The R1 activity-shaped CONTINUE_AS_NEW retry: whatever explicitRetryPolicy wrote from a Partial<RetryPolicy>, so numbers carry no integer or minimum constraint. It never had a meaning, and the service ignores it.",
131
+ properties: {
132
+ maxRetries: { type: "number" },
133
+ retryDelay: { type: "number" },
134
+ backoffMultiplier: { type: "number" },
135
+ maxDelay: { type: "number" },
136
+ retryOnErrorTypes: { type: "array", items: { type: "string" } },
137
+ nonRetryableErrorTypes: { type: "array", items: { type: "string" } }
138
+ },
139
+ additionalProperties: false
140
+ },
141
+ canOptions: {
142
+ type: "object",
143
+ description: "Options of a CONTINUE_AS_NEW command (C-SCHEMA, frozen in R2). retry is the R2 run-retry policy of the new run, or the R1 activity shape (retryDelay, maxRetries, maxDelay) that R1 bundles wrote and R2 bundles still write for that shape: it never had a meaning, and the service ignores it instead of reading it as a run-retry policy.",
144
+ properties: {
145
+ taskQueue: ID,
146
+ retry: {
147
+ oneOf: [{ $ref: "#/$defs/runRetryPolicy" }, { $ref: "#/$defs/legacyCanRetryPolicy" }]
148
+ },
149
+ workflowTaskTimeout: NON_NEGATIVE_MS,
150
+ context: { type: "object" },
151
+ versioningBehavior: { enum: [...VERSIONING_BEHAVIORS] }
152
+ },
153
+ additionalProperties: false
154
+ },
99
155
  headers: STRING_MAP
100
156
  };
101
157
  function command(type, required, properties) {
@@ -169,13 +225,16 @@ var COMMAND_DEFS = {
169
225
  localActivityId: ID,
170
226
  result: {},
171
227
  failure: { $ref: "#/$defs/failure" },
172
- attempts: { type: "integer", minimum: 1 }
228
+ attempts: { type: "integer", minimum: 1 },
229
+ nodeType: ID,
230
+ operation: ID,
231
+ summary: { type: "string", maxLength: 200 }
173
232
  }),
174
233
  oneOf: [{ required: ["result"] }, { required: ["failure"] }]
175
234
  },
176
235
  CONTINUE_AS_NEW: command("CONTINUE_AS_NEW", ["input", "options"], {
177
236
  input: {},
178
- options: { type: "object" }
237
+ options: { $ref: "#/$defs/canOptions" }
179
238
  }),
180
239
  REQUEST_CANCEL_EXTERNAL_RUN: command("REQUEST_CANCEL_EXTERNAL_RUN", ["externalId", "target"], {
181
240
  externalId: ID,
@@ -221,9 +280,26 @@ var EVENT_PAYLOADS = {
221
280
  executionTimeout: NON_NEGATIVE_MS,
222
281
  runTimeout: NON_NEGATIVE_MS,
223
282
  workflowTaskTimeout: NON_NEGATIVE_MS,
224
- versioningBehavior: { enum: ["PINNED", "AUTO_UPGRADE"] },
283
+ versioningBehavior: { enum: [...VERSIONING_BEHAVIORS] },
225
284
  /** Seed of `ctx.random()`/`ctx.uuid()`; the service writes the run id. Absent: `info.runId`. */
226
- randomnessSeed: ID
285
+ randomnessSeed: ID,
286
+ startDelayMs: {
287
+ ...NON_NEGATIVE_MS,
288
+ description: "R2: the start delay of a delayed run (11 \xA72.23); the first task waits for it."
289
+ },
290
+ runAttempt: {
291
+ type: "integer",
292
+ minimum: 1,
293
+ description: "R2: the run-level retry attempt (11 \xA72.17), 1-based."
294
+ },
295
+ businessId: {
296
+ type: "string",
297
+ description: "R2: the workflow id (11 \xA72.1), stored as WorkflowRun.businessId."
298
+ },
299
+ workflowId: { type: "string", description: "R2: the same value as businessId." },
300
+ timeouts: { $ref: "#/$defs/timeouts" },
301
+ retry: { $ref: "#/$defs/runRetryPolicy" },
302
+ priority: { type: "integer", minimum: 1, maximum: 5 }
227
303
  }),
228
304
  WORKFLOW_TASK_SCHEDULED: payload(["taskId"], {
229
305
  taskId: ID,
@@ -242,6 +318,9 @@ var EVENT_PAYLOADS = {
242
318
  type: "integer",
243
319
  minimum: 1,
244
320
  description: "The history length the attempt was leased with (run.taskStartedSeq), when it is not this event's own seq. Required on the WORKFLOW_TASK_STARTED of a transient attempt: input events with a higher seq that precede this event arrived during the attempt and belong to the next activation."
321
+ },
322
+ version: {
323
+ description: "R2: the workflow version whose bundle served the task (it differs from WORKFLOW_STARTED.version after an AUTO_UPGRADE or a versioning override)."
245
324
  }
246
325
  }),
247
326
  WORKFLOW_TASK_COMPLETED: payload(["taskId"], {
@@ -346,7 +425,7 @@ var EVENT_PAYLOADS = {
346
425
  CHILD_RUN_TIMED_OUT: payload(["childId"], {
347
426
  childId: ID,
348
427
  childRunId: ID,
349
- timeoutType: { enum: ["WORKFLOW_RUN", "WORKFLOW_EXECUTION"] }
428
+ timeoutType: { enum: [...WORKFLOW_TIMEOUT_TYPES] }
350
429
  }),
351
430
  EXTERNAL_RUN_CANCEL_REQUESTED: payload(["externalId", "target"], {
352
431
  externalId: ID,
@@ -380,12 +459,18 @@ var EVENT_PAYLOADS = {
380
459
  LOCAL_ACTIVITY_COMPLETED: payload(["localActivityId", "attempts"], {
381
460
  localActivityId: ID,
382
461
  result: {},
383
- attempts: { type: "integer", minimum: 1 }
462
+ attempts: { type: "integer", minimum: 1 },
463
+ nodeType: ID,
464
+ operation: ID,
465
+ summary: { type: "string" }
384
466
  }),
385
467
  LOCAL_ACTIVITY_FAILED: payload(["localActivityId", "attempts", "failure"], {
386
468
  localActivityId: ID,
387
469
  failure: FAILURE_REF,
388
- attempts: { type: "integer", minimum: 1 }
470
+ attempts: { type: "integer", minimum: 1 },
471
+ nodeType: ID,
472
+ operation: ID,
473
+ summary: { type: "string" }
389
474
  }),
390
475
  SEARCH_ATTRIBUTES_UPSERTED: payload(["attributes"], { attributes: { type: "object" } }),
391
476
  CONTEXT_UPSERTED: payload(["entries"], { entries: { type: "object" } }),
@@ -399,17 +484,45 @@ var EVENT_PAYLOADS = {
399
484
  toSeq: { type: "integer", minimum: 1 },
400
485
  reason: { type: "string" }
401
486
  }),
402
- VERSIONING_OVERRIDE_SET: payload(["override"], { override: {} }),
487
+ VERSIONING_OVERRIDE_SET: payload(["override"], {
488
+ override: {
489
+ description: "The per-run override (11 \xA72.27): { behavior: PINNED, version } pins the run, { behavior: AUTO_UPGRADE } upgrades it, null removes the override.",
490
+ oneOf: [
491
+ { type: "null" },
492
+ {
493
+ type: "object",
494
+ required: ["behavior", "version"],
495
+ properties: { behavior: { const: "PINNED" }, version: {} },
496
+ additionalProperties: false
497
+ },
498
+ {
499
+ type: "object",
500
+ required: ["behavior"],
501
+ properties: { behavior: { const: "AUTO_UPGRADE" } },
502
+ additionalProperties: false
503
+ }
504
+ ]
505
+ },
506
+ actor: {},
507
+ reason: { type: "string" }
508
+ }),
403
509
  WORKFLOW_COMPLETED: payload(["output"], { output: {} }),
404
510
  WORKFLOW_FAILED: payload(["failure"], { failure: FAILURE_REF }),
405
511
  WORKFLOW_CANCELLED: payload([], { details: {} }),
406
512
  WORKFLOW_TERMINATED: payload([], { reason: { type: "string" }, actor: {} }),
407
513
  WORKFLOW_TIMED_OUT: payload(["timeoutType"], {
408
- timeoutType: { enum: ["WORKFLOW_RUN", "WORKFLOW_EXECUTION"] }
514
+ timeoutType: { enum: [...WORKFLOW_TIMEOUT_TYPES] },
515
+ failure: FAILURE_REF
409
516
  }),
410
517
  WORKFLOW_CONTINUED_AS_NEW: payload(["input", "options"], {
411
518
  input: {},
412
- options: { type: "object" },
519
+ // Not canOptions: the event keeps what the service accepted when the run
520
+ // continued, and Phase B (R1) runs stored options that the R2 command shape
521
+ // refuses (fractional delays, a backoff below 1, a long task queue).
522
+ options: {
523
+ type: "object",
524
+ description: "The CONTINUE_AS_NEW options as the service recorded them. New commands are checked against canOptions; histories recorded before R2 may hold any object the R1 contract accepted."
525
+ },
413
526
  newRunId: { type: "string" }
414
527
  })
415
528
  };
@@ -494,7 +607,9 @@ var WORKFLOW_TASK_SCHEMA = {
494
607
  version: {},
495
608
  buildId: { type: "string" },
496
609
  businessId: { type: "string" },
610
+ workflowId: { type: "string" },
497
611
  attempt: { type: "integer", minimum: 1 },
612
+ runAttempt: { type: "integer", minimum: 1 },
498
613
  taskQueue: { type: "string" },
499
614
  parentRunId: { type: ["string", "null"] },
500
615
  rootRunId: { type: ["string", "null"] },
@@ -517,9 +632,46 @@ var WORKFLOW_TASK_SCHEMA = {
517
632
  priority: { type: "integer", minimum: 1, maximum: 5 },
518
633
  summary: { type: "string" },
519
634
  details: { type: "string" },
520
- context: { type: "object" }
635
+ context: { type: "object" },
636
+ memo: { type: "object" },
637
+ versioningBehavior: { enum: [...VERSIONING_BEHAVIORS] },
638
+ retry: { $ref: "#/$defs/runRetryPolicy" }
521
639
  }
522
640
  },
641
+ localActivityRequest: {
642
+ type: "object",
643
+ required: [
644
+ "localActivityId",
645
+ "kind",
646
+ "nodeType",
647
+ "operation",
648
+ "args",
649
+ "retry",
650
+ "startToCloseTimeout",
651
+ "attempt",
652
+ "backoffMs"
653
+ ],
654
+ description: "R2: a local activity the task needs (11 \xA72.12). Run attempt `attempt` after waiting backoffMs, then run the same task again with the outcome in localActivityResults.",
655
+ properties: {
656
+ localActivityId: ID,
657
+ kind: { const: "node" },
658
+ nodeType: ID,
659
+ nodeVersion: { type: "string" },
660
+ operation: ID,
661
+ args: {},
662
+ connection: ID,
663
+ retry: { $ref: "#/$defs/retryPolicy" },
664
+ startToCloseTimeout: {
665
+ type: "integer",
666
+ minimum: 1,
667
+ maximum: LOCAL_ACTIVITY_MAX_TIMEOUT_MS
668
+ },
669
+ attempt: { type: "integer", minimum: 1 },
670
+ backoffMs: NON_NEGATIVE_MS,
671
+ summary: { type: "string", maxLength: 200 }
672
+ },
673
+ additionalProperties: false
674
+ },
523
675
  request: {
524
676
  type: "object",
525
677
  required: ["protocol", "kind", "workflowFn", "info", "history", "nowMs"],
@@ -564,7 +716,24 @@ var WORKFLOW_TASK_SCHEMA = {
564
716
  protocol: { const: HISTORY_PROTOCOL },
565
717
  outcome: { enum: ["commands", "failed", "localActivityRequested"] },
566
718
  commands: { type: "array", items: { $ref: "#/$defs/command" } },
567
- localActivityRequests: { type: "array", items: { type: "object" } },
719
+ localActivityRequests: {
720
+ type: "array",
721
+ items: { $ref: "#/$defs/localActivityRequest" }
722
+ },
723
+ unfinishedHandlers: {
724
+ type: "array",
725
+ description: "R2: handlers still running when the terminal command was issued (11 \xA72.18); never set on replay.",
726
+ items: {
727
+ type: "object",
728
+ required: ["kind", "name", "count"],
729
+ properties: {
730
+ kind: { enum: ["signal", "update"] },
731
+ name: { type: "string" },
732
+ count: { type: "integer", minimum: 1 }
733
+ },
734
+ additionalProperties: false
735
+ }
736
+ },
568
737
  queryResults: {
569
738
  type: "array",
570
739
  items: {
@@ -727,12 +896,12 @@ function validateCommands(commands, options = {}) {
727
896
  return;
728
897
  }
729
898
  const command2 = checked.command;
730
- if (!isWorkflowCommandEnabled(command2, options.enabled)) {
899
+ if (!isWorkflowCommandEnabled(command2, options.enabled) && !(options.relief !== void 0 && isReliefCommand(command2, options.relief))) {
731
900
  unsupported = true;
732
901
  issues.push({
733
902
  index,
734
903
  code: "commands.unsupported",
735
- message: `${command2.type} is not supported in this release`
904
+ message: unsupportedMessage(command2, options.enabled)
736
905
  });
737
906
  }
738
907
  const id = idOf(command2);
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var chunkFR7KYWRO_cjs = require('./chunk-FR7KYWRO.cjs');
4
-
5
3
  // src/durable/definitions.ts
6
4
  function checkName(name, what) {
7
5
  if (typeof name !== "string" || name === "" || name.startsWith("__"))
@@ -234,16 +232,6 @@ function failureToError(failure, depth = 0) {
234
232
  return error;
235
233
  }
236
234
 
237
- // src/durable/durations.ts
238
- function toMs(value, what = "duration") {
239
- const ms = chunkFR7KYWRO_cjs.durationMs(value, "ms");
240
- if (ms === void 0) throw new TypeError(`${what} "${String(value)}" is not a duration`);
241
- return Math.round(ms);
242
- }
243
- function optionalMs(value, what) {
244
- return value === void 0 ? void 0 : toMs(value, what);
245
- }
246
-
247
235
  exports.ActivityFailure = ActivityFailure;
248
236
  exports.ApplicationError = ApplicationError;
249
237
  exports.CancelledFailure = CancelledFailure;
@@ -262,6 +250,4 @@ exports.errorToFailure = errorToFailure;
262
250
  exports.failureToError = failureToError;
263
251
  exports.isCancellation = isCancellation;
264
252
  exports.isRunFailure = isRunFailure;
265
- exports.optionalMs = optionalMs;
266
253
  exports.signalName = signalName;
267
- exports.toMs = toMs;
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunk623FVQSN_cjs = require('./chunk-623FVQSN.cjs');
3
+ var chunk3FIDHONL_cjs = require('./chunk-3FIDHONL.cjs');
4
4
 
5
5
  function failedTaskResult(cause, message) {
6
6
  return {
7
- protocol: chunk623FVQSN_cjs.HISTORY_PROTOCOL,
7
+ protocol: chunk3FIDHONL_cjs.HISTORY_PROTOCOL,
8
8
  outcome: "failed",
9
9
  commands: [],
10
10
  failure: { cause, message },
@@ -2,7 +2,7 @@ import { autoLayout } from './chunk-5LUIDMF4.js';
2
2
  import { makeRef, isPredicate, conditionTreeOf, BuilderError, refModelOf } from './chunk-JZ4TOOLN.js';
3
3
  import { formatRefTemplate } from './chunk-7AAZGVKD.js';
4
4
  import { isRecord, setOwn, cloneJson, ownValue } from './chunk-PMCM2OH4.js';
5
- import { isDurableWorkflow, SDK_VERSION } from './chunk-N23SKIG4.js';
5
+ import { isDurableWorkflow, SDK_VERSION } from './chunk-7ILGCUI6.js';
6
6
 
7
7
  // src/builder/descriptors.ts
8
8
  function op(nodeType, version, operation) {
@@ -1,15 +1,140 @@
1
- import { PHASE_C_COMMANDS, PHASE_B_CORE_COMMANDS, PHASE_B_PARITY_COMMANDS, TERMINAL_COMMANDS, isInputEvent, isCommandEvent } from './chunk-DJYMDLV5.js';
2
- import { isActivityNodeTypeAllowed } from './chunk-BO6OVILK.js';
1
+ import { PHASE_C_COMMANDS, PHASE_B_CORE_COMMANDS, PHASE_B_PARITY_COMMANDS, TERMINAL_COMMANDS, isActivityNodeTypeAllowed, isInputEvent, isCommandEvent } from './chunk-2DDULZFM.js';
3
2
 
4
3
  // src/history/commands.ts
4
+ var COMMAND_FEATURES = [
5
+ "core",
6
+ "parity.can",
7
+ "parity.context",
8
+ "parity.localActivity",
9
+ "parity.externalCancel",
10
+ "parity.childOptions",
11
+ "parity.canOptions",
12
+ "parity.workflowIdTarget",
13
+ "c.updates",
14
+ "c.searchAttributes",
15
+ "c.userActivity"
16
+ ];
17
+ var PHASE_B_CORE_FEATURES = /* @__PURE__ */ new Set([
18
+ "core",
19
+ "parity.can",
20
+ "parity.context"
21
+ ]);
22
+ var PHASE_B_PARITY_FEATURES = /* @__PURE__ */ new Set([
23
+ "core",
24
+ "parity.can",
25
+ "parity.context",
26
+ "parity.localActivity",
27
+ "parity.externalCancel",
28
+ "parity.childOptions",
29
+ "parity.canOptions",
30
+ "parity.workflowIdTarget"
31
+ ]);
32
+ var CORE_CHILD_OPTIONS = /* @__PURE__ */ new Set([
33
+ "parentClosePolicy",
34
+ "cancellationType",
35
+ "taskQueue",
36
+ "workflowId",
37
+ "priority",
38
+ "summary",
39
+ "details",
40
+ "context",
41
+ "startDelay",
42
+ "executionTimeout",
43
+ "runTimeout",
44
+ "workflowTaskTimeout"
45
+ ]);
46
+ var CORE_CAN_OPTIONS = /* @__PURE__ */ new Set([
47
+ "taskQueue",
48
+ "retry",
49
+ "workflowTaskTimeout",
50
+ "context",
51
+ "versioningBehavior"
52
+ ]);
53
+ var LEGACY_RETRY_KEYS = ["retryDelay", "maxRetries", "maxDelay"];
54
+ var RUN_RETRY_KEYS = ["initialDelayMs", "maxAttempts", "maxDelayMs"];
55
+ function continueAsNewRetryShape(options) {
56
+ const retry = options["retry"];
57
+ if (retry === void 0) return "none";
58
+ if (typeof retry !== "object" || retry === null || Array.isArray(retry)) return "invalid";
59
+ const keys = Object.keys(retry);
60
+ const run = keys.some((key) => RUN_RETRY_KEYS.includes(key));
61
+ const legacy = keys.some((key) => LEGACY_RETRY_KEYS.includes(key));
62
+ if (run === legacy) return "invalid";
63
+ return run ? "run" : "legacy";
64
+ }
65
+ function hasOtherKeys(value, allowed) {
66
+ return Object.entries(value).some(([key, entry]) => entry !== void 0 && !allowed.has(key));
67
+ }
68
+ function commandFeatures(command) {
69
+ const needed = /* @__PURE__ */ new Set();
70
+ switch (command.type) {
71
+ case "START_CHILD_RUN":
72
+ needed.add("core");
73
+ if (hasOtherKeys(command.options, CORE_CHILD_OPTIONS)) needed.add("parity.childOptions");
74
+ break;
75
+ case "SIGNAL_RUN":
76
+ needed.add("core");
77
+ if ("workflowId" in command.target) needed.add("parity.workflowIdTarget");
78
+ break;
79
+ case "REQUEST_CANCEL_EXTERNAL_RUN":
80
+ if ("childId" in command.target) needed.add("core");
81
+ else needed.add("parity.externalCancel");
82
+ if ("workflowId" in command.target) needed.add("parity.workflowIdTarget");
83
+ break;
84
+ case "CONTINUE_AS_NEW":
85
+ needed.add("parity.can");
86
+ if (hasOtherKeys(command.options, CORE_CAN_OPTIONS) || continueAsNewRetryShape(command.options) === "run")
87
+ needed.add("parity.canOptions");
88
+ break;
89
+ case "UPSERT_CONTEXT":
90
+ needed.add("parity.context");
91
+ break;
92
+ case "RECORD_LOCAL_ACTIVITY":
93
+ needed.add("parity.localActivity");
94
+ break;
95
+ case "UPSERT_SEARCH_ATTRIBUTES":
96
+ needed.add("c.searchAttributes");
97
+ break;
98
+ case "ACCEPT_UPDATE":
99
+ case "REJECT_UPDATE":
100
+ case "COMPLETE_UPDATE":
101
+ needed.add("c.updates");
102
+ break;
103
+ default:
104
+ needed.add("core");
105
+ }
106
+ return COMMAND_FEATURES.filter((feature) => needed.has(feature));
107
+ }
5
108
  function isCommandEnabled(type, enabled = "core") {
6
109
  if (PHASE_C_COMMANDS.has(type)) return false;
7
110
  if (PHASE_B_CORE_COMMANDS.has(type)) return true;
8
111
  return enabled === "parity" && PHASE_B_PARITY_COMMANDS.has(type);
9
112
  }
10
113
  function isWorkflowCommandEnabled(command, enabled = "core") {
11
- if (command.type === "REQUEST_CANCEL_EXTERNAL_RUN" && "childId" in command.target) return true;
12
- return isCommandEnabled(command.type, enabled);
114
+ if (typeof enabled === "string") {
115
+ if (command.type === "REQUEST_CANCEL_EXTERNAL_RUN" && "childId" in command.target) return true;
116
+ return isCommandEnabled(command.type, enabled);
117
+ }
118
+ return commandFeatures(command).every((feature) => enabled.has(feature));
119
+ }
120
+ function unsupportedMessage(command, enabled = "core") {
121
+ if (typeof enabled === "string") return `${command.type} is not supported in this release`;
122
+ const missing = commandFeatures(command).filter((feature) => !enabled.has(feature));
123
+ const parity = missing.filter((feature) => feature.startsWith("parity."));
124
+ const flag = parity.length > 0 ? " (needs the fluidgrids.durable-parity flag)" : "";
125
+ return `${command.type} needs ${missing.join(", ")}, which this workspace does not enable${flag}`;
126
+ }
127
+ function isReliefCommand(command, lease) {
128
+ switch (command.type) {
129
+ case "RECORD_LOCAL_ACTIVITY":
130
+ return lease.grantedLocalActivityIds.includes(command.localActivityId);
131
+ case "ACCEPT_UPDATE":
132
+ case "REJECT_UPDATE":
133
+ case "COMPLETE_UPDATE":
134
+ return lease.deliveredUpdateIds.includes(command.updateId);
135
+ default:
136
+ return false;
137
+ }
13
138
  }
14
139
 
15
140
  // src/history/activation.ts
@@ -107,6 +232,7 @@ function initialRunState() {
107
232
  timers: {},
108
233
  children: {},
109
234
  externals: {},
235
+ localActivities: {},
110
236
  sideEffects: {},
111
237
  markers: {},
112
238
  signalsReceived: 0,
@@ -346,6 +472,21 @@ function applyEvent(state, event) {
346
472
  case "SIDE_EFFECT_RECORDED":
347
473
  state.sideEffects[str(p, "sideEffectId")] = p["value"] ?? null;
348
474
  break;
475
+ case "LOCAL_ACTIVITY_COMPLETED":
476
+ case "LOCAL_ACTIVITY_FAILED": {
477
+ const id = str(p, "localActivityId");
478
+ if (state.localActivities[id])
479
+ throw new HistoryStateError(`Local activity "${id}" is recorded twice`, event.seq);
480
+ state.localActivities[id] = {
481
+ status: event.type === "LOCAL_ACTIVITY_COMPLETED" ? "COMPLETED" : "FAILED",
482
+ attempts: typeof p["attempts"] === "number" ? p["attempts"] : 1,
483
+ recordedSeq: event.seq,
484
+ ...typeof p["nodeType"] === "string" ? { nodeType: p["nodeType"] } : {},
485
+ ...typeof p["operation"] === "string" ? { operation: p["operation"] } : {},
486
+ ...typeof p["summary"] === "string" ? { summary: p["summary"] } : {}
487
+ };
488
+ break;
489
+ }
349
490
  case "MARKER_RECORDED":
350
491
  state.markers[str(p, "markerId")] = p["data"] ?? null;
351
492
  break;
@@ -421,11 +562,12 @@ function eventsForCommands(state, commands, context) {
421
562
  const children = new Set(Object.keys(state.children));
422
563
  const externals = new Set(Object.keys(state.externals));
423
564
  const sideEffects = new Set(Object.keys(state.sideEffects));
565
+ const localActivities = new Set(Object.keys(state.localActivities));
424
566
  let unsupported = false;
425
567
  commands.forEach((command, index) => {
426
- if (!isWorkflowCommandEnabled(command, context.enabled)) {
568
+ if (!isWorkflowCommandEnabled(command, context.enabled) && !(context.relief !== void 0 && isReliefCommand(command, context.relief))) {
427
569
  unsupported = true;
428
- reject(index, "commands.unsupported", `${command.type} is not supported in this release`);
570
+ reject(index, "commands.unsupported", unsupportedMessage(command, context.enabled));
429
571
  return;
430
572
  }
431
573
  if (TERMINAL_COMMANDS.has(command.type) && index !== commands.length - 1)
@@ -516,6 +658,13 @@ function eventsForCommands(state, commands, context) {
516
658
  events.push({ ...base, type: "CONTEXT_UPSERTED", payload: payloadOf(command) });
517
659
  break;
518
660
  case "RECORD_LOCAL_ACTIVITY":
661
+ if (localActivities.has(command.localActivityId))
662
+ reject(
663
+ index,
664
+ "localActivity.duplicate",
665
+ `Local activity "${command.localActivityId}" is already recorded`
666
+ );
667
+ localActivities.add(command.localActivityId);
519
668
  events.push({
520
669
  ...base,
521
670
  type: command.failure ? "LOCAL_ACTIVITY_FAILED" : "LOCAL_ACTIVITY_COMPLETED",
@@ -559,47 +708,6 @@ function hasUnprocessedInput(history) {
559
708
  return unseenInputs(history).length > 0;
560
709
  }
561
710
 
562
- // src/history/retry.ts
563
- var DEFAULT_ACTIVITY_RETRY = Object.freeze({
564
- retryDelay: 1e3,
565
- backoffMultiplier: 2,
566
- maxDelay: 1e5
567
- });
568
- var FINAL_TIMEOUTS = /* @__PURE__ */ new Set(["SCHEDULE_TO_START", "SCHEDULE_TO_CLOSE"]);
569
- function computeRetryDelay(policy, attempt, failure) {
570
- if (failure?.nonRetryable === true) return { retry: false, reason: "nonRetryable" };
571
- if (failure?.timeoutType !== void 0 && FINAL_TIMEOUTS.has(failure.timeoutType))
572
- return { retry: false, reason: "finalTimeout" };
573
- if (failure?.type !== void 0 && policy.nonRetryableErrorTypes !== void 0 && policy.nonRetryableErrorTypes.includes(failure.type))
574
- return { retry: false, reason: "typeDenied" };
575
- if (failure !== void 0 && policy.retryOnErrorTypes !== void 0 && policy.retryOnErrorTypes.length > 0 && !policy.retryOnErrorTypes.includes(failure.errorType))
576
- return { retry: false, reason: "errorTypeNotListed" };
577
- if (policy.maxRetries !== void 0 && attempt > policy.maxRetries)
578
- return { retry: false, reason: "maxRetries" };
579
- if (failure?.nextRetryDelayMs !== void 0)
580
- return { retry: true, delayMs: Math.max(0, Math.round(failure.nextRetryDelayMs)) };
581
- const base = Math.max(0, policy.retryDelay);
582
- const multiplier = policy.backoffMultiplier ?? 2;
583
- const cap = policy.maxDelay ?? base * 100;
584
- const exponent = Math.max(0, attempt - 1);
585
- const delay = Math.min(base * Math.pow(multiplier, exponent), cap);
586
- return { retry: true, delayMs: Math.round(Number.isFinite(delay) ? delay : cap) };
587
- }
588
- function explicitRetryPolicy(policy) {
589
- const retryDelay = policy?.retryDelay ?? DEFAULT_ACTIVITY_RETRY.retryDelay;
590
- const out = {
591
- retryDelay,
592
- backoffMultiplier: policy?.backoffMultiplier ?? DEFAULT_ACTIVITY_RETRY.backoffMultiplier ?? 2,
593
- maxDelay: policy?.maxDelay ?? (policy?.retryDelay === void 0 ? 1e5 : Math.max(retryDelay, retryDelay * 100))
594
- };
595
- if (policy?.maxRetries !== void 0) out.maxRetries = policy.maxRetries;
596
- if (policy?.retryOnErrorTypes !== void 0)
597
- out.retryOnErrorTypes = [...policy.retryOnErrorTypes];
598
- if (policy?.nonRetryableErrorTypes !== void 0)
599
- out.nonRetryableErrorTypes = [...policy.nonRetryableErrorTypes];
600
- return out;
601
- }
602
-
603
711
  // src/history/defaults.ts
604
712
  function codeWorkflowParentClosePolicy(state) {
605
713
  const policy = state.parentClosePolicy;
@@ -609,4 +717,4 @@ function codeWorkflowParentClosePolicy(state) {
609
717
  var CHILD_DEFAULT_PARENT_CLOSE_POLICY = Object.freeze({ child: "TERMINATE", startChild: "ABANDON" });
610
718
  var CHILD_DEFAULT_CANCELLATION_TYPE = "WAIT_CANCELLATION_COMPLETED";
611
719
 
612
- export { CHILD_DEFAULT_CANCELLATION_TYPE, CHILD_DEFAULT_PARENT_CLOSE_POLICY, DEFAULT_ACTIVITY_RETRY, HistoryStateError, applyEvent, codeWorkflowParentClosePolicy, computeRetryDelay, eventsForCommands, explicitRetryPolicy, hasUnprocessedInput, initialRunState, isActivityOpen, isChildOpen, isCommandEnabled, isWorkflowCommandEnabled, pendingCounts, projectRunState, splitActivations, taskCompletedEvents, unseenInputs, utf8Bytes };
720
+ export { CHILD_DEFAULT_CANCELLATION_TYPE, CHILD_DEFAULT_PARENT_CLOSE_POLICY, COMMAND_FEATURES, CORE_CAN_OPTIONS, CORE_CHILD_OPTIONS, HistoryStateError, PHASE_B_CORE_FEATURES, PHASE_B_PARITY_FEATURES, applyEvent, codeWorkflowParentClosePolicy, commandFeatures, continueAsNewRetryShape, eventsForCommands, hasUnprocessedInput, initialRunState, isActivityOpen, isChildOpen, isCommandEnabled, isReliefCommand, isWorkflowCommandEnabled, pendingCounts, projectRunState, splitActivations, taskCompletedEvents, unseenInputs, unsupportedMessage, utf8Bytes };