@fluidgrids/workflows 2026.1029.1 → 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 (118) hide show
  1. package/README.md +112 -4
  2. package/dist/{activation-CESehfYi.d.cts → activation-DqUfpHzk.d.cts} +1 -1
  3. package/dist/{activation-BnVQMv9y.d.ts → activation-xpx1oWuo.d.ts} +1 -1
  4. package/dist/{chunk-MJ5TGYVG.js → chunk-2D3MYIIF.js} +969 -153
  5. package/dist/{chunk-2B37XAFQ.cjs → chunk-3U2NU7YC.cjs} +24 -11
  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-2DDULZFM.js → chunk-5HIVIV53.js} +86 -75
  9. package/dist/chunk-5MFVJM76.js +1222 -0
  10. package/dist/{chunk-EWYADREB.cjs → chunk-672KMMBK.cjs} +2 -2
  11. package/dist/{chunk-KXJDRQ6G.js → chunk-6A2FGSUS.js} +22 -2
  12. package/dist/{chunk-OIX4O6UR.js → chunk-6OLN6BMB.js} +16 -3
  13. package/dist/{chunk-6FSHT5IL.js → chunk-7EZIANC7.js} +1 -1
  14. package/dist/chunk-A5SXCA62.cjs +93 -0
  15. package/dist/chunk-AC6ZEXVR.js +85 -0
  16. package/dist/{chunk-FWBRQWRX.js → chunk-AE5Q6ZAJ.js} +167 -10
  17. package/dist/{chunk-7ILGCUI6.js → chunk-C4F5KJTI.js} +142 -3
  18. package/dist/{chunk-WXXNCHUY.js → chunk-G5H32GIG.js} +1 -1
  19. package/dist/{chunk-OMY3CKUZ.cjs → chunk-GEQDGUGB.cjs} +1042 -226
  20. package/dist/{chunk-25BKWR2O.js → chunk-HCM7ZC7Q.js} +1 -1
  21. package/dist/{chunk-I47EENR4.cjs → chunk-HMZUGSMU.cjs} +673 -156
  22. package/dist/{chunk-NXFBVDOI.cjs → chunk-IQPXHQQQ.cjs} +8 -4
  23. package/dist/{chunk-RUQIMTN5.cjs → chunk-ISOIA7NV.cjs} +178 -15
  24. package/dist/chunk-JSC75O5C.cjs +167 -0
  25. package/dist/{chunk-BD7ZPG53.js → chunk-NWQ5WRLE.js} +10 -2
  26. package/dist/chunk-ODZ2IAR2.cjs +1247 -0
  27. package/dist/{chunk-FQSJI5NV.js → chunk-SR7TR5KX.js} +6 -2
  28. package/dist/{chunk-OKX3FYIM.cjs → chunk-TCTE7DX5.cjs} +3 -3
  29. package/dist/{chunk-3FIDHONL.cjs → chunk-TYF56RGB.cjs} +99 -80
  30. package/dist/{chunk-J3PYFGKA.cjs → chunk-VA4OFR72.cjs} +162 -4
  31. package/dist/chunk-VU5S5A7V.js +150 -0
  32. package/dist/{chunk-A36CCOWS.js → chunk-YEHR4NNE.js} +633 -128
  33. package/dist/{chunk-ELL2RBML.cjs → chunk-ZCGKGDCL.cjs} +23 -1
  34. package/dist/codegen/index.d.cts +2 -2
  35. package/dist/codegen/index.d.ts +2 -2
  36. package/dist/{collect-BTHjQaSp.d.ts → collect-6NIEufHd.d.ts} +20 -3
  37. package/dist/{collect-CSyOg5XC.d.cts → collect-CcTCKqx6.d.cts} +20 -3
  38. package/dist/{file-cgL9l9l8.d.cts → file-BxYpwjRQ.d.cts} +250 -15
  39. package/dist/{file-olQudcx5.d.ts → file-CFdPQJI9.d.ts} +250 -15
  40. package/dist/history/index.cjs +283 -106
  41. package/dist/history/index.d.cts +549 -10
  42. package/dist/history/index.d.ts +549 -10
  43. package/dist/history/index.js +5 -4
  44. package/dist/index.cjs +146 -53
  45. package/dist/index.d.cts +38 -14
  46. package/dist/index.d.ts +38 -14
  47. package/dist/index.js +6 -5
  48. package/dist/interceptors-CNcr2dlk.d.ts +159 -0
  49. package/dist/interceptors-CqkNZVfI.d.cts +159 -0
  50. package/dist/ir/index.cjs +339 -36
  51. package/dist/ir/index.d.cts +244 -8
  52. package/dist/ir/index.d.ts +244 -8
  53. package/dist/ir/index.js +306 -21
  54. package/dist/{lower-3S6PsqjJ.d.cts → lower-BtRfIW2A.d.cts} +23 -9
  55. package/dist/{lower-DmZpQ8hJ.d.ts → lower-CpsMFOFX.d.ts} +23 -9
  56. package/dist/{manifest-BJjrQt77.d.ts → manifest-D-I_twys.d.ts} +1 -1
  57. package/dist/{manifest-gRI2Q5Fj.d.cts → manifest-DahBQVM8.d.cts} +1 -1
  58. package/dist/node-evaluator-DGQDPSPI.cjs +24 -0
  59. package/dist/node-evaluator-LEEVD7H7.js +14 -0
  60. package/dist/payload-fields-BVRQn2yH.d.cts +122 -0
  61. package/dist/payload-fields-oOBWxDiG.d.ts +122 -0
  62. package/dist/quickjs/index.cjs +27 -27
  63. package/dist/quickjs/index.d.cts +6 -6
  64. package/dist/quickjs/index.d.ts +6 -6
  65. package/dist/quickjs/index.js +9 -9
  66. package/dist/roundtrip/index.cjs +72 -66
  67. package/dist/roundtrip/index.d.cts +25 -11
  68. package/dist/roundtrip/index.d.ts +25 -11
  69. package/dist/roundtrip/index.js +13 -11
  70. package/dist/runtime/index.cjs +19 -19
  71. package/dist/runtime/index.d.cts +139 -12
  72. package/dist/runtime/index.d.ts +139 -12
  73. package/dist/runtime/index.js +6 -6
  74. package/dist/testing/index.cjs +688 -121
  75. package/dist/testing/index.d.cts +174 -10
  76. package/dist/testing/index.d.ts +174 -10
  77. package/dist/testing/index.js +646 -82
  78. package/dist/{types-CnIOinoz.d.ts → types-Bv2i4cBX.d.cts} +126 -23
  79. package/dist/{types-CQKOhPTa.d.cts → types-DGx-b9eq.d.ts} +126 -23
  80. package/dist/{types-Bb2wRnJ5.d.cts → types-V7jEEUaL.d.cts} +1 -1
  81. package/dist/{types-Bb2wRnJ5.d.ts → types-V7jEEUaL.d.ts} +1 -1
  82. package/dist/{workflow-8uRU9rhL.d.ts → workflow-B18OeF7g.d.ts} +2 -2
  83. package/dist/{workflow-DWTPHFbt.d.ts → workflow-BGnv8SS6.d.ts} +261 -14
  84. package/dist/{workflow-CZOXUlQ5.d.cts → workflow-BJPFv3cp.d.cts} +2 -2
  85. package/dist/{workflow-O6e64ZcG.d.cts → workflow-DS32Gtws.d.cts} +261 -14
  86. package/fixtures/histories/activity-options-updated.history.json +159 -0
  87. package/fixtures/histories/activity-paused-unpaused.history.json +160 -0
  88. package/fixtures/histories/codec-opaque.history.json +229 -0
  89. package/fixtures/histories/dynamic-workflow.history.json +150 -0
  90. package/fixtures/histories/interceptor-headers.history.json +339 -0
  91. package/fixtures/histories/query-custom.history.json +213 -0
  92. package/fixtures/histories/query-default-handler.history.json +120 -0
  93. package/fixtures/histories/reset-forked-reapplied-signals.history.json +239 -0
  94. package/fixtures/histories/reset-reapplied-update-admitted.history.json +228 -0
  95. package/fixtures/histories/search-attributes-upserted.history.json +177 -0
  96. package/fixtures/histories/update-accepted-completed.history.json +45 -30
  97. package/fixtures/histories/update-default-handler.history.json +246 -0
  98. package/fixtures/histories/update-handler-awaits-activity.history.json +196 -0
  99. package/fixtures/histories/update-not-handled.history.json +138 -0
  100. package/fixtures/histories/update-rejected-no-event.history.json +190 -0
  101. package/fixtures/histories/update-with-start-admitted.history.json +150 -0
  102. package/fixtures/histories/user-activity-cancel.history.json +149 -0
  103. package/fixtures/histories/user-activity-retry.history.json +143 -0
  104. package/fixtures/histories/user-activity.history.json +149 -0
  105. package/package.json +1 -1
  106. package/schema/bridge-v2.schema.json +1062 -0
  107. package/schema/history-file.schema.json +255 -81
  108. package/schema/ir-v2.schema.json +246 -1
  109. package/schema/payload-fields.json +162 -0
  110. package/schema/run-event.schema.json +239 -80
  111. package/schema/workflow-command.schema.json +210 -84
  112. package/schema/workflow-task.schema.json +532 -167
  113. package/dist/chunk-6QPOJZT6.cjs +0 -1180
  114. package/dist/chunk-A2OHX3UQ.js +0 -1156
  115. package/dist/chunk-PWIUEWC3.js +0 -81
  116. package/dist/chunk-YHBVMOMK.cjs +0 -87
  117. package/dist/node-evaluator-SOADN23V.js +0 -14
  118. package/dist/node-evaluator-YGDEXK4U.cjs +0 -24
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunkELL2RBML_cjs = require('./chunk-ELL2RBML.cjs');
3
+ var chunkZCGKGDCL_cjs = require('./chunk-ZCGKGDCL.cjs');
4
4
  var chunkQ4MWQNJK_cjs = require('./chunk-Q4MWQNJK.cjs');
5
5
  var chunkL24YIZY7_cjs = require('./chunk-L24YIZY7.cjs');
6
- var chunkJ3PYFGKA_cjs = require('./chunk-J3PYFGKA.cjs');
7
- var chunkRUQIMTN5_cjs = require('./chunk-RUQIMTN5.cjs');
8
- var chunk3FIDHONL_cjs = require('./chunk-3FIDHONL.cjs');
9
- var chunkYHBVMOMK_cjs = require('./chunk-YHBVMOMK.cjs');
6
+ var chunkVA4OFR72_cjs = require('./chunk-VA4OFR72.cjs');
7
+ var chunkISOIA7NV_cjs = require('./chunk-ISOIA7NV.cjs');
8
+ var chunkA5SXCA62_cjs = require('./chunk-A5SXCA62.cjs');
9
+ var chunkTYF56RGB_cjs = require('./chunk-TYF56RGB.cjs');
10
10
 
11
11
  // src/runtime/ids.ts
12
12
  var CommandIds = class {
@@ -39,7 +39,7 @@ function field(event, key) {
39
39
  function describeCommand(command) {
40
40
  switch (command.type) {
41
41
  case "SCHEDULE_ACTIVITY":
42
- return `SCHEDULE_ACTIVITY ${command.activityId} (${command.nodeType} ${command.operation})`;
42
+ return command.kind === "user" ? `SCHEDULE_ACTIVITY ${command.activityId} (user ${command.activityName})` : `SCHEDULE_ACTIVITY ${command.activityId} (${command.nodeType} ${command.operation})`;
43
43
  case "REQUEST_CANCEL_ACTIVITY":
44
44
  return `REQUEST_CANCEL_ACTIVITY ${command.activityId}`;
45
45
  case "START_TIMER":
@@ -57,22 +57,31 @@ function describeCommand(command) {
57
57
  return `RECORD_MARKER ${command.markerId}`;
58
58
  case "RECORD_LOCAL_ACTIVITY":
59
59
  return `RECORD_LOCAL_ACTIVITY ${command.localActivityId}${command.nodeType !== void 0 ? ` (${command.nodeType} ${command.operation ?? ""})` : ""}`;
60
+ case "ACCEPT_UPDATE":
61
+ case "REJECT_UPDATE":
62
+ case "COMPLETE_UPDATE":
63
+ return `${command.type} ${command.updateId}`;
60
64
  default:
61
65
  return command.type;
62
66
  }
63
67
  }
64
68
  function describeEvent(event) {
65
- const id = field(event, "activityId") ?? field(event, "timerId") ?? field(event, "childId") ?? field(event, "externalId") ?? field(event, "sideEffectId") ?? field(event, "markerId") ?? field(event, "localActivityId");
69
+ const id = field(event, "activityId") ?? field(event, "timerId") ?? field(event, "childId") ?? field(event, "externalId") ?? field(event, "sideEffectId") ?? field(event, "markerId") ?? field(event, "localActivityId") ?? field(event, "updateId");
66
70
  return `${event.type}${typeof id === "string" ? ` ${id}` : ""} (seq ${event.seq})`;
67
71
  }
68
72
  function mismatch(command, event) {
69
- const expected = chunk3FIDHONL_cjs.COMMAND_EVENT_TYPES[command.type];
73
+ const expected = chunkTYF56RGB_cjs.COMMAND_EVENT_TYPES[command.type];
70
74
  const typeOk = command.type === "RECORD_LOCAL_ACTIVITY" ? event.type === "LOCAL_ACTIVITY_COMPLETED" || event.type === "LOCAL_ACTIVITY_FAILED" : event.type === expected;
71
75
  const differ = () => `the code issued ${describeCommand(command)} where the history has ${describeEvent(event)}`;
72
76
  if (!typeOk) return differ();
73
77
  switch (command.type) {
74
- case "SCHEDULE_ACTIVITY":
75
- return field(event, "activityId") === command.activityId && field(event, "nodeType") === command.nodeType && field(event, "operation") === command.operation ? void 0 : differ();
78
+ case "SCHEDULE_ACTIVITY": {
79
+ if (field(event, "activityId") !== command.activityId) return differ();
80
+ const kind = field(event, "kind") ?? "node";
81
+ if (command.kind === "user")
82
+ return kind === "user" && field(event, "activityName") === command.activityName ? void 0 : differ();
83
+ return kind === "node" && field(event, "nodeType") === command.nodeType && field(event, "operation") === command.operation ? void 0 : differ();
84
+ }
76
85
  case "REQUEST_CANCEL_ACTIVITY":
77
86
  return field(event, "activityId") === command.activityId ? void 0 : differ();
78
87
  case "START_TIMER":
@@ -88,6 +97,9 @@ function mismatch(command, event) {
88
97
  return field(event, "sideEffectId") === command.sideEffectId ? void 0 : differ();
89
98
  case "RECORD_MARKER":
90
99
  return field(event, "markerId") === command.markerId ? void 0 : differ();
100
+ case "ACCEPT_UPDATE":
101
+ case "COMPLETE_UPDATE":
102
+ return field(event, "updateId") === command.updateId ? void 0 : differ();
91
103
  case "RECORD_LOCAL_ACTIVITY": {
92
104
  const sameOperation = field(event, "nodeType") === void 0 || field(event, "nodeType") === command.nodeType && field(event, "operation") === command.operation;
93
105
  return field(event, "localActivityId") === command.localActivityId && sameOperation ? void 0 : differ();
@@ -103,6 +115,7 @@ function isSkippablePatch(event) {
103
115
  function matchActivation(commands, recorded) {
104
116
  let position = 0;
105
117
  for (const command of commands) {
118
+ if (chunkTYF56RGB_cjs.COMMAND_EVENT_TYPES[command.type] === null) continue;
106
119
  let event = recorded[position];
107
120
  while (event !== void 0 && isSkippablePatch(event) && !(command.type === "RECORD_MARKER" && command.markerId === field(event, "markerId"))) {
108
121
  position += 1;
@@ -128,15 +141,35 @@ function matchActivation(commands, recorded) {
128
141
  }
129
142
 
130
143
  // src/runtime/scheduler.ts
144
+ var COMMAND_ID_CALLS = {
145
+ a: "Scheduling an activity",
146
+ t: "Starting a timer",
147
+ c: "Starting a child run",
148
+ s: "ctx.sideEffect()",
149
+ x: "Signalling or cancelling another run",
150
+ m: "ctx.setCurrentDetails()",
151
+ l: "Running a local activity"
152
+ };
153
+ function isBuiltInQuery(name) {
154
+ return chunkTYF56RGB_cjs.BUILT_IN_QUERIES.includes(name);
155
+ }
131
156
  var SDK_NAME = "@fluidgrids/workflows";
132
157
  var ContinueAsNewRequest = class {
133
- constructor(input, options) {
158
+ constructor(input, options, headers = {}) {
134
159
  this.input = input;
135
160
  this.options = options;
161
+ this.headers = headers;
136
162
  }
137
163
  input;
138
164
  options;
165
+ headers;
139
166
  };
167
+ function checkPolicy(policy) {
168
+ const value = policy ?? "WARN_AND_ABANDON";
169
+ if (value !== "WARN_AND_ABANDON" && value !== "ABANDON")
170
+ throw new TypeError("unfinishedPolicy must be WARN_AND_ABANDON or ABANDON");
171
+ return value;
172
+ }
140
173
  var TaskFailure = class {
141
174
  constructor(cause, message, stackTrace, seq, errorType) {
142
175
  this.cause = cause;
@@ -187,7 +220,7 @@ var Scope = class {
187
220
  cancel() {
188
221
  if (this.consideredCancelled) return;
189
222
  this.consideredCancelled = true;
190
- this.rejectRequested(new chunkELL2RBML_cjs.CancelledFailure("Cancellation requested"));
223
+ this.rejectRequested(new chunkZCGKGDCL_cjs.CancelledFailure("Cancellation requested"));
191
224
  const errors = [];
192
225
  const handlers = [...this.handlers];
193
226
  this.handlers.clear();
@@ -211,6 +244,32 @@ var Scope = class {
211
244
  this.parent?.children.delete(this);
212
245
  }
213
246
  };
247
+ function checkHandlerName(name, what) {
248
+ if (typeof name !== "string" || name === "" || name.startsWith("__"))
249
+ throw new TypeError(`${what} needs a name that does not start with "__"`);
250
+ return name;
251
+ }
252
+ function definitionName(value, what) {
253
+ return checkHandlerName(typeof value === "string" ? value : value?.name, what);
254
+ }
255
+ function isHeaders(value) {
256
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
257
+ }
258
+ function headersOf(value) {
259
+ return isHeaders(value) ? { ...value } : {};
260
+ }
261
+ function checkFairness(options) {
262
+ const key = options.fairnessKey;
263
+ if (key !== void 0 && (typeof key !== "string" || key === "" || key.length > chunkTYF56RGB_cjs.FAIRNESS_KEY_MAX_LENGTH))
264
+ throw new TypeError(
265
+ `fairnessKey must be a string of 1 to ${chunkTYF56RGB_cjs.FAIRNESS_KEY_MAX_LENGTH} characters`
266
+ );
267
+ const weight = options.fairnessWeight;
268
+ if (weight !== void 0 && (typeof weight !== "number" || !Number.isFinite(weight) || weight < chunkTYF56RGB_cjs.FAIRNESS_WEIGHT_MIN || weight > chunkTYF56RGB_cjs.FAIRNESS_WEIGHT_MAX))
269
+ throw new TypeError(
270
+ `fairnessWeight must be a number from ${chunkTYF56RGB_cjs.FAIRNESS_WEIGHT_MIN} to ${chunkTYF56RGB_cjs.FAIRNESS_WEIGHT_MAX}`
271
+ );
272
+ }
214
273
  function toJson(value, what) {
215
274
  if (value === void 0) return null;
216
275
  if (typeof value === "function" || typeof value === "symbol")
@@ -279,6 +338,11 @@ function infoFromStarted(info, started) {
279
338
  if (typeof p["priority"] === "number") out.priority = p["priority"];
280
339
  if (typeof p["firstRunId"] === "string") out.firstRunId = p["firstRunId"];
281
340
  if (typeof p["continuedFromRunId"] === "string") out.continuedFromRunId = p["continuedFromRunId"];
341
+ if (isHeaders(p["headers"])) out.headers = { ...p["headers"] };
342
+ if (isJsonObject(p["searchAttributes"]))
343
+ out.searchAttributes = chunkISOIA7NV_cjs.mergeSearchAttributes({}, p["searchAttributes"]);
344
+ if (typeof p["fairnessKey"] === "string") out.fairnessKey = p["fairnessKey"];
345
+ if (typeof p["fairnessWeight"] === "number") out.fairnessWeight = p["fairnessWeight"];
282
346
  if (out.workflowId === void 0 && out.businessId !== void 0) out.workflowId = out.businessId;
283
347
  if (out.runAttempt === void 0 && out.attempt !== void 0) out.runAttempt = out.attempt;
284
348
  return out;
@@ -293,7 +357,7 @@ var WorkflowExecution = class {
293
357
  activationOpen = false;
294
358
  replaying = false;
295
359
  clock = 0;
296
- random;
360
+ randomSource;
297
361
  ids = new CommandIds();
298
362
  commands = [];
299
363
  newCommands = [];
@@ -338,6 +402,24 @@ var WorkflowExecution = class {
338
402
  /** Running asynchronous handlers by name, for the drain warning (11 §2.18). */
339
403
  running = /* @__PURE__ */ new Map();
340
404
  unfinished;
405
+ /** Updates delivered so far, by id (an update is delivered at most once per task). */
406
+ deliveredUpdates = /* @__PURE__ */ new Set();
407
+ /** Updates delivered in the current activation without a handler yet. */
408
+ bufferedUpdates = [];
409
+ updateHandlers = /* @__PURE__ */ new Map();
410
+ defaultUpdateHandler;
411
+ queryHandlers = /* @__PURE__ */ new Map();
412
+ defaultQueryHandler;
413
+ /** Set while a query handler or an update validator runs: commands and sinks throw. */
414
+ readOnly;
415
+ /** The first state-changing call a read-only handler made, even when it caught the error. */
416
+ readOnlyViolation;
417
+ searchAttributes;
418
+ startHeaders;
419
+ inbound;
420
+ outbound;
421
+ sinkCalls = [];
422
+ sinkCallsDropped = false;
341
423
  recordedLocalActivities = /* @__PURE__ */ new Map();
342
424
  localActivityResults = /* @__PURE__ */ new Map();
343
425
  localActivities = /* @__PURE__ */ new Map();
@@ -355,16 +437,16 @@ var WorkflowExecution = class {
355
437
  this.bytesUpTo = [0];
356
438
  let bytes = 0;
357
439
  for (const event of history) {
358
- bytes += chunkRUQIMTN5_cjs.utf8Bytes(JSON.stringify(event.payload));
440
+ bytes += chunkISOIA7NV_cjs.utf8Bytes(JSON.stringify(event.payload));
359
441
  this.bytesUpTo.push(bytes);
360
442
  }
361
443
  this.historyLength = history.length;
362
444
  this.historyBytes = bytes;
363
- const limit = input.request.info.historyLimit ?? chunk3FIDHONL_cjs.DEFAULT_HISTORY_LIMIT;
445
+ const limit = input.request.info.historyLimit ?? chunkTYF56RGB_cjs.DEFAULT_HISTORY_LIMIT;
364
446
  this.limitEvents = limit.events;
365
447
  this.limitBytes = limit.bytes;
366
448
  this.captureStacks = input.request.kind === "query";
367
- this.random = chunkL24YIZY7_cjs.createRandom(chunkL24YIZY7_cjs.seedOf(randomnessSeedOf(input.request)));
449
+ this.randomSource = chunkL24YIZY7_cjs.createRandom(chunkL24YIZY7_cjs.seedOf(randomnessSeedOf(input.request)));
368
450
  for (const event of history) {
369
451
  if (event.type === "SIDE_EFFECT_RECORDED") {
370
452
  const id = event.payload["sideEffectId"];
@@ -390,7 +472,7 @@ var WorkflowExecution = class {
390
472
  ...entry.failure !== void 0 ? { failure: entry.failure } : { result: entry.result ?? null },
391
473
  attempts: entry.attempts
392
474
  });
393
- this.activations = chunkRUQIMTN5_cjs.splitActivations(
475
+ this.activations = chunkISOIA7NV_cjs.splitActivations(
394
476
  history,
395
477
  input.request.nowMs,
396
478
  input.request.kind !== "query"
@@ -398,6 +480,30 @@ var WorkflowExecution = class {
398
480
  const execution = this;
399
481
  const snapshot = infoFromStarted(input.request.info, history[0]);
400
482
  this.memo = { ...snapshot.memo ?? snapshot.context ?? {} };
483
+ this.searchAttributes = { ...snapshot.searchAttributes ?? {} };
484
+ this.startHeaders = { ...snapshot.headers ?? {} };
485
+ let inbound = [];
486
+ let outbound = [];
487
+ const factories = input.interceptors ?? [];
488
+ if (factories.length > 0 && input.request.kind === "task" && !(input.request.features ?? []).includes("interceptors"))
489
+ this.failTask(
490
+ "UNSUPPORTED_COMMAND",
491
+ "The bundle exports interceptors, which this workspace does not enable (needs the fluidgrids.run-control flag)"
492
+ );
493
+ else
494
+ try {
495
+ const resolved = chunkVA4OFR72_cjs.resolveWorkflowInterceptors(factories);
496
+ inbound = resolved.inbound;
497
+ outbound = resolved.outbound;
498
+ } catch (error) {
499
+ this.failTask(
500
+ "WORKFLOW_CODE_ERROR",
501
+ `The interceptors factory failed: ${messageOf(error)}`,
502
+ stackTextOf(error)
503
+ );
504
+ }
505
+ this.inbound = inbound;
506
+ this.outbound = outbound;
401
507
  this.info = {
402
508
  ...snapshot,
403
509
  workflowFn: input.request.workflowFn,
@@ -407,6 +513,9 @@ var WorkflowExecution = class {
407
513
  get memo() {
408
514
  return { ...execution.memo };
409
515
  },
516
+ get searchAttributes() {
517
+ return { ...execution.searchAttributes };
518
+ },
410
519
  get historyLength() {
411
520
  return execution.historyLength;
412
521
  },
@@ -423,15 +532,39 @@ var WorkflowExecution = class {
423
532
  this.context = this.contextFor(void 0);
424
533
  }
425
534
  continueAsNewSuggested() {
426
- return this.historyLength >= this.limitEvents * chunk3FIDHONL_cjs.CONTINUE_AS_NEW_SUGGESTED_RATIO || this.historyBytes >= this.limitBytes * chunk3FIDHONL_cjs.CONTINUE_AS_NEW_SUGGESTED_RATIO;
535
+ return this.historyLength >= this.limitEvents * chunkTYF56RGB_cjs.CONTINUE_AS_NEW_SUGGESTED_RATIO || this.historyBytes >= this.limitBytes * chunkTYF56RGB_cjs.CONTINUE_AS_NEW_SUGGESTED_RATIO;
427
536
  }
428
537
  /** The workflow clock. */
429
538
  now() {
430
539
  return this.clock;
431
540
  }
432
- /** The next deterministic random number. */
541
+ /** The next deterministic random number (`Math.random()` and `crypto.getRandomValues()`). */
433
542
  nextRandom() {
434
- return this.random();
543
+ this.assertWritable("Math.random() or crypto.getRandomValues()");
544
+ return this.randomSource();
545
+ }
546
+ /** `ctx.random()`: advances the run's random source, so read-only handlers may not call it. */
547
+ random() {
548
+ this.assertWritable("ctx.random()");
549
+ return this.randomSource();
550
+ }
551
+ /**
552
+ * Throw `QueryHandlerSideEffect` when a query handler or an update validator
553
+ * calls something that changes the run's deterministic state (the random
554
+ * source, the command id counters, patches, details). Validators are not run
555
+ * again on replay, and a worker that keeps a run's state between tasks keeps
556
+ * whatever a query handler changed, so either would make the next replay
557
+ * diverge. The violation is remembered, so catching the error does not hide it.
558
+ */
559
+ assertWritable(what) {
560
+ if (this.readOnly === void 0) return;
561
+ this.readOnlyViolation ??= what;
562
+ throw new chunkZCGKGDCL_cjs.QueryHandlerSideEffect(`${what} (in ${this.readOnly})`);
563
+ }
564
+ /** The next command id of a kind; refused in read-only handlers (it advances a counter). */
565
+ nextId(kind) {
566
+ this.assertWritable(COMMAND_ID_CALLS[kind]);
567
+ return this.ids.next(kind);
435
568
  }
436
569
  /** Begin or finish an activation; `done` when there is nothing left to do. */
437
570
  step() {
@@ -456,7 +589,7 @@ var WorkflowExecution = class {
456
589
  const requests = this.pendingLocalActivityRequests();
457
590
  if (requests.length > 0) {
458
591
  const requested = {
459
- protocol: chunk3FIDHONL_cjs.HISTORY_PROTOCOL,
592
+ protocol: chunkTYF56RGB_cjs.HISTORY_PROTOCOL,
460
593
  outcome: "localActivityRequested",
461
594
  commands: [],
462
595
  localActivityRequests: requests,
@@ -465,12 +598,14 @@ var WorkflowExecution = class {
465
598
  return requested;
466
599
  }
467
600
  const result = {
468
- protocol: chunk3FIDHONL_cjs.HISTORY_PROTOCOL,
601
+ protocol: chunkTYF56RGB_cjs.HISTORY_PROTOCOL,
469
602
  outcome: this.failure ? "failed" : "commands",
470
603
  commands: this.failure ? [] : this.newCommands,
471
604
  logs: this.logs
472
605
  };
473
606
  if (!this.failure && this.unfinished !== void 0) result.unfinishedHandlers = this.unfinished;
607
+ if (!this.failure && this.request.kind === "task" && this.sinkCalls.length > 0)
608
+ result.sinkCalls = this.sinkCalls;
474
609
  if (this.failure) {
475
610
  result.failure = { cause: this.failure.cause, message: this.failure.message };
476
611
  if (this.failure.stackTrace !== void 0)
@@ -478,7 +613,8 @@ var WorkflowExecution = class {
478
613
  if (this.failure.seq !== void 0) result.failure.seq = this.failure.seq;
479
614
  if (this.failure.errorType !== void 0) result.failure.errorType = this.failure.errorType;
480
615
  }
481
- if (this.request.kind === "query") result.queryResults = this.answerQueries();
616
+ if (this.request.kind === "query" || (this.request.queries ?? []).length > 0)
617
+ result.queryResults = this.answerQueries();
482
618
  return result;
483
619
  }
484
620
  /**
@@ -505,11 +641,54 @@ var WorkflowExecution = class {
505
641
  if (this.failure) return;
506
642
  this.deliver(event);
507
643
  }
644
+ for (const update of this.updatesOf(activation)) {
645
+ if (this.failure) return;
646
+ this.deliverUpdate(update);
647
+ }
648
+ }
649
+ /**
650
+ * The updates an activation delivers after its inputs (C-ABI-H): a replayed
651
+ * activation re-delivers the updates its task accepted (validators
652
+ * skipped); the open activation of a workflow task delivers the lease's
653
+ * pending updates. Updates history admitted (`UPDATE_ADMITTED`) arrive as
654
+ * inputs instead.
655
+ */
656
+ updatesOf(activation) {
657
+ const out = [];
658
+ if (activation.recorded) {
659
+ for (const event of activation.recorded) {
660
+ if (event.type !== "UPDATE_ACCEPTED") continue;
661
+ const p = event.payload;
662
+ const updateId = typeof p["updateId"] === "string" ? p["updateId"] : "";
663
+ if (this.deliveredUpdates.has(updateId)) continue;
664
+ out.push({
665
+ updateId,
666
+ name: typeof p["name"] === "string" ? p["name"] : "",
667
+ args: p["args"] ?? null,
668
+ headers: headersOf(p["headers"]),
669
+ validate: false
670
+ });
671
+ }
672
+ return out;
673
+ }
674
+ if (this.request.kind === "query") return out;
675
+ for (const update of this.request.updates ?? []) {
676
+ if (update.admitted === true || this.deliveredUpdates.has(update.updateId)) continue;
677
+ out.push({
678
+ updateId: update.updateId,
679
+ name: update.name,
680
+ args: update.args ?? null,
681
+ headers: headersOf(update.headers),
682
+ validate: true
683
+ });
684
+ }
685
+ return out;
508
686
  }
509
687
  finishActivation() {
510
688
  this.activationOpen = false;
511
689
  const activation = this.activations[this.index];
512
690
  if (!activation) return;
691
+ this.rejectUnhandledUpdates();
513
692
  if (activation.recorded) {
514
693
  const found = matchActivation(this.commands, activation.recorded);
515
694
  if (found)
@@ -569,8 +748,20 @@ var WorkflowExecution = class {
569
748
  return;
570
749
  }
571
750
  case "SIGNAL_RECEIVED":
572
- this.dispatchSignal(id("name"), p["payload"] ?? null);
751
+ this.dispatchSignal(id("name"), p["payload"] ?? null, headersOf(p["headers"]));
752
+ return;
753
+ case "UPDATE_ADMITTED": {
754
+ const updateId = id("updateId");
755
+ if (this.deliveredUpdates.has(updateId)) return;
756
+ this.deliverUpdate({
757
+ updateId,
758
+ name: id("name"),
759
+ args: p["args"] ?? null,
760
+ headers: headersOf(p["headers"]),
761
+ validate: true
762
+ });
573
763
  return;
764
+ }
574
765
  case "CHILD_RUN_STARTED":
575
766
  case "CHILD_RUN_COMPLETED":
576
767
  case "CHILD_RUN_FAILED":
@@ -590,7 +781,7 @@ var WorkflowExecution = class {
590
781
  else {
591
782
  const failure = p["failure"];
592
783
  pending.reject(
593
- typeof failure === "object" && failure !== null && !Array.isArray(failure) ? chunkELL2RBML_cjs.failureToError(failure) : new chunkELL2RBML_cjs.ServerFailure(`${pending.description} was not delivered`)
784
+ typeof failure === "object" && failure !== null && !Array.isArray(failure) ? chunkZCGKGDCL_cjs.failureToError(failure) : new chunkZCGKGDCL_cjs.ServerFailure(`${pending.description} was not delivered`)
594
785
  );
595
786
  }
596
787
  return;
@@ -620,12 +811,14 @@ var WorkflowExecution = class {
620
811
  pending.release?.();
621
812
  const p = event.payload;
622
813
  const failure = typeof p["failure"] === "object" && p["failure"] !== null && !Array.isArray(p["failure"]) ? p["failure"] : void 0;
623
- const wrap = (cause) => new chunkELL2RBML_cjs.ActivityFailure(
624
- `Activity ${activityId} (${pending.nodeType} ${pending.operation}) failed: ${cause.message}`,
814
+ const label = pending.activityName !== void 0 ? `user ${pending.activityName}` : `${pending.nodeType} ${pending.operation}`;
815
+ const wrap = (cause) => new chunkZCGKGDCL_cjs.ActivityFailure(
816
+ `Activity ${activityId} (${label}) failed: ${cause.message}`,
625
817
  activityId,
626
818
  pending.nodeType,
627
819
  pending.operation,
628
- cause
820
+ cause,
821
+ pending.activityName
629
822
  );
630
823
  switch (event.type) {
631
824
  case "ACTIVITY_COMPLETED":
@@ -634,19 +827,19 @@ var WorkflowExecution = class {
634
827
  case "ACTIVITY_FAILED":
635
828
  pending.reject(
636
829
  wrap(
637
- failure ? chunkELL2RBML_cjs.failureToError(failure) : new chunkELL2RBML_cjs.ApplicationError("Activity failed", { errorType: "UNKNOWN" })
830
+ failure ? chunkZCGKGDCL_cjs.failureToError(failure) : new chunkZCGKGDCL_cjs.ApplicationError("Activity failed", { errorType: "UNKNOWN" })
638
831
  )
639
832
  );
640
833
  return;
641
834
  case "ACTIVITY_TIMED_OUT": {
642
835
  const timeoutType = typeof p["timeoutType"] === "string" ? p["timeoutType"] : "UNKNOWN";
643
836
  pending.reject(
644
- wrap(new chunkELL2RBML_cjs.TimeoutFailure(`Activity timed out (${timeoutType})`, timeoutType))
837
+ wrap(new chunkZCGKGDCL_cjs.TimeoutFailure(`Activity timed out (${timeoutType})`, timeoutType))
645
838
  );
646
839
  return;
647
840
  }
648
841
  default:
649
- pending.reject(wrap(new chunkELL2RBML_cjs.CancelledFailure("Activity cancelled")));
842
+ pending.reject(wrap(new chunkZCGKGDCL_cjs.CancelledFailure("Activity cancelled")));
650
843
  }
651
844
  }
652
845
  settleChild(event, childId) {
@@ -664,7 +857,7 @@ var WorkflowExecution = class {
664
857
  let outcome;
665
858
  const failureValue = p["failure"];
666
859
  const failure = typeof failureValue === "object" && failureValue !== null && !Array.isArray(failureValue) ? failureValue : void 0;
667
- const wrap = (cause) => new chunkELL2RBML_cjs.ChildRunFailure(
860
+ const wrap = (cause) => new chunkZCGKGDCL_cjs.ChildRunFailure(
668
861
  `Child run ${childId} ${event.type.slice("CHILD_RUN_".length).toLowerCase().replace("_", " ")}: ${cause.message}`,
669
862
  childId,
670
863
  child.runId,
@@ -678,18 +871,18 @@ var WorkflowExecution = class {
678
871
  outcome = {
679
872
  ok: false,
680
873
  error: wrap(
681
- failure ? chunkELL2RBML_cjs.failureToError(failure) : new chunkELL2RBML_cjs.ApplicationError("Child failed", { errorType: "UNKNOWN" })
874
+ failure ? chunkZCGKGDCL_cjs.failureToError(failure) : new chunkZCGKGDCL_cjs.ApplicationError("Child failed", { errorType: "UNKNOWN" })
682
875
  )
683
876
  };
684
877
  break;
685
878
  case "CHILD_RUN_CANCELLED":
686
- outcome = { ok: false, error: wrap(new chunkELL2RBML_cjs.CancelledFailure("Child run cancelled")) };
879
+ outcome = { ok: false, error: wrap(new chunkZCGKGDCL_cjs.CancelledFailure("Child run cancelled")) };
687
880
  break;
688
881
  case "CHILD_RUN_TERMINATED":
689
882
  outcome = {
690
883
  ok: false,
691
884
  error: wrap(
692
- new chunkELL2RBML_cjs.TerminatedFailure(typeof p["reason"] === "string" ? p["reason"] : "Terminated")
885
+ new chunkZCGKGDCL_cjs.TerminatedFailure(typeof p["reason"] === "string" ? p["reason"] : "Terminated")
693
886
  )
694
887
  };
695
888
  break;
@@ -697,7 +890,7 @@ var WorkflowExecution = class {
697
890
  const timeoutType = typeof p["timeoutType"] === "string" ? p["timeoutType"] : "WORKFLOW_RUN";
698
891
  outcome = {
699
892
  ok: false,
700
- error: wrap(new chunkELL2RBML_cjs.TimeoutFailure(`Child run timed out (${timeoutType})`, timeoutType))
893
+ error: wrap(new chunkZCGKGDCL_cjs.TimeoutFailure(`Child run timed out (${timeoutType})`, timeoutType))
701
894
  };
702
895
  }
703
896
  }
@@ -717,10 +910,24 @@ var WorkflowExecution = class {
717
910
  else result.reject(outcome.error);
718
911
  }
719
912
  }
720
- dispatchSignal(name, payload) {
913
+ /** Run a signal handler through the inbound `handleSignal` interceptors. */
914
+ signalCall(name, payload, headers, handler) {
915
+ if (this.inbound.length === 0) return () => handler(payload);
916
+ const chain = chunkVA4OFR72_cjs.compose(
917
+ this.inbound,
918
+ "handleSignal",
919
+ (input) => handler(input.payload)
920
+ );
921
+ return () => chain({ name, payload, headers });
922
+ }
923
+ dispatchSignal(name, payload, headers = {}) {
721
924
  const handler = this.signalHandlers.get(name);
722
925
  if (handler) {
723
- this.runHandler(() => handler(payload), name, this.signalPolicies.get(name));
926
+ this.runHandler(
927
+ this.signalCall(name, payload, headers, handler),
928
+ name,
929
+ this.signalPolicies.get(name)
930
+ );
724
931
  return;
725
932
  }
726
933
  const waiters = this.signalWaiters.get(name);
@@ -732,7 +939,11 @@ var WorkflowExecution = class {
732
939
  }
733
940
  if (this.defaultSignalHandler) {
734
941
  const fallback = this.defaultSignalHandler;
735
- this.runHandler(() => fallback(name, payload), name, this.defaultSignalPolicy);
942
+ this.runHandler(
943
+ this.signalCall(name, payload, headers, (value) => fallback(name, value)),
944
+ name,
945
+ this.defaultSignalPolicy
946
+ );
736
947
  return;
737
948
  }
738
949
  const buffer = this.signalBuffers.get(name) ?? [];
@@ -757,22 +968,228 @@ var WorkflowExecution = class {
757
968
  return;
758
969
  }
759
970
  if (result instanceof Promise) {
760
- this.runningHandlers += 1;
761
- const entry = this.running.get(name) ?? { count: 0, policy };
762
- entry.count += 1;
763
- entry.policy = policy;
764
- this.running.set(name, entry);
765
- const done = () => {
766
- this.runningHandlers -= 1;
767
- entry.count -= 1;
768
- if (entry.count === 0) this.running.delete(name);
769
- };
971
+ const done = this.trackHandler("signal", name, policy);
770
972
  result.then(done, (error) => {
771
973
  done();
772
974
  this.onWorkflowError(error);
773
975
  });
774
976
  }
775
977
  }
978
+ /** Count a running asynchronous handler (drain check, `allHandlersFinished`); returns its end. */
979
+ trackHandler(kind, name, policy) {
980
+ this.runningHandlers += 1;
981
+ const key = `${kind}:${name}`;
982
+ const entry = this.running.get(key) ?? { kind, name, count: 0, policy };
983
+ entry.count += 1;
984
+ entry.policy = policy;
985
+ this.running.set(key, entry);
986
+ return () => {
987
+ this.runningHandlers -= 1;
988
+ entry.count -= 1;
989
+ if (entry.count === 0) this.running.delete(key);
990
+ };
991
+ }
992
+ // ---- updates (Phase C) ----------------------------------------------------
993
+ deliverUpdate(update) {
994
+ this.deliveredUpdates.add(update.updateId);
995
+ const entry = this.updateHandlerFor(update.name);
996
+ if (!entry) {
997
+ this.bufferedUpdates.push(update);
998
+ return;
999
+ }
1000
+ this.runUpdate(update, entry);
1001
+ }
1002
+ updateHandlerFor(name) {
1003
+ const own = this.updateHandlers.get(name);
1004
+ if (own) return own;
1005
+ const fallback = this.defaultUpdateHandler;
1006
+ if (!fallback) return void 0;
1007
+ const validate = fallback.validate;
1008
+ return {
1009
+ handler: (args) => fallback.handler(name, args),
1010
+ ...validate !== void 0 ? { validate: (args) => validate(name, args) } : {},
1011
+ policy: fallback.policy
1012
+ };
1013
+ }
1014
+ /**
1015
+ * Run `fn` with commands, sinks and every other change to the run's
1016
+ * deterministic state refused (query handlers, update validators). A
1017
+ * refused call fails the whole call with `QueryHandlerSideEffect`, even
1018
+ * when the code caught the error it threw.
1019
+ */
1020
+ readOnlyCall(what, fn) {
1021
+ const previous = this.readOnly;
1022
+ const previousViolation = this.readOnlyViolation;
1023
+ this.readOnly = what;
1024
+ this.readOnlyViolation = void 0;
1025
+ try {
1026
+ let value;
1027
+ try {
1028
+ value = fn();
1029
+ } catch (error) {
1030
+ const violation2 = this.readOnlyViolation;
1031
+ if (violation2 !== void 0 && !(error instanceof chunkZCGKGDCL_cjs.QueryHandlerSideEffect))
1032
+ throw new chunkZCGKGDCL_cjs.QueryHandlerSideEffect(`${violation2} (in ${what})`);
1033
+ throw error;
1034
+ }
1035
+ const violation = this.readOnlyViolation;
1036
+ if (violation !== void 0) throw new chunkZCGKGDCL_cjs.QueryHandlerSideEffect(`${violation} (in ${what})`);
1037
+ return value;
1038
+ } finally {
1039
+ this.readOnly = previous;
1040
+ this.readOnlyViolation = previousViolation;
1041
+ }
1042
+ }
1043
+ /**
1044
+ * Validate, accept and run one update. A validator error rejects it
1045
+ * (`REJECT_UPDATE`, no history); otherwise `ACCEPT_UPDATE` is issued and
1046
+ * the handler's result or failure completes it (`COMPLETE_UPDATE`). A
1047
+ * handler that throws something other than a failure class fails the task,
1048
+ * as a signal handler does.
1049
+ */
1050
+ runUpdate(update, entry) {
1051
+ if (this.closed || this.failure) return;
1052
+ const input = {
1053
+ updateId: update.updateId,
1054
+ name: update.name,
1055
+ args: update.args,
1056
+ headers: update.headers
1057
+ };
1058
+ if (update.validate && (entry.validate !== void 0 || this.inbound.length > 0)) {
1059
+ const validate = chunkVA4OFR72_cjs.compose(
1060
+ this.inbound,
1061
+ "validateUpdate",
1062
+ (checked) => entry.validate?.(checked.args)
1063
+ );
1064
+ try {
1065
+ this.readOnlyCall(`The validator of update ${update.name}`, () => validate(input));
1066
+ } catch (error) {
1067
+ if (error instanceof chunkZCGKGDCL_cjs.QueryHandlerSideEffect) {
1068
+ this.failTask("WORKFLOW_CODE_ERROR", messageOf(error), stackTextOf(error));
1069
+ return;
1070
+ }
1071
+ const failure = chunkZCGKGDCL_cjs.errorToFailure(error);
1072
+ delete failure.stackTrace;
1073
+ this.commands.push({ type: "REJECT_UPDATE", updateId: update.updateId, failure });
1074
+ return;
1075
+ }
1076
+ }
1077
+ if (!this.push({ type: "ACCEPT_UPDATE", updateId: update.updateId })) return;
1078
+ const handle = chunkVA4OFR72_cjs.compose(
1079
+ this.inbound,
1080
+ "handleUpdate",
1081
+ (accepted) => entry.handler(accepted.args)
1082
+ );
1083
+ let result;
1084
+ try {
1085
+ result = handle(input);
1086
+ } catch (error) {
1087
+ this.completeUpdate(update, { ok: false, error });
1088
+ return;
1089
+ }
1090
+ if (result instanceof Promise) {
1091
+ const done = this.trackHandler("update", update.name, entry.policy);
1092
+ result.then(
1093
+ (value) => {
1094
+ done();
1095
+ this.completeUpdate(update, { ok: true, value });
1096
+ },
1097
+ (error) => {
1098
+ done();
1099
+ this.completeUpdate(update, { ok: false, error });
1100
+ }
1101
+ );
1102
+ return;
1103
+ }
1104
+ this.completeUpdate(update, { ok: true, value: result });
1105
+ }
1106
+ completeUpdate(update, outcome) {
1107
+ if (this.closed || this.failure) return;
1108
+ if (outcome.ok) {
1109
+ let value;
1110
+ try {
1111
+ value = toJson(outcome.value, `The result of update ${update.name}`);
1112
+ } catch (error2) {
1113
+ this.onWorkflowError(error2);
1114
+ return;
1115
+ }
1116
+ this.push({ type: "COMPLETE_UPDATE", updateId: update.updateId, result: value });
1117
+ return;
1118
+ }
1119
+ const error = outcome.error;
1120
+ if (error instanceof ContinueAsNewRequest || !(chunkZCGKGDCL_cjs.isRunFailure(error) || this.isFailureType(error))) {
1121
+ this.onWorkflowError(error);
1122
+ return;
1123
+ }
1124
+ const failure = chunkZCGKGDCL_cjs.errorToFailure(error);
1125
+ delete failure.stackTrace;
1126
+ this.push({ type: "COMPLETE_UPDATE", updateId: update.updateId, failure });
1127
+ }
1128
+ /** Reject the updates of this activation that no handler took (`UpdateNotHandled`). */
1129
+ rejectUnhandledUpdates() {
1130
+ const pending = this.bufferedUpdates;
1131
+ this.bufferedUpdates = [];
1132
+ if (this.closed || this.failure) return;
1133
+ for (const update of pending)
1134
+ this.commands.push({
1135
+ type: "REJECT_UPDATE",
1136
+ updateId: update.updateId,
1137
+ failure: {
1138
+ errorType: "VALIDATION",
1139
+ type: "UpdateNotHandled",
1140
+ message: `The workflow has no handler for update "${update.name}"`,
1141
+ source: "sdk-ts"
1142
+ }
1143
+ });
1144
+ }
1145
+ handleUpdate(update, handler, options = {}) {
1146
+ const name = definitionName(update, "ctx.handleUpdate");
1147
+ if (typeof handler !== "function")
1148
+ throw new TypeError("ctx.handleUpdate needs a handler function");
1149
+ if (options.validate !== void 0 && typeof options.validate !== "function")
1150
+ throw new TypeError("validate must be a function");
1151
+ const policy = checkPolicy(options.unfinishedPolicy);
1152
+ this.updateHandlers.set(name, {
1153
+ handler,
1154
+ ...options.validate !== void 0 ? { validate: options.validate } : {},
1155
+ policy
1156
+ });
1157
+ this.dispatchBufferedUpdates();
1158
+ }
1159
+ setDefaultUpdateHandler(first, second) {
1160
+ const handler = typeof first === "function" ? first : second;
1161
+ const options = (typeof first === "function" ? second : first) ?? {};
1162
+ if (typeof handler !== "function" || typeof options !== "object")
1163
+ throw new TypeError("ctx.setDefaultUpdateHandler needs a handler function");
1164
+ if (options.validate !== void 0 && typeof options.validate !== "function")
1165
+ throw new TypeError("validate must be a function");
1166
+ this.defaultUpdateHandler = {
1167
+ handler,
1168
+ ...options.validate !== void 0 ? { validate: options.validate } : {},
1169
+ policy: checkPolicy(options.unfinishedPolicy)
1170
+ };
1171
+ this.dispatchBufferedUpdates();
1172
+ }
1173
+ dispatchBufferedUpdates() {
1174
+ const pending = this.bufferedUpdates;
1175
+ this.bufferedUpdates = [];
1176
+ for (const update of pending) {
1177
+ const entry = this.updateHandlerFor(update.name);
1178
+ if (entry) this.runUpdate(update, entry);
1179
+ else this.bufferedUpdates.push(update);
1180
+ }
1181
+ }
1182
+ handleQuery(query, handler) {
1183
+ const name = definitionName(query, "ctx.handleQuery");
1184
+ if (typeof handler !== "function")
1185
+ throw new TypeError("ctx.handleQuery needs a handler function");
1186
+ this.queryHandlers.set(name, handler);
1187
+ }
1188
+ setDefaultQueryHandler(handler) {
1189
+ if (typeof handler !== "function")
1190
+ throw new TypeError("ctx.setDefaultQueryHandler needs a handler function");
1191
+ this.defaultQueryHandler = handler;
1192
+ }
776
1193
  /**
777
1194
  * The drain check of 11 §2.18 when the workflow finishes: handlers still
778
1195
  * running with policy `WARN_AND_ABANDON` give one warning line and
@@ -780,13 +1197,18 @@ var WorkflowExecution = class {
780
1197
  */
781
1198
  checkUnfinishedHandlers(command) {
782
1199
  if (this.replaying || command.type === "CANCEL_WORKFLOW") return;
783
- const unfinished = [...this.running.entries()].filter(([, entry]) => entry.count > 0 && entry.policy === "WARN_AND_ABANDON").map(([name, entry]) => ({ kind: "signal", name, count: entry.count })).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
1200
+ const unfinished = [...this.running.values()].filter((entry) => entry.count > 0 && entry.policy === "WARN_AND_ABANDON").map(
1201
+ (entry) => ({ kind: entry.kind, name: entry.name, count: entry.count })
1202
+ ).sort(
1203
+ (a, b) => a.kind !== b.kind ? a.kind < b.kind ? -1 : 1 : a.name < b.name ? -1 : a.name > b.name ? 1 : 0
1204
+ );
784
1205
  if (unfinished.length === 0) return;
785
1206
  this.unfinished = unfinished;
786
1207
  const total = unfinished.reduce((sum, entry) => sum + entry.count, 0);
1208
+ const what = unfinished.every((entry) => entry.kind === "signal") ? "signal handler" : unfinished.every((entry) => entry.kind === "update") ? "update handler" : "signal or update handler";
787
1209
  this.logs.push({
788
1210
  level: "warn",
789
- message: `The workflow finished while ${total} signal handler${total === 1 ? " was" : "s were"} still running (${unfinished.map((entry) => `${entry.name} x${entry.count}`).join(
1211
+ message: `The workflow finished while ${total} ${what}${total === 1 ? " was" : "s were"} still running (${unfinished.map((entry) => `${entry.name} x${entry.count}`).join(
790
1212
  ", "
791
1213
  )}); await ctx.allHandlersFinished() before returning, or set unfinishedPolicy: 'ABANDON' on the handler`,
792
1214
  data: unfinished.map((entry) => ({ kind: entry.kind, name: entry.name, count: entry.count }))
@@ -796,7 +1218,15 @@ var WorkflowExecution = class {
796
1218
  startFunction(input) {
797
1219
  let promise;
798
1220
  try {
799
- promise = Promise.resolve(this.definition.fn(this.context, input));
1221
+ const run = (value) => (
1222
+ // The input crossed the history as JSON; the function declared its type.
1223
+ Promise.resolve(this.definition.fn(this.context, value))
1224
+ );
1225
+ promise = this.inbound.length === 0 ? run(input) : chunkVA4OFR72_cjs.compose(
1226
+ this.inbound,
1227
+ "execute",
1228
+ (execute) => run(execute.input)
1229
+ )({ workflowFn: this.request.workflowFn, input, headers: { ...this.startHeaders } });
800
1230
  } catch (error) {
801
1231
  promise = Promise.reject(error);
802
1232
  }
@@ -826,15 +1256,21 @@ var WorkflowExecution = class {
826
1256
  onWorkflowError(error) {
827
1257
  if (this.closed || this.failure) return;
828
1258
  if (error instanceof ContinueAsNewRequest) {
829
- this.pushTerminal({ type: "CONTINUE_AS_NEW", input: error.input, options: error.options });
1259
+ const command = {
1260
+ type: "CONTINUE_AS_NEW",
1261
+ input: error.input,
1262
+ options: error.options
1263
+ };
1264
+ if (Object.keys(error.headers).length > 0) command.headers = { ...error.headers };
1265
+ this.pushTerminal(command);
830
1266
  return;
831
1267
  }
832
1268
  const name = errorName(error);
833
- if (error instanceof chunkELL2RBML_cjs.DeterminismViolation || name === "DeterminismViolation") {
1269
+ if (error instanceof chunkZCGKGDCL_cjs.DeterminismViolation || name === "DeterminismViolation") {
834
1270
  this.failTask("NON_DETERMINISM", messageOf(error), stackTextOf(error), void 0, name);
835
1271
  return;
836
1272
  }
837
- if (error instanceof chunkELL2RBML_cjs.HistoryLimitExceeded) {
1273
+ if (error instanceof chunkZCGKGDCL_cjs.HistoryLimitExceeded) {
838
1274
  this.failTask("HISTORY_LIMIT", messageOf(error), stackTextOf(error));
839
1275
  return;
840
1276
  }
@@ -842,16 +1278,20 @@ var WorkflowExecution = class {
842
1278
  this.failTask("ISOLATE_MEMORY", messageOf(error), stackTextOf(error), void 0, name);
843
1279
  return;
844
1280
  }
845
- if (error instanceof chunkELL2RBML_cjs.PhaseCFeatureError) {
1281
+ if (error instanceof chunkZCGKGDCL_cjs.PhaseCFeatureError) {
846
1282
  this.failTask("UNSUPPORTED_COMMAND", messageOf(error), stackTextOf(error));
847
1283
  return;
848
1284
  }
849
- if (this.cancelRequested && chunkELL2RBML_cjs.isCancellation(error)) {
1285
+ if (error instanceof chunkZCGKGDCL_cjs.QueryHandlerSideEffect) {
1286
+ this.failTask("WORKFLOW_CODE_ERROR", messageOf(error), stackTextOf(error), void 0, name);
1287
+ return;
1288
+ }
1289
+ if (this.cancelRequested && chunkZCGKGDCL_cjs.isCancellation(error)) {
850
1290
  this.pushTerminal({ type: "CANCEL_WORKFLOW" });
851
1291
  return;
852
1292
  }
853
- if (chunkELL2RBML_cjs.isRunFailure(error) || this.isFailureType(error)) {
854
- this.pushTerminal({ type: "FAIL_WORKFLOW", failure: chunkELL2RBML_cjs.errorToFailure(error) });
1293
+ if (chunkZCGKGDCL_cjs.isRunFailure(error) || this.isFailureType(error)) {
1294
+ this.pushTerminal({ type: "FAIL_WORKFLOW", failure: chunkZCGKGDCL_cjs.errorToFailure(error) });
855
1295
  return;
856
1296
  }
857
1297
  this.failTask(
@@ -873,13 +1313,14 @@ var WorkflowExecution = class {
873
1313
  */
874
1314
  checkLimit() {
875
1315
  const events = this.historyLength + this.commands.length;
876
- if (events >= this.limitEvents * chunk3FIDHONL_cjs.HISTORY_LIMIT_EXCEEDED_RATIO || this.historyBytes >= this.limitBytes * chunk3FIDHONL_cjs.HISTORY_LIMIT_EXCEEDED_RATIO)
877
- throw new chunkELL2RBML_cjs.HistoryLimitExceeded(
1316
+ if (events >= this.limitEvents * chunkTYF56RGB_cjs.HISTORY_LIMIT_EXCEEDED_RATIO || this.historyBytes >= this.limitBytes * chunkTYF56RGB_cjs.HISTORY_LIMIT_EXCEEDED_RATIO)
1317
+ throw new chunkZCGKGDCL_cjs.HistoryLimitExceeded(
878
1318
  `The history has ${events} events and ${this.historyBytes} bytes, past 95 % of its limit (${this.limitEvents} events, ${this.limitBytes} bytes); continue as new`
879
1319
  );
880
1320
  }
881
1321
  /** Issue a command; false when the run is already closed (the command is dropped). */
882
1322
  push(command) {
1323
+ this.assertWritable(command.type);
883
1324
  if (this.closed || this.failure) return false;
884
1325
  this.checkLimit();
885
1326
  this.commands.push(command);
@@ -900,12 +1341,12 @@ var WorkflowExecution = class {
900
1341
  scheduleActivity(scope, operation, options) {
901
1342
  if (typeof operation !== "object" || operation === null || typeof operation.nodeType !== "string")
902
1343
  throw new TypeError("ctx.run needs a node operation (from nodes.* or the generated clients)");
903
- if (operation.role === "trigger" || !chunk3FIDHONL_cjs.isActivityNodeTypeAllowed(operation.nodeType))
904
- throw new chunkELL2RBML_cjs.ApplicationError(
1344
+ if (operation.role === "trigger" || !chunkA5SXCA62_cjs.isActivityNodeTypeAllowed(operation.nodeType))
1345
+ throw new chunkZCGKGDCL_cjs.ApplicationError(
905
1346
  `${operation.nodeType} cannot run as a durable activity: only store and registry nodes and internal:http, internal:datatable, internal:set and internal:code can`,
906
1347
  { type: "durable.activityTypeNotAllowed", errorType: "VALIDATION", nonRetryable: true }
907
1348
  );
908
- const activityId = this.ids.next("a");
1349
+ const activityId = this.nextId("a");
909
1350
  const operationName = options.operation ?? operation.operation ?? "execute";
910
1351
  const nodeVersion = options.nodeVersion ?? operation.version;
911
1352
  const cancellationType = options.cancellationType ?? "WAIT_CANCELLATION_COMPLETED";
@@ -916,14 +1357,14 @@ var WorkflowExecution = class {
916
1357
  nodeType: operation.nodeType,
917
1358
  operation: operationName,
918
1359
  args: toJson(options.args, `The args of ${operation.nodeType}`),
919
- retry: chunkYHBVMOMK_cjs.explicitRetryPolicy(options.retry)
1360
+ retry: chunkTYF56RGB_cjs.explicitRetryPolicy(options.retry)
920
1361
  };
921
1362
  if (nodeVersion !== void 0) command.nodeVersion = nodeVersion;
922
1363
  if (options.connection !== void 0) command.connection = options.connection;
923
- const startToClose = chunkJ3PYFGKA_cjs.optionalMs(options.startToCloseTimeout, "startToCloseTimeout");
924
- const scheduleToClose = chunkJ3PYFGKA_cjs.optionalMs(options.scheduleToCloseTimeout, "scheduleToCloseTimeout");
925
- const scheduleToStart = chunkJ3PYFGKA_cjs.optionalMs(options.scheduleToStartTimeout, "scheduleToStartTimeout");
926
- const heartbeat = chunkJ3PYFGKA_cjs.optionalMs(options.heartbeatTimeout, "heartbeatTimeout");
1364
+ const startToClose = chunkVA4OFR72_cjs.optionalMs(options.startToCloseTimeout, "startToCloseTimeout");
1365
+ const scheduleToClose = chunkVA4OFR72_cjs.optionalMs(options.scheduleToCloseTimeout, "scheduleToCloseTimeout");
1366
+ const scheduleToStart = chunkVA4OFR72_cjs.optionalMs(options.scheduleToStartTimeout, "scheduleToStartTimeout");
1367
+ const heartbeat = chunkVA4OFR72_cjs.optionalMs(options.heartbeatTimeout, "heartbeatTimeout");
927
1368
  if (startToClose !== void 0) command.startToCloseTimeout = startToClose;
928
1369
  if (scheduleToClose !== void 0) command.scheduleToCloseTimeout = scheduleToClose;
929
1370
  if (scheduleToStart !== void 0) command.scheduleToStartTimeout = scheduleToStart;
@@ -932,30 +1373,130 @@ var WorkflowExecution = class {
932
1373
  if (options.priority !== void 0) command.priority = options.priority;
933
1374
  if (options.summary !== void 0) command.summary = options.summary;
934
1375
  if (options.runOn !== void 0) command.runOn = options.runOn;
935
- if (options.headers !== void 0) command.headers = { ...options.headers };
936
- if (scope.consideredCancelled)
937
- return Promise.reject(new chunkELL2RBML_cjs.CancelledFailure("Scope is cancelled"));
938
- if (!this.push(command)) return this.never();
939
- this.issued.add(`activity:${activityId}`);
940
- return new Promise((resolve, reject) => {
941
- const entry = {
942
- resolve,
943
- reject,
1376
+ checkFairness(options);
1377
+ if (options.fairnessKey !== void 0) command.fairnessKey = options.fairnessKey;
1378
+ if (options.fairnessWeight !== void 0) command.fairnessWeight = options.fairnessWeight;
1379
+ return this.issueActivity(
1380
+ scope,
1381
+ command,
1382
+ options.headers,
1383
+ {
944
1384
  description: `activity ${activityId} (${operation.nodeType} ${operationName})`,
945
1385
  nodeType: operation.nodeType,
946
1386
  operation: operationName,
947
1387
  cancellationType
948
- };
1388
+ },
1389
+ { kind: "node", name: operation.nodeType, operation: operationName }
1390
+ );
1391
+ }
1392
+ /**
1393
+ * `ctx.activity` (Phase C): a user activity on a self-hosted task queue
1394
+ * (`SCHEDULE_ACTIVITY` of kind `user`). The queue is the option, else the
1395
+ * declaration's, else the run's own.
1396
+ */
1397
+ userActivity(scope, activity, options) {
1398
+ if (typeof options !== "object" || options === null)
1399
+ throw new TypeError("ctx.activity needs options with args");
1400
+ let name;
1401
+ let declaredQueue;
1402
+ if (typeof activity === "string") name = activity;
1403
+ else if (chunkVA4OFR72_cjs.isActivityDefinition(activity)) {
1404
+ name = activity.name;
1405
+ declaredQueue = activity.options.taskQueue;
1406
+ } else throw new TypeError("ctx.activity needs an activity name or a declareActivity() value");
1407
+ chunkVA4OFR72_cjs.checkActivityName(name);
1408
+ const taskQueue = options.taskQueue ?? declaredQueue ?? this.info.taskQueue ?? "managed";
1409
+ chunkVA4OFR72_cjs.checkTaskQueueName(taskQueue);
1410
+ const connections = options.connections;
1411
+ if (connections !== void 0 && (!Array.isArray(connections) || connections.length > chunkTYF56RGB_cjs.MAX_ACTIVITY_CONNECTIONS || new Set(connections).size !== connections.length || !connections.every((entry) => typeof entry === "string" && entry !== "")))
1412
+ throw new TypeError(
1413
+ `connections must be at most ${chunkTYF56RGB_cjs.MAX_ACTIVITY_CONNECTIONS} distinct connection names`
1414
+ );
1415
+ checkFairness(options);
1416
+ const activityId = this.nextId("a");
1417
+ const cancellationType = options.cancellationType ?? "WAIT_CANCELLATION_COMPLETED";
1418
+ const command = {
1419
+ type: "SCHEDULE_ACTIVITY",
1420
+ activityId,
1421
+ kind: "user",
1422
+ activityName: name,
1423
+ taskQueue,
1424
+ args: toJson(options.args, `The args of activity ${name}`),
1425
+ retry: chunkTYF56RGB_cjs.explicitRetryPolicy(options.retry)
1426
+ };
1427
+ const startToClose = chunkVA4OFR72_cjs.optionalMs(options.startToCloseTimeout, "startToCloseTimeout");
1428
+ const scheduleToClose = chunkVA4OFR72_cjs.optionalMs(options.scheduleToCloseTimeout, "scheduleToCloseTimeout");
1429
+ const scheduleToStart = chunkVA4OFR72_cjs.optionalMs(options.scheduleToStartTimeout, "scheduleToStartTimeout");
1430
+ const heartbeat = chunkVA4OFR72_cjs.optionalMs(options.heartbeatTimeout, "heartbeatTimeout");
1431
+ if (startToClose !== void 0) command.startToCloseTimeout = startToClose;
1432
+ if (scheduleToClose !== void 0) command.scheduleToCloseTimeout = scheduleToClose;
1433
+ if (scheduleToStart !== void 0) command.scheduleToStartTimeout = scheduleToStart;
1434
+ if (heartbeat !== void 0) command.heartbeatTimeout = heartbeat;
1435
+ if (options.cancellationType !== void 0) command.cancellationType = options.cancellationType;
1436
+ if (options.priority !== void 0) command.priority = options.priority;
1437
+ if (options.summary !== void 0) command.summary = options.summary;
1438
+ if (options.fairnessKey !== void 0) command.fairnessKey = options.fairnessKey;
1439
+ if (options.fairnessWeight !== void 0) command.fairnessWeight = options.fairnessWeight;
1440
+ if (connections !== void 0) command.connections = [...connections];
1441
+ return this.issueActivity(
1442
+ scope,
1443
+ command,
1444
+ options.headers,
1445
+ {
1446
+ description: `activity ${activityId} (user ${name})`,
1447
+ nodeType: "",
1448
+ operation: name,
1449
+ activityName: name,
1450
+ cancellationType
1451
+ },
1452
+ { kind: "user", name }
1453
+ );
1454
+ }
1455
+ /** Run the outbound `scheduleActivity` interceptors, then issue the command. */
1456
+ issueActivity(scope, command, headers, pending, what) {
1457
+ if (this.outbound.length === 0) {
1458
+ if (headers !== void 0) command.headers = { ...headers };
1459
+ return this.pushActivity(scope, command, pending);
1460
+ }
1461
+ const chain = chunkVA4OFR72_cjs.compose(
1462
+ this.outbound,
1463
+ "scheduleActivity",
1464
+ (input) => {
1465
+ command.args = toJson(input.args, `The args of ${what.name}`);
1466
+ if (headers !== void 0 || Object.keys(input.headers).length > 0)
1467
+ command.headers = { ...input.headers };
1468
+ return this.pushActivity(scope, command, pending);
1469
+ }
1470
+ );
1471
+ return chain({
1472
+ activityId: command.activityId,
1473
+ kind: what.kind,
1474
+ name: what.name,
1475
+ ...what.operation !== void 0 ? { operation: what.operation } : {},
1476
+ args: command.args,
1477
+ headers: { ...headers ?? {} }
1478
+ });
1479
+ }
1480
+ pushActivity(scope, command, pending) {
1481
+ const activityId = command.activityId;
1482
+ const cancellationType = pending.cancellationType;
1483
+ if (scope.consideredCancelled)
1484
+ return Promise.reject(new chunkZCGKGDCL_cjs.CancelledFailure("Scope is cancelled"));
1485
+ if (!this.push(command)) return this.never();
1486
+ this.issued.add(`activity:${activityId}`);
1487
+ return new Promise((resolve, reject) => {
1488
+ const entry = { ...pending, resolve, reject };
949
1489
  const stack = this.stack();
950
1490
  if (stack !== void 0) entry.stack = stack;
951
1491
  entry.release = scope.onCancel(() => {
952
1492
  if (!this.activities.has(activityId)) return;
953
- const cancelled = new chunkELL2RBML_cjs.ActivityFailure(
1493
+ const cancelled = new chunkZCGKGDCL_cjs.ActivityFailure(
954
1494
  `Activity ${activityId} cancelled`,
955
1495
  activityId,
956
1496
  entry.nodeType,
957
1497
  entry.operation,
958
- new chunkELL2RBML_cjs.CancelledFailure("Activity cancelled")
1498
+ new chunkZCGKGDCL_cjs.CancelledFailure("Activity cancelled"),
1499
+ entry.activityName
959
1500
  );
960
1501
  if (cancellationType !== "ABANDON")
961
1502
  this.push({ type: "REQUEST_CANCEL_ACTIVITY", activityId });
@@ -977,98 +1518,112 @@ var WorkflowExecution = class {
977
1518
  */
978
1519
  localActivity(scope, operation, options) {
979
1520
  if (typeof operation === "function")
980
- throw new chunkELL2RBML_cjs.PhaseCFeatureError("ctx.localActivity with a function (user local activities)");
1521
+ throw new chunkZCGKGDCL_cjs.PhaseCFeatureError("ctx.localActivity with a function (user local activities)");
981
1522
  if (typeof operation !== "object" || operation === null || typeof operation.nodeType !== "string")
982
1523
  throw new TypeError(
983
1524
  "ctx.localActivity needs a node operation (from nodes.* or the generated clients)"
984
1525
  );
985
1526
  const descriptor = operation;
986
- if (descriptor.role === "trigger" || !chunk3FIDHONL_cjs.isActivityNodeTypeAllowed(descriptor.nodeType))
987
- throw new chunkELL2RBML_cjs.ApplicationError(
1527
+ if (descriptor.role === "trigger" || !chunkA5SXCA62_cjs.isActivityNodeTypeAllowed(descriptor.nodeType))
1528
+ throw new chunkZCGKGDCL_cjs.ApplicationError(
988
1529
  `${descriptor.nodeType} cannot run as a durable activity: only store and registry nodes and internal:http, internal:datatable, internal:set and internal:code can`,
989
1530
  { type: "durable.activityTypeNotAllowed", errorType: "VALIDATION", nonRetryable: true }
990
1531
  );
991
1532
  if (typeof options !== "object" || options === null)
992
1533
  throw new TypeError("ctx.localActivity needs options with args");
993
- const timeout = options.startToCloseTimeout === void 0 ? chunk3FIDHONL_cjs.LOCAL_ACTIVITY_MAX_TIMEOUT_MS : chunkJ3PYFGKA_cjs.toMs(options.startToCloseTimeout, "startToCloseTimeout");
994
- if (timeout < 1 || timeout > chunk3FIDHONL_cjs.LOCAL_ACTIVITY_MAX_TIMEOUT_MS)
1534
+ const timeout = options.startToCloseTimeout === void 0 ? chunkTYF56RGB_cjs.LOCAL_ACTIVITY_MAX_TIMEOUT_MS : chunkVA4OFR72_cjs.toMs(options.startToCloseTimeout, "startToCloseTimeout");
1535
+ if (timeout < 1 || timeout > chunkTYF56RGB_cjs.LOCAL_ACTIVITY_MAX_TIMEOUT_MS)
995
1536
  throw new TypeError(
996
1537
  `A local activity's startToCloseTimeout must be between 1 ms and 30 s (got ${timeout} ms); use ctx.run for longer calls`
997
1538
  );
998
- const localActivityId = this.ids.next("l");
1539
+ const localActivityId = this.nextId("l");
999
1540
  const operationName = options.operation ?? descriptor.operation ?? "execute";
1000
1541
  const nodeVersion = options.nodeVersion ?? descriptor.version;
1001
- const retry = chunkYHBVMOMK_cjs.explicitRetryPolicy(options.retry);
1542
+ const retry = chunkTYF56RGB_cjs.explicitRetryPolicy(options.retry);
1002
1543
  const args = toJson(options.args, `The args of ${descriptor.nodeType}`);
1003
- if (scope.consideredCancelled)
1004
- return Promise.reject(new chunkELL2RBML_cjs.CancelledFailure("Scope is cancelled"));
1005
- const label = `local activity ${localActivityId} (${descriptor.nodeType} ${operationName})`;
1006
- const wrap = (cause) => new chunkELL2RBML_cjs.ActivityFailure(
1007
- `Local activity ${localActivityId} (${descriptor.nodeType} ${operationName}) failed: ${cause.message}`,
1008
- localActivityId,
1009
- descriptor.nodeType,
1010
- operationName,
1011
- cause
1012
- );
1013
- const record = (outcome) => {
1014
- const command = {
1015
- type: "RECORD_LOCAL_ACTIVITY",
1544
+ const proceed = (args2) => {
1545
+ if (scope.consideredCancelled)
1546
+ return Promise.reject(new chunkZCGKGDCL_cjs.CancelledFailure("Scope is cancelled"));
1547
+ const label = `local activity ${localActivityId} (${descriptor.nodeType} ${operationName})`;
1548
+ const wrap = (cause) => new chunkZCGKGDCL_cjs.ActivityFailure(
1549
+ `Local activity ${localActivityId} (${descriptor.nodeType} ${operationName}) failed: ${cause.message}`,
1550
+ localActivityId,
1551
+ descriptor.nodeType,
1552
+ operationName,
1553
+ cause
1554
+ );
1555
+ const record = (outcome) => {
1556
+ const command = {
1557
+ type: "RECORD_LOCAL_ACTIVITY",
1558
+ localActivityId,
1559
+ attempts: Math.max(1, Math.round(outcome.attempts)),
1560
+ nodeType: descriptor.nodeType,
1561
+ operation: operationName,
1562
+ ...outcome.failure !== void 0 ? { failure: outcome.failure } : { result: outcome.result ?? null }
1563
+ };
1564
+ if (options.summary !== void 0) command.summary = options.summary;
1565
+ if (!this.push(command)) return this.never();
1566
+ if (outcome.failure !== void 0)
1567
+ return Promise.reject(wrap(chunkZCGKGDCL_cjs.failureToError(outcome.failure)));
1568
+ return Promise.resolve(outcome.result ?? null);
1569
+ };
1570
+ const replayed = this.replaying;
1571
+ if (replayed) {
1572
+ const recorded = this.recordedLocalActivities.get(localActivityId);
1573
+ if (recorded !== void 0) return record(recorded);
1574
+ }
1575
+ const given = replayed ? void 0 : this.localActivityResults.get(localActivityId);
1576
+ let attempt = 1;
1577
+ let backoffMs = 0;
1578
+ if (given !== void 0) {
1579
+ if (given.failure === void 0) return record(given);
1580
+ const decision = chunkTYF56RGB_cjs.computeRetryDelay(retry, given.attempts, given.failure);
1581
+ if (!decision.retry) return record(given);
1582
+ attempt = given.attempts + 1;
1583
+ backoffMs = decision.delayMs;
1584
+ }
1585
+ const request = {
1016
1586
  localActivityId,
1017
- attempts: Math.max(1, Math.round(outcome.attempts)),
1587
+ kind: "node",
1018
1588
  nodeType: descriptor.nodeType,
1019
1589
  operation: operationName,
1020
- ...outcome.failure !== void 0 ? { failure: outcome.failure } : { result: outcome.result ?? null }
1590
+ args: args2,
1591
+ retry,
1592
+ startToCloseTimeout: timeout,
1593
+ attempt,
1594
+ backoffMs
1021
1595
  };
1022
- if (options.summary !== void 0) command.summary = options.summary;
1023
- if (!this.push(command)) return this.never();
1024
- if (outcome.failure !== void 0)
1025
- return Promise.reject(wrap(chunkELL2RBML_cjs.failureToError(outcome.failure)));
1026
- return Promise.resolve(outcome.result ?? null);
1596
+ if (nodeVersion !== void 0) request.nodeVersion = nodeVersion;
1597
+ if (options.connection !== void 0) request.connection = options.connection;
1598
+ if (options.summary !== void 0) request.summary = options.summary;
1599
+ return new Promise((resolve, reject) => {
1600
+ const entry = {
1601
+ resolve,
1602
+ reject,
1603
+ description: label,
1604
+ request,
1605
+ replayed
1606
+ };
1607
+ const stack = this.stack();
1608
+ if (stack !== void 0) entry.stack = stack;
1609
+ entry.release = scope.onCancel(() => {
1610
+ if (!this.localActivities.delete(localActivityId)) return;
1611
+ reject(wrap(new chunkZCGKGDCL_cjs.CancelledFailure("Local activity cancelled")));
1612
+ });
1613
+ this.localActivities.set(localActivityId, entry);
1614
+ });
1027
1615
  };
1028
- const replayed = this.replaying;
1029
- if (replayed) {
1030
- const recorded = this.recordedLocalActivities.get(localActivityId);
1031
- if (recorded !== void 0) return record(recorded);
1032
- }
1033
- const given = replayed ? void 0 : this.localActivityResults.get(localActivityId);
1034
- let attempt = 1;
1035
- let backoffMs = 0;
1036
- if (given !== void 0) {
1037
- if (given.failure === void 0) return record(given);
1038
- const decision = chunkYHBVMOMK_cjs.computeRetryDelay(retry, given.attempts, given.failure);
1039
- if (!decision.retry) return record(given);
1040
- attempt = given.attempts + 1;
1041
- backoffMs = decision.delayMs;
1042
- }
1043
- const request = {
1616
+ if (this.outbound.length === 0) return proceed(args);
1617
+ const chain = chunkVA4OFR72_cjs.compose(
1618
+ this.outbound,
1619
+ "scheduleLocalActivity",
1620
+ (input) => proceed(toJson(input.args, `The args of ${descriptor.nodeType}`))
1621
+ );
1622
+ return chain({
1044
1623
  localActivityId,
1045
- kind: "node",
1046
1624
  nodeType: descriptor.nodeType,
1047
1625
  operation: operationName,
1048
- args,
1049
- retry,
1050
- startToCloseTimeout: timeout,
1051
- attempt,
1052
- backoffMs
1053
- };
1054
- if (nodeVersion !== void 0) request.nodeVersion = nodeVersion;
1055
- if (options.connection !== void 0) request.connection = options.connection;
1056
- if (options.summary !== void 0) request.summary = options.summary;
1057
- return new Promise((resolve, reject) => {
1058
- const entry = {
1059
- resolve,
1060
- reject,
1061
- description: label,
1062
- request,
1063
- replayed
1064
- };
1065
- const stack = this.stack();
1066
- if (stack !== void 0) entry.stack = stack;
1067
- entry.release = scope.onCancel(() => {
1068
- if (!this.localActivities.delete(localActivityId)) return;
1069
- reject(wrap(new chunkELL2RBML_cjs.CancelledFailure("Local activity cancelled")));
1070
- });
1071
- this.localActivities.set(localActivityId, entry);
1626
+ args
1072
1627
  });
1073
1628
  }
1074
1629
  startTimer(scope, durationMs, summary) {
@@ -1078,8 +1633,8 @@ var WorkflowExecution = class {
1078
1633
  timer(scope, durationMs, summary) {
1079
1634
  if (durationMs <= 0) return { promise: Promise.resolve() };
1080
1635
  if (scope.consideredCancelled)
1081
- return { promise: Promise.reject(new chunkELL2RBML_cjs.CancelledFailure("Scope is cancelled")) };
1082
- const timerId = this.ids.next("t");
1636
+ return { promise: Promise.reject(new chunkZCGKGDCL_cjs.CancelledFailure("Scope is cancelled")) };
1637
+ const timerId = this.nextId("t");
1083
1638
  const command = {
1084
1639
  type: "START_TIMER",
1085
1640
  timerId,
@@ -1100,7 +1655,7 @@ var WorkflowExecution = class {
1100
1655
  if (!this.timers.has(timerId)) return;
1101
1656
  this.timers.delete(timerId);
1102
1657
  this.push({ type: "CANCEL_TIMER", timerId });
1103
- reject(new chunkELL2RBML_cjs.CancelledFailure("Timer cancelled"));
1658
+ reject(new chunkZCGKGDCL_cjs.CancelledFailure("Timer cancelled"));
1104
1659
  });
1105
1660
  this.timers.set(timerId, entry);
1106
1661
  });
@@ -1118,14 +1673,14 @@ var WorkflowExecution = class {
1118
1673
  condition(scope, predicate, timeout) {
1119
1674
  if (predicate()) return Promise.resolve(true);
1120
1675
  if (scope.consideredCancelled)
1121
- return Promise.reject(new chunkELL2RBML_cjs.CancelledFailure("Scope is cancelled"));
1676
+ return Promise.reject(new chunkZCGKGDCL_cjs.CancelledFailure("Scope is cancelled"));
1122
1677
  return new Promise((resolve, reject) => {
1123
1678
  const condition = { predicate, resolve, reject };
1124
1679
  const stack = this.stack();
1125
1680
  if (stack !== void 0) condition.stack = stack;
1126
1681
  this.conditions.push(condition);
1127
1682
  if (timeout !== void 0) {
1128
- const timer = this.timer(scope, chunkJ3PYFGKA_cjs.toMs(timeout, "condition timeout"), void 0);
1683
+ const timer = this.timer(scope, chunkVA4OFR72_cjs.toMs(timeout, "condition timeout"), void 0);
1129
1684
  if (timer.timerId !== void 0) condition.timerId = timer.timerId;
1130
1685
  timer.promise.then(
1131
1686
  () => {
@@ -1141,7 +1696,7 @@ var WorkflowExecution = class {
1141
1696
  if (!this.conditions.includes(condition)) return;
1142
1697
  this.conditions = this.conditions.filter((entry) => entry !== condition);
1143
1698
  this.cancelOwnTimer(condition.timerId);
1144
- reject(new chunkELL2RBML_cjs.CancelledFailure("Condition cancelled"));
1699
+ reject(new chunkZCGKGDCL_cjs.CancelledFailure("Condition cancelled"));
1145
1700
  });
1146
1701
  });
1147
1702
  }
@@ -1169,7 +1724,7 @@ var WorkflowExecution = class {
1169
1724
  return fired;
1170
1725
  }
1171
1726
  signalReceived(scope, signal) {
1172
- const name = chunkELL2RBML_cjs.signalName(signal);
1727
+ const name = chunkZCGKGDCL_cjs.signalName(signal);
1173
1728
  const buffered = this.takeBuffered(name);
1174
1729
  if (buffered !== void 0) return Promise.resolve(buffered);
1175
1730
  return new Promise((resolve, reject) => {
@@ -1188,16 +1743,14 @@ var WorkflowExecution = class {
1188
1743
  const position = list.indexOf(entry);
1189
1744
  if (position < 0) return;
1190
1745
  list.splice(position, 1);
1191
- reject(new chunkELL2RBML_cjs.CancelledFailure("Signal wait cancelled"));
1746
+ reject(new chunkZCGKGDCL_cjs.CancelledFailure("Signal wait cancelled"));
1192
1747
  });
1193
1748
  });
1194
1749
  }
1195
1750
  onSignal(signal, handler, options = {}) {
1196
1751
  if (typeof handler !== "function") throw new TypeError("ctx.onSignal needs a handler function");
1197
- const policy = options.unfinishedPolicy ?? "WARN_AND_ABANDON";
1198
- if (policy !== "WARN_AND_ABANDON" && policy !== "ABANDON")
1199
- throw new TypeError("unfinishedPolicy must be WARN_AND_ABANDON or ABANDON");
1200
- const name = chunkELL2RBML_cjs.signalName(signal);
1752
+ const policy = checkPolicy(options.unfinishedPolicy);
1753
+ const name = chunkZCGKGDCL_cjs.signalName(signal);
1201
1754
  this.signalHandlers.set(name, handler);
1202
1755
  this.signalPolicies.set(name, policy);
1203
1756
  let payload = this.takeBuffered(name);
@@ -1240,7 +1793,7 @@ var WorkflowExecution = class {
1240
1793
  return {
1241
1794
  runId: "runId" in resolved ? resolved.runId : "",
1242
1795
  ..."workflowId" in resolved ? { workflowKey: resolved.workflowKey, workflowId: resolved.workflowId } : {},
1243
- signal: (signal, payload) => this.signalExternal(resolved, chunkELL2RBML_cjs.signalName(signal), payload),
1796
+ signal: (signal, payload) => this.signalExternal(resolved, chunkZCGKGDCL_cjs.signalName(signal), payload),
1244
1797
  cancel: () => this.cancelExternal(resolved)
1245
1798
  };
1246
1799
  }
@@ -1249,7 +1802,7 @@ var WorkflowExecution = class {
1249
1802
  if (target === "") throw new TypeError("ctx.child needs a workflow key or function");
1250
1803
  return { workflowKey: target };
1251
1804
  }
1252
- if (chunkJ3PYFGKA_cjs.isDurableWorkflow(target)) {
1805
+ if (chunkVA4OFR72_cjs.isDurableWorkflow(target)) {
1253
1806
  const exportName = this.exportNames.get(target);
1254
1807
  if (exportName === void 0)
1255
1808
  throw new TypeError(
@@ -1270,7 +1823,7 @@ var WorkflowExecution = class {
1270
1823
  if (options.context !== void 0)
1271
1824
  opts["context"] = toJson(options.context, "The child context");
1272
1825
  if (options.retry !== void 0)
1273
- opts["retry"] = toJson(chunkJ3PYFGKA_cjs.runRetryPolicyOf(options.retry), "The child retry policy");
1826
+ opts["retry"] = toJson(chunkVA4OFR72_cjs.runRetryPolicyOf(options.retry), "The child retry policy");
1274
1827
  if (options.versioningBehavior !== void 0)
1275
1828
  opts["versioningBehavior"] = options.versioningBehavior;
1276
1829
  if (options.idReusePolicy !== void 0) opts["idReusePolicy"] = options.idReusePolicy;
@@ -1284,7 +1837,7 @@ var WorkflowExecution = class {
1284
1837
  for (const [key, name] of durations) {
1285
1838
  const value = options[key];
1286
1839
  if (value !== void 0 && (typeof value === "number" || typeof value === "string"))
1287
- opts[name] = chunkJ3PYFGKA_cjs.toMs(value, name);
1840
+ opts[name] = chunkVA4OFR72_cjs.toMs(value, name);
1288
1841
  }
1289
1842
  const command = {
1290
1843
  type: "START_CHILD_RUN",
@@ -1296,13 +1849,39 @@ var WorkflowExecution = class {
1296
1849
  ...opts
1297
1850
  }
1298
1851
  };
1852
+ checkFairness(options);
1853
+ if (options.fairnessKey !== void 0) command.options.fairnessKey = options.fairnessKey;
1854
+ if (options.fairnessWeight !== void 0)
1855
+ command.options.fairnessWeight = options.fairnessWeight;
1299
1856
  if (options.version !== void 0) command.version = options.version;
1300
1857
  if (options.headers !== void 0) command.headers = { ...options.headers };
1301
1858
  return command;
1302
1859
  }
1860
+ /**
1861
+ * Run the outbound `startChild` interceptors around a child start. `go`
1862
+ * starts the child with the options the interceptors leave (input and
1863
+ * headers).
1864
+ */
1865
+ interceptChild(target, options, go) {
1866
+ if (this.outbound.length === 0) return go(options);
1867
+ const chain = chunkVA4OFR72_cjs.compose(
1868
+ this.outbound,
1869
+ "startChild",
1870
+ (input) => go({
1871
+ ...options,
1872
+ input: input.input,
1873
+ ...options.headers !== void 0 || Object.keys(input.headers).length > 0 ? { headers: { ...input.headers } } : {}
1874
+ })
1875
+ );
1876
+ return chain({
1877
+ ...this.childTarget(target),
1878
+ input: toJson(options.input, "The child input"),
1879
+ headers: { ...options.headers ?? {} }
1880
+ });
1881
+ }
1303
1882
  startChildRun(scope, target, options, defaultPolicy) {
1304
1883
  if (scope.consideredCancelled) return void 0;
1305
- const childId = this.ids.next("c");
1884
+ const childId = this.nextId("c");
1306
1885
  const command = this.childCommand(childId, target, options, defaultPolicy);
1307
1886
  if (!this.push(command)) return void 0;
1308
1887
  this.issued.add(`child:${childId}`);
@@ -1315,19 +1894,19 @@ var WorkflowExecution = class {
1315
1894
  onChildCancel(child, entry) {
1316
1895
  return () => {
1317
1896
  if (child.settled) return;
1318
- const type = child.cancellationType ?? chunkRUQIMTN5_cjs.CHILD_DEFAULT_CANCELLATION_TYPE;
1319
- const error = new chunkELL2RBML_cjs.ChildRunFailure(
1897
+ const type = child.cancellationType ?? chunkISOIA7NV_cjs.CHILD_DEFAULT_CANCELLATION_TYPE;
1898
+ const error = new chunkZCGKGDCL_cjs.ChildRunFailure(
1320
1899
  `Child run ${child.childId} cancelled`,
1321
1900
  child.childId,
1322
1901
  child.runId,
1323
- new chunkELL2RBML_cjs.CancelledFailure("Child run cancelled")
1902
+ new chunkZCGKGDCL_cjs.CancelledFailure("Child run cancelled")
1324
1903
  );
1325
1904
  if (type === "ABANDON") {
1326
1905
  child.result = void 0;
1327
1906
  entry.reject(error);
1328
1907
  return;
1329
1908
  }
1330
- const externalId = this.ids.next("x");
1909
+ const externalId = this.nextId("x");
1331
1910
  if (this.push({
1332
1911
  type: "REQUEST_CANCEL_EXTERNAL_RUN",
1333
1912
  externalId,
@@ -1361,15 +1940,17 @@ var WorkflowExecution = class {
1361
1940
  };
1362
1941
  }
1363
1942
  child(scope, target, options) {
1364
- const child = this.startChildRun(
1365
- scope,
1366
- target,
1367
- options,
1368
- chunkRUQIMTN5_cjs.CHILD_DEFAULT_PARENT_CLOSE_POLICY.child
1369
- );
1370
- if (!child)
1371
- return scope.consideredCancelled ? Promise.reject(new chunkELL2RBML_cjs.CancelledFailure("Scope is cancelled")) : this.never();
1372
- return this.childResult(child);
1943
+ return this.interceptChild(target, options, (opts) => {
1944
+ const child = this.startChildRun(
1945
+ scope,
1946
+ target,
1947
+ opts,
1948
+ chunkISOIA7NV_cjs.CHILD_DEFAULT_PARENT_CLOSE_POLICY.child
1949
+ );
1950
+ if (!child)
1951
+ return scope.consideredCancelled ? Promise.reject(new chunkZCGKGDCL_cjs.CancelledFailure("Scope is cancelled")) : this.never();
1952
+ return this.childResult(child);
1953
+ });
1373
1954
  }
1374
1955
  childResult(child) {
1375
1956
  if (child.settled && child.outcome) {
@@ -1389,14 +1970,21 @@ var WorkflowExecution = class {
1389
1970
  });
1390
1971
  }
1391
1972
  startChild(scope, target, options) {
1973
+ return this.interceptChild(
1974
+ target,
1975
+ options,
1976
+ (opts) => this.startChildHandle(scope, target, opts)
1977
+ );
1978
+ }
1979
+ startChildHandle(scope, target, options) {
1392
1980
  const child = this.startChildRun(
1393
1981
  scope,
1394
1982
  target,
1395
1983
  options,
1396
- chunkRUQIMTN5_cjs.CHILD_DEFAULT_PARENT_CLOSE_POLICY.startChild
1984
+ chunkISOIA7NV_cjs.CHILD_DEFAULT_PARENT_CLOSE_POLICY.startChild
1397
1985
  );
1398
1986
  if (!child)
1399
- return scope.consideredCancelled ? Promise.reject(new chunkELL2RBML_cjs.CancelledFailure("Scope is cancelled")) : this.never();
1987
+ return scope.consideredCancelled ? Promise.reject(new chunkZCGKGDCL_cjs.CancelledFailure("Scope is cancelled")) : this.never();
1400
1988
  return new Promise((resolve, reject) => {
1401
1989
  const entry = {
1402
1990
  resolve,
@@ -1411,14 +1999,28 @@ var WorkflowExecution = class {
1411
1999
  childId: child.childId,
1412
2000
  runId: runId ?? child.runId ?? "",
1413
2001
  result: () => this.childResult(child),
1414
- signal: (signal, payload) => this.signalExternal({ childId: child.childId }, chunkELL2RBML_cjs.signalName(signal), payload),
2002
+ signal: (signal, payload) => this.signalExternal({ childId: child.childId }, chunkZCGKGDCL_cjs.signalName(signal), payload),
1415
2003
  cancel: () => this.cancelExternal({ childId: child.childId })
1416
2004
  };
1417
2005
  return handle;
1418
2006
  });
1419
2007
  }
1420
2008
  signalExternal(target, name, payload) {
1421
- const externalId = this.ids.next("x");
2009
+ if (this.outbound.length === 0) return this.pushSignal(target, name, payload, void 0);
2010
+ const chain = chunkVA4OFR72_cjs.compose(
2011
+ this.outbound,
2012
+ "signalRun",
2013
+ (input) => this.pushSignal(input.target, input.name, input.payload, input.headers)
2014
+ );
2015
+ return chain({
2016
+ target,
2017
+ name,
2018
+ payload: toJson(payload, `The payload of signal ${name}`),
2019
+ headers: {}
2020
+ });
2021
+ }
2022
+ pushSignal(target, name, payload, headers) {
2023
+ const externalId = this.nextId("x");
1422
2024
  const command = {
1423
2025
  type: "SIGNAL_RUN",
1424
2026
  externalId,
@@ -1426,6 +2028,7 @@ var WorkflowExecution = class {
1426
2028
  name,
1427
2029
  payload: toJson(payload, `The payload of signal ${name}`)
1428
2030
  };
2031
+ if (headers !== void 0 && Object.keys(headers).length > 0) command.headers = { ...headers };
1429
2032
  if (!this.push(command)) return this.never();
1430
2033
  this.issued.add(`external:${externalId}`);
1431
2034
  return new Promise((resolve, reject) => {
@@ -1440,7 +2043,15 @@ var WorkflowExecution = class {
1440
2043
  });
1441
2044
  }
1442
2045
  cancelExternal(target) {
1443
- const externalId = this.ids.next("x");
2046
+ if (this.outbound.length === 0) return this.pushCancel(target);
2047
+ return chunkVA4OFR72_cjs.compose(
2048
+ this.outbound,
2049
+ "cancelRun",
2050
+ (input) => this.pushCancel(input.target)
2051
+ )({ target });
2052
+ }
2053
+ pushCancel(target) {
2054
+ const externalId = this.nextId("x");
1444
2055
  if (!this.push({ type: "REQUEST_CANCEL_EXTERNAL_RUN", externalId, target }))
1445
2056
  return this.never();
1446
2057
  this.issued.add(`external:${externalId}`);
@@ -1456,7 +2067,15 @@ var WorkflowExecution = class {
1456
2067
  });
1457
2068
  }
1458
2069
  sideEffect(fn) {
1459
- const sideEffectId = this.ids.next("s");
2070
+ if (this.outbound.length === 0) return this.recordSideEffect(fn);
2071
+ return chunkVA4OFR72_cjs.compose(
2072
+ this.outbound,
2073
+ "sideEffect",
2074
+ () => this.recordSideEffect(fn)
2075
+ )({});
2076
+ }
2077
+ recordSideEffect(fn) {
2078
+ const sideEffectId = this.nextId("s");
1460
2079
  let value;
1461
2080
  if (this.replaying && this.recordedSideEffects.has(sideEffectId)) {
1462
2081
  value = this.recordedSideEffects.get(sideEffectId) ?? null;
@@ -1470,6 +2089,7 @@ var WorkflowExecution = class {
1470
2089
  if (typeof patchId !== "string" || patchId === "") throw new TypeError("A patch needs an id");
1471
2090
  const known = this.patches.get(patchId);
1472
2091
  if (known !== void 0) return known;
2092
+ this.assertWritable(deprecated ? "ctx.deprecatePatch()" : "ctx.patched()");
1473
2093
  const markerId = patchMarkerId(patchId);
1474
2094
  let result;
1475
2095
  if (this.replaying) {
@@ -1496,26 +2116,122 @@ var WorkflowExecution = class {
1496
2116
  }
1497
2117
  setCurrentDetails(markdown) {
1498
2118
  if (typeof markdown !== "string") throw new TypeError("setCurrentDetails takes Markdown text");
2119
+ this.assertWritable("ctx.setCurrentDetails()");
1499
2120
  this.currentDetails = markdown;
1500
2121
  this.push({
1501
2122
  type: "RECORD_MARKER",
1502
- markerId: this.ids.next("m"),
2123
+ markerId: this.nextId("m"),
1503
2124
  data: { currentDetails: markdown }
1504
2125
  });
1505
2126
  }
1506
2127
  upsertContext(entries) {
1507
2128
  const json = toJson(entries, "The context entries");
1508
2129
  if (!isJsonObject(json)) throw new TypeError("ctx.upsertContext takes an object");
1509
- if (this.push({ type: "UPSERT_CONTEXT", entries: json })) this.memo = { ...this.memo, ...json };
2130
+ const apply = (input) => {
2131
+ const final = toJson(input.entries, "The context entries");
2132
+ if (!isJsonObject(final)) throw new TypeError("ctx.upsertContext takes an object");
2133
+ if (this.push({ type: "UPSERT_CONTEXT", entries: final }))
2134
+ this.memo = { ...this.memo, ...final };
2135
+ };
2136
+ if (this.outbound.length === 0) apply({ entries: json });
2137
+ else
2138
+ chunkVA4OFR72_cjs.compose(
2139
+ this.outbound,
2140
+ "upsertContext",
2141
+ apply
2142
+ )({ entries: json });
2143
+ }
2144
+ /** `ctx.upsertSearchAttributes` (Phase C): a null value removes an attribute. */
2145
+ upsertSearchAttributes(attributes) {
2146
+ const json = toJson(attributes, "The search attributes");
2147
+ if (!isJsonObject(json) || Object.keys(json).length === 0)
2148
+ throw new TypeError("ctx.upsertSearchAttributes takes an object with at least one attribute");
2149
+ for (const key of Object.keys(json))
2150
+ if (key.trim() === "") throw new TypeError("A search attribute needs a name");
2151
+ const apply = (input) => {
2152
+ const final = toJson(input.attributes, "The search attributes");
2153
+ if (!isJsonObject(final)) throw new TypeError("ctx.upsertSearchAttributes takes an object");
2154
+ if (this.push({ type: "UPSERT_SEARCH_ATTRIBUTES", attributes: final }))
2155
+ this.searchAttributes = chunkISOIA7NV_cjs.mergeSearchAttributes(this.searchAttributes, final);
2156
+ };
2157
+ if (this.outbound.length === 0) apply({ attributes: json });
2158
+ else
2159
+ chunkVA4OFR72_cjs.compose(
2160
+ this.outbound,
2161
+ "upsertSearchAttributes",
2162
+ apply
2163
+ )({ attributes: json });
2164
+ }
2165
+ /** A `ctx.sinks.<sink>.<fn>(...args)` call: recorded once, never on replay (11 §2.31). */
2166
+ callSink(sink, fn, args) {
2167
+ this.assertWritable(`The sink call ${sink}.${fn}`);
2168
+ if (this.replaying || this.closed || this.failure || this.request.kind !== "task") return;
2169
+ if (this.sinkCalls.length >= chunkTYF56RGB_cjs.MAX_SINK_CALLS) {
2170
+ if (!this.sinkCallsDropped) {
2171
+ this.sinkCallsDropped = true;
2172
+ this.logs.push({
2173
+ level: "warn",
2174
+ message: `More than ${chunkTYF56RGB_cjs.MAX_SINK_CALLS} sink calls in one workflow task; the rest were dropped`
2175
+ });
2176
+ }
2177
+ return;
2178
+ }
2179
+ this.sinkCalls.push({
2180
+ sink,
2181
+ fn,
2182
+ args: args.map((arg, index) => toJson(arg, `Argument ${index + 1} of ${sink}.${fn}`))
2183
+ });
2184
+ }
2185
+ sinksProxy() {
2186
+ const execution = this;
2187
+ const sinkOf = (sink) => new Proxy(
2188
+ {},
2189
+ {
2190
+ get(_target, fn) {
2191
+ if (typeof fn !== "string" || fn === "then") return void 0;
2192
+ return (...args) => execution.callSink(sink, fn, args);
2193
+ }
2194
+ }
2195
+ );
2196
+ return new Proxy(
2197
+ {},
2198
+ {
2199
+ get(_target, sink) {
2200
+ if (typeof sink !== "string" || sink === "then") return void 0;
2201
+ return sinkOf(sink);
2202
+ }
2203
+ }
2204
+ );
2205
+ }
2206
+ /** `ctx.continueAsNew`: a rejection with the request, after the outbound interceptors. */
2207
+ continueAsNewCall(input, options) {
2208
+ let request;
2209
+ try {
2210
+ request = this.continueAsNew(input, options);
2211
+ } catch (error) {
2212
+ return Promise.reject(error);
2213
+ }
2214
+ if (this.outbound.length === 0) return Promise.reject(request);
2215
+ return chunkVA4OFR72_cjs.compose(
2216
+ this.outbound,
2217
+ "continueAsNew",
2218
+ (changed) => Promise.reject(
2219
+ new ContinueAsNewRequest(
2220
+ toJson(changed.input, "The continue-as-new input"),
2221
+ changed.options,
2222
+ headersOf(changed.headers)
2223
+ )
2224
+ )
2225
+ )({ input: request.input, options: { ...request.options }, headers: {} });
1510
2226
  }
1511
2227
  /** The request a `ctx.continueAsNew` call throws; the run ends with `CONTINUE_AS_NEW`. */
1512
2228
  continueAsNew(input, options) {
1513
2229
  const opts = {};
1514
2230
  if (options.taskQueue !== void 0) opts["taskQueue"] = options.taskQueue;
1515
2231
  if (options.retry !== void 0)
1516
- opts["retry"] = toJson(chunkJ3PYFGKA_cjs.continueAsNewRetryOf(options.retry), "retry");
2232
+ opts["retry"] = toJson(chunkVA4OFR72_cjs.continueAsNewRetryOf(options.retry), "retry");
1517
2233
  if (options.workflowTaskTimeout !== void 0)
1518
- opts["workflowTaskTimeout"] = chunkJ3PYFGKA_cjs.toMs(options.workflowTaskTimeout, "workflowTaskTimeout");
2234
+ opts["workflowTaskTimeout"] = chunkVA4OFR72_cjs.toMs(options.workflowTaskTimeout, "workflowTaskTimeout");
1519
2235
  if (options.context !== void 0) opts["context"] = toJson(options.context, "context");
1520
2236
  if (options.versioningBehavior !== void 0)
1521
2237
  opts["versioningBehavior"] = options.versioningBehavior;
@@ -1525,7 +2241,7 @@ var WorkflowExecution = class {
1525
2241
  const scope = new Scope(parent, options.nonCancellable === true);
1526
2242
  let timerId;
1527
2243
  if (options.timeout !== void 0) {
1528
- const timer = this.timer(parent, chunkJ3PYFGKA_cjs.toMs(options.timeout, "scope timeout"), void 0);
2244
+ const timer = this.timer(parent, chunkVA4OFR72_cjs.toMs(options.timeout, "scope timeout"), void 0);
1529
2245
  timerId = timer.timerId;
1530
2246
  timer.promise.then(
1531
2247
  () => scope.cancel(),
@@ -1580,13 +2296,49 @@ var WorkflowExecution = class {
1580
2296
  );
1581
2297
  return out;
1582
2298
  }
1583
- answerQueries() {
1584
- return (this.request.queries ?? []).map((query) => {
1585
- if (!chunk3FIDHONL_cjs.BUILT_IN_QUERIES.includes(query.name))
2299
+ /**
2300
+ * Answer a custom query (Phase C): the handler registered for the name, else
2301
+ * the default handler, run read-only through the inbound `handleQuery`
2302
+ * interceptors. No handler gives `rejected`.
2303
+ */
2304
+ answerCustomQuery(query) {
2305
+ if (this.failure)
2306
+ return { queryId: query.queryId, error: `The replay failed: ${this.failure.message}` };
2307
+ const own = this.queryHandlers.get(query.name);
2308
+ const fallback = this.defaultQueryHandler;
2309
+ const handler = own ?? (fallback !== void 0 ? (args) => fallback(query.name, args) : void 0);
2310
+ if (handler === void 0)
2311
+ return {
2312
+ queryId: query.queryId,
2313
+ rejected: true,
2314
+ error: `The workflow has no handler for query "${query.name}"`
2315
+ };
2316
+ const chain = chunkVA4OFR72_cjs.compose(
2317
+ this.inbound,
2318
+ "handleQuery",
2319
+ (input) => handler(input.args)
2320
+ );
2321
+ try {
2322
+ const value = this.readOnlyCall(
2323
+ `the handler of query ${query.name}`,
2324
+ () => chain({ queryId: query.queryId, name: query.name, args: query.args ?? null })
2325
+ );
2326
+ if (typeof value === "object" && value !== null && typeof value.then === "function")
1586
2327
  return {
1587
2328
  queryId: query.queryId,
1588
- error: `Unknown query ${String(query.name)}; custom queries are Phase C`
2329
+ error: `The handler of query "${query.name}" returned a promise; query handlers must return a value`
1589
2330
  };
2331
+ return { queryId: query.queryId, value: toJson(value, `The result of query ${query.name}`) };
2332
+ } catch (error) {
2333
+ return {
2334
+ queryId: query.queryId,
2335
+ error: `${errorName(error) || "Error"}: ${messageOf(error)}`
2336
+ };
2337
+ }
2338
+ }
2339
+ answerQueries() {
2340
+ return (this.request.queries ?? []).map((query) => {
2341
+ if (!isBuiltInQuery(query.name)) return this.answerCustomQuery(query);
1590
2342
  if (this.failure)
1591
2343
  return { queryId: query.queryId, error: `The replay failed: ${this.failure.message}` };
1592
2344
  if (query.name === "__stack_trace")
@@ -1634,9 +2386,20 @@ ${entry.stack}`).join("\n\n")
1634
2386
  contextFor(bound) {
1635
2387
  const scope = () => bound ?? this.currentScope();
1636
2388
  const log = (level) => (message, data) => {
1637
- if (this.replaying) return;
2389
+ if (this.replaying || this.readOnly !== void 0) return;
1638
2390
  const line = { level, message: String(message) };
1639
- if (data !== void 0) line.data = toJson(data, "The log data");
2391
+ const payload = data !== void 0 ? toJson(data, "The log data") : void 0;
2392
+ const attributes = this.outbound.length === 0 ? {} : chunkVA4OFR72_cjs.compose(
2393
+ this.outbound,
2394
+ "getLogAttributes",
2395
+ (input) => input
2396
+ )({});
2397
+ if (Object.keys(attributes).length === 0) {
2398
+ if (payload !== void 0) line.data = payload;
2399
+ } else {
2400
+ const extra = toJson(attributes, "The log attributes");
2401
+ line.data = payload === void 0 ? extra : isJsonObject(payload) && isJsonObject(extra) ? { ...extra, ...payload } : { ...isJsonObject(extra) ? extra : {}, data: payload };
2402
+ }
1640
2403
  this.logs.push(line);
1641
2404
  };
1642
2405
  const logger = {
@@ -1647,14 +2410,21 @@ ${entry.stack}`).join("\n\n")
1647
2410
  };
1648
2411
  const scopeFn = ((fn, options = {}) => this.cancellationScope(scope(), fn, options));
1649
2412
  scopeFn.current = () => scope();
1650
- const phaseC = (feature) => () => {
1651
- throw new chunkELL2RBML_cjs.PhaseCFeatureError(feature);
1652
- };
1653
2413
  const context = {
1654
2414
  info: this.info,
1655
2415
  log: logger,
1656
2416
  run: (operation, options) => this.scheduleActivity(scope(), operation, options),
1657
- sleep: (duration, options = {}) => this.startTimer(scope(), chunkJ3PYFGKA_cjs.toMs(duration, "sleep duration"), options.summary),
2417
+ sleep: (duration, options = {}) => {
2418
+ const durationMs = chunkVA4OFR72_cjs.toMs(duration, "sleep duration");
2419
+ if (this.outbound.length === 0)
2420
+ return this.startTimer(scope(), durationMs, options.summary);
2421
+ const current = scope();
2422
+ return chunkVA4OFR72_cjs.compose(
2423
+ this.outbound,
2424
+ "startTimer",
2425
+ (input) => this.startTimer(current, chunkVA4OFR72_cjs.toMs(input.durationMs, "sleep duration"), input.summary)
2426
+ )({ durationMs, ...options.summary !== void 0 ? { summary: options.summary } : {} });
2427
+ },
1658
2428
  condition: (predicate, timeout) => this.condition(scope(), predicate, timeout),
1659
2429
  signalReceived: (signal) => this.signalReceived(scope(), signal),
1660
2430
  onSignal: ((signal, optionsOrHandler, maybeHandler) => {
@@ -1666,13 +2436,16 @@ ${entry.stack}`).join("\n\n")
1666
2436
  setDefaultSignalHandler: (handler) => this.setDefaultSignalHandler(handler),
1667
2437
  child: (target, options = {}) => this.child(scope(), target, options),
1668
2438
  startChild: (target, options = {}) => this.startChild(scope(), target, options),
1669
- signalRun: (target, signal, payload) => this.signalExternal(this.externalTarget(target), chunkELL2RBML_cjs.signalName(signal), payload),
1670
- signalParent: (signal, payload) => this.signalExternal({ parent: true }, chunkELL2RBML_cjs.signalName(signal), payload),
2439
+ signalRun: (target, signal, payload) => this.signalExternal(this.externalTarget(target), chunkZCGKGDCL_cjs.signalName(signal), payload),
2440
+ signalParent: (signal, payload) => this.signalExternal({ parent: true }, chunkZCGKGDCL_cjs.signalName(signal), payload),
1671
2441
  getRunHandle: (target) => this.runHandle(target),
1672
2442
  cancelRun: (target) => this.cancelExternal(this.externalTarget(target)),
1673
2443
  now: () => this.clock,
1674
2444
  random: () => this.random(),
1675
- uuid: () => chunkL24YIZY7_cjs.uuidFrom(this.random),
2445
+ uuid: () => {
2446
+ this.assertWritable("ctx.uuid()");
2447
+ return chunkL24YIZY7_cjs.uuidFrom(this.randomSource);
2448
+ },
1676
2449
  sideEffect: (fn) => this.sideEffect(fn),
1677
2450
  patched: (patchId) => this.patched(patchId, false),
1678
2451
  deprecatePatch: (patchId) => {
@@ -1680,13 +2453,7 @@ ${entry.stack}`).join("\n\n")
1680
2453
  },
1681
2454
  setCurrentDetails: (markdown) => this.setCurrentDetails(markdown),
1682
2455
  upsertContext: (entries) => this.upsertContext(entries),
1683
- continueAsNew: (input, options = {}) => {
1684
- try {
1685
- return Promise.reject(this.continueAsNew(input, options));
1686
- } catch (error) {
1687
- return Promise.reject(error);
1688
- }
1689
- },
2456
+ continueAsNew: (input, options = {}) => this.continueAsNewCall(input, options),
1690
2457
  cancellationScope: scopeFn,
1691
2458
  nonCancellable: (fn) => this.cancellationScope(scope(), fn, { nonCancellable: true }),
1692
2459
  onCancel: (fn) => {
@@ -1698,7 +2465,7 @@ ${entry.stack}`).join("\n\n")
1698
2465
  }
1699
2466
  });
1700
2467
  },
1701
- isCancellation: (error) => chunkELL2RBML_cjs.isCancellation(error),
2468
+ isCancellation: (error) => chunkZCGKGDCL_cjs.isCancellation(error),
1702
2469
  saga: () => {
1703
2470
  const compensations = [];
1704
2471
  return {
@@ -1722,11 +2489,14 @@ ${entry.stack}`).join("\n\n")
1722
2489
  };
1723
2490
  },
1724
2491
  allHandlersFinished: () => this.allHandlersFinished(),
1725
- activity: phaseC("ctx.activity (user activities)"),
2492
+ activity: (activity, options) => this.userActivity(scope(), activity, options),
1726
2493
  localActivity: ((operation, options) => this.localActivity(scope(), operation, options)),
1727
- handleQuery: phaseC("ctx.handleQuery (custom queries)"),
1728
- handleUpdate: phaseC("ctx.handleUpdate (updates)"),
1729
- upsertSearchAttributes: phaseC("ctx.upsertSearchAttributes (search attributes)")
2494
+ handleQuery: ((query, handler) => this.handleQuery(query, handler)),
2495
+ setDefaultQueryHandler: (handler) => this.setDefaultQueryHandler(handler),
2496
+ handleUpdate: ((update, handler, options) => this.handleUpdate(update, handler, options)),
2497
+ setDefaultUpdateHandler: ((first, second) => this.setDefaultUpdateHandler(first, second)),
2498
+ upsertSearchAttributes: (attributes) => this.upsertSearchAttributes(attributes),
2499
+ sinks: this.sinksProxy()
1730
2500
  };
1731
2501
  return Object.freeze(context);
1732
2502
  }
@@ -1738,21 +2508,40 @@ function buildWorkflowRegistry(modules) {
1738
2508
  const byName = /* @__PURE__ */ new Map();
1739
2509
  const exportNames = /* @__PURE__ */ new Map();
1740
2510
  const ambiguous = /* @__PURE__ */ new Set();
2511
+ const interceptors = [];
2512
+ let dynamic;
2513
+ let dynamicAmbiguous = false;
1741
2514
  for (const [, namespace] of modules) {
1742
2515
  for (const exportName of Object.keys(namespace).sort()) {
1743
2516
  const value = namespace[exportName];
1744
- if (!chunkJ3PYFGKA_cjs.isDurableWorkflow(value)) continue;
2517
+ if (exportName === "interceptors") {
2518
+ const factory = chunkVA4OFR72_cjs.interceptorsFactoryOf(value);
2519
+ if (factory !== void 0 && !interceptors.includes(factory)) interceptors.push(factory);
2520
+ continue;
2521
+ }
2522
+ if (!chunkVA4OFR72_cjs.isDurableWorkflow(value)) continue;
1745
2523
  const existing = byName.get(exportName);
1746
2524
  if (existing && existing !== value) ambiguous.add(exportName);
1747
2525
  byName.set(exportName, value);
1748
2526
  if (!exportNames.has(value)) exportNames.set(value, exportName);
2527
+ if (value.dynamic === true) {
2528
+ if (dynamic !== void 0 && dynamic !== value) dynamicAmbiguous = true;
2529
+ dynamic ??= value;
2530
+ }
1749
2531
  }
1750
2532
  }
1751
- return { byName, exportNames, ambiguous };
2533
+ return {
2534
+ byName,
2535
+ exportNames,
2536
+ ambiguous,
2537
+ ...dynamic !== void 0 ? { dynamic } : {},
2538
+ ...dynamicAmbiguous ? { dynamicAmbiguous } : {},
2539
+ ...interceptors.length > 0 ? { interceptors } : {}
2540
+ };
1752
2541
  }
1753
2542
  function failedResult(cause, message) {
1754
2543
  return {
1755
- protocol: chunk3FIDHONL_cjs.HISTORY_PROTOCOL,
2544
+ protocol: chunkTYF56RGB_cjs.HISTORY_PROTOCOL,
1756
2545
  outcome: "failed",
1757
2546
  commands: [],
1758
2547
  failure: { cause, message },
@@ -1777,6 +2566,23 @@ function checkRequest(value) {
1777
2566
  }
1778
2567
  if (typeof value["nowMs"] !== "number" || !Number.isFinite(value["nowMs"]))
1779
2568
  return "nowMs must be a number";
2569
+ const updates = value["updates"];
2570
+ if (updates !== void 0) {
2571
+ if (!Array.isArray(updates)) return "updates must be an array";
2572
+ for (const [index, update] of updates.entries())
2573
+ if (!isObject(update) || typeof update["updateId"] !== "string" || update["updateId"] === "" || typeof update["name"] !== "string")
2574
+ return `updates[${index}] needs an updateId and a name`;
2575
+ }
2576
+ const queries = value["queries"];
2577
+ if (queries !== void 0) {
2578
+ if (!Array.isArray(queries)) return "queries must be an array";
2579
+ for (const [index, query] of queries.entries())
2580
+ if (!isObject(query) || typeof query["queryId"] !== "string" || typeof query["name"] !== "string")
2581
+ return `queries[${index}] needs a queryId and a name`;
2582
+ }
2583
+ const features = value["features"];
2584
+ if (features !== void 0 && (!Array.isArray(features) || !features.every((feature) => typeof feature === "string")))
2585
+ return "features must be an array of strings";
1780
2586
  return value;
1781
2587
  }
1782
2588
  function createWorkflowRuntime(registry, shims = void 0) {
@@ -1785,14 +2591,15 @@ function createWorkflowRuntime(registry, shims = void 0) {
1785
2591
  const internalFailure = (error) => {
1786
2592
  const message = error instanceof Error ? error.message : String(error);
1787
2593
  const stack = error instanceof Error ? error.stack : void 0;
1788
- if (error instanceof chunkELL2RBML_cjs.HistoryLimitExceeded) execution?.failTask("HISTORY_LIMIT", message, stack);
1789
- else if (error instanceof chunkELL2RBML_cjs.DeterminismViolation || error instanceof Error && error.name === "DeterminismViolation")
2594
+ if (error instanceof chunkZCGKGDCL_cjs.HistoryLimitExceeded) execution?.failTask("HISTORY_LIMIT", message, stack);
2595
+ else if (error instanceof chunkZCGKGDCL_cjs.DeterminismViolation || error instanceof Error && error.name === "DeterminismViolation")
1790
2596
  execution?.failTask("NON_DETERMINISM", message, stack);
1791
2597
  else execution?.failTask("INTERNAL", message, stack);
1792
2598
  };
1793
2599
  return Object.freeze({
1794
- protocol: chunk3FIDHONL_cjs.HISTORY_PROTOCOL,
1795
- sdkVersion: chunkJ3PYFGKA_cjs.SDK_VERSION,
2600
+ protocol: chunkTYF56RGB_cjs.HISTORY_PROTOCOL,
2601
+ sdkVersion: chunkVA4OFR72_cjs.SDK_VERSION,
2602
+ capabilities: Object.freeze([...chunkTYF56RGB_cjs.RUNTIME_CAPABILITIES]),
1796
2603
  start(requestJson) {
1797
2604
  shims?.detach();
1798
2605
  execution = void 0;
@@ -1807,10 +2614,10 @@ function createWorkflowRuntime(registry, shims = void 0) {
1807
2614
  );
1808
2615
  return;
1809
2616
  }
1810
- if (isObject(parsed) && parsed["protocol"] !== chunk3FIDHONL_cjs.HISTORY_PROTOCOL) {
2617
+ if (isObject(parsed) && parsed["protocol"] !== chunkTYF56RGB_cjs.HISTORY_PROTOCOL) {
1811
2618
  early = failedResult(
1812
2619
  "PROTOCOL_MISMATCH",
1813
- `This bundle speaks runtime protocol ${chunk3FIDHONL_cjs.HISTORY_PROTOCOL}; the request uses ${String(parsed["protocol"])}`
2620
+ `This bundle speaks runtime protocol ${chunkTYF56RGB_cjs.HISTORY_PROTOCOL}; the request uses ${String(parsed["protocol"])}`
1814
2621
  );
1815
2622
  return;
1816
2623
  }
@@ -1826,7 +2633,15 @@ function createWorkflowRuntime(registry, shims = void 0) {
1826
2633
  );
1827
2634
  return;
1828
2635
  }
1829
- const definition = registry.byName.get(request.workflowFn);
2636
+ const exported = registry.byName.get(request.workflowFn);
2637
+ if (!exported && registry.dynamic !== void 0 && registry.dynamicAmbiguous === true) {
2638
+ early = failedResult(
2639
+ "INVALID_REQUEST",
2640
+ `More than one module exports a dynamic workflow; "${request.workflowFn}" cannot be served`
2641
+ );
2642
+ return;
2643
+ }
2644
+ const definition = exported ?? registry.dynamic;
1830
2645
  if (!definition) {
1831
2646
  early = failedResult(
1832
2647
  "INVALID_REQUEST",
@@ -1839,7 +2654,8 @@ function createWorkflowRuntime(registry, shims = void 0) {
1839
2654
  definition,
1840
2655
  exportNames: registry.exportNames,
1841
2656
  request,
1842
- sdkVersion: chunkJ3PYFGKA_cjs.SDK_VERSION
2657
+ sdkVersion: chunkVA4OFR72_cjs.SDK_VERSION,
2658
+ ...registry.interceptors !== void 0 ? { interceptors: registry.interceptors } : {}
1843
2659
  });
1844
2660
  execution = created;
1845
2661
  shims?.attach({ now: () => created.now(), random: () => created.nextRandom() });