@requence/task 0.7.1 → 0.8.2-edge.1149

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 (95) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +5 -5
  3. package/build/{chunk-b4h2we9a.js → chunk-f7g9gsa0.js} +33 -3
  4. package/build/chunk-f7g9gsa0.js.map +11 -0
  5. package/build/cli.js +18 -8
  6. package/build/cli.js.map +3 -3
  7. package/build/index.js +1062 -502
  8. package/build/index.js.map +27 -16
  9. package/build/types/helpers/src/index.d.ts +8 -2
  10. package/build/types/helpers/src/index.d.ts.map +1 -1
  11. package/build/types/helpers/src/jsonschema/validate.d.ts +1 -5
  12. package/build/types/helpers/src/jsonschema/validate.d.ts.map +1 -1
  13. package/build/types/helpers/src/jsonschema/zod.d.ts +11 -1
  14. package/build/types/helpers/src/jsonschema/zod.d.ts.map +1 -1
  15. package/build/types/helpers/src/protocol/NodeTree.d.ts +532 -148
  16. package/build/types/helpers/src/protocol/NodeTree.d.ts.map +1 -1
  17. package/build/types/helpers/src/protocol/clientProperties.d.ts +66 -0
  18. package/build/types/helpers/src/protocol/clientProperties.d.ts.map +1 -0
  19. package/build/types/helpers/src/protocol/command.d.ts +372 -142
  20. package/build/types/helpers/src/protocol/command.d.ts.map +1 -1
  21. package/build/types/helpers/src/protocol/configurationScript.d.ts +10 -0
  22. package/build/types/helpers/src/protocol/configurationScript.d.ts.map +1 -0
  23. package/build/types/helpers/src/protocol/helpers.d.ts.map +1 -1
  24. package/build/types/helpers/src/protocol/index.d.ts +5 -0
  25. package/build/types/helpers/src/protocol/index.d.ts.map +1 -1
  26. package/build/types/helpers/src/protocol/logicLanguages.d.ts +19 -0
  27. package/build/types/helpers/src/protocol/logicLanguages.d.ts.map +1 -0
  28. package/build/types/helpers/src/protocol/loopDetection.d.ts +23 -0
  29. package/build/types/helpers/src/protocol/loopDetection.d.ts.map +1 -0
  30. package/build/types/helpers/src/protocol/nodeType.d.ts +81 -27
  31. package/build/types/helpers/src/protocol/nodeType.d.ts.map +1 -1
  32. package/build/types/helpers/src/protocol/taskOptions.d.ts +4 -1
  33. package/build/types/helpers/src/protocol/taskOptions.d.ts.map +1 -1
  34. package/build/types/helpers/src/protocol/templateNodeTypes.d.ts +36 -20
  35. package/build/types/helpers/src/protocol/templateNodeTypes.d.ts.map +1 -1
  36. package/build/types/helpers/src/protocol/treeNodes.d.ts +508 -164
  37. package/build/types/helpers/src/protocol/treeNodes.d.ts.map +1 -1
  38. package/build/types/helpers/src/protocol/update.d.ts +40 -24
  39. package/build/types/helpers/src/protocol/update.d.ts.map +1 -1
  40. package/build/types/helpers/src/protocol/validateTreeStructure.d.ts +22 -0
  41. package/build/types/helpers/src/protocol/validateTreeStructure.d.ts.map +1 -0
  42. package/build/types/helpers/src/utils/amqpHeartbeat.d.ts +3 -0
  43. package/build/types/helpers/src/utils/amqpHeartbeat.d.ts.map +1 -0
  44. package/build/types/helpers/src/utils/amqpPublishRetry.d.ts +45 -0
  45. package/build/types/helpers/src/utils/amqpPublishRetry.d.ts.map +1 -0
  46. package/build/types/helpers/src/utils/claimCheckObject.d.ts +40 -0
  47. package/build/types/helpers/src/utils/claimCheckObject.d.ts.map +1 -0
  48. package/build/types/helpers/src/utils/debounce.d.ts.map +1 -1
  49. package/build/types/helpers/src/{files → utils}/fileObject.d.ts.map +1 -1
  50. package/build/types/helpers/src/{files → utils}/isValidMimeType.d.ts.map +1 -1
  51. package/build/types/helpers/src/utils/mapData.d.ts +1 -1
  52. package/build/types/helpers/src/utils/mapData.d.ts.map +1 -1
  53. package/build/types/helpers/src/{files → utils}/streamObject.d.ts.map +1 -1
  54. package/build/types/helpers/src/utils/variableRef.d.ts +19 -0
  55. package/build/types/helpers/src/utils/variableRef.d.ts.map +1 -0
  56. package/build/types/helpers/src/utils/variableScriptPatterns.d.ts +125 -0
  57. package/build/types/helpers/src/utils/variableScriptPatterns.d.ts.map +1 -0
  58. package/build/types/task/src/abortTask.d.ts.map +1 -1
  59. package/build/types/task/src/ackTask.d.ts.map +1 -1
  60. package/build/types/task/src/createTask.d.ts +0 -1
  61. package/build/types/task/src/createTask.d.ts.map +1 -1
  62. package/build/types/task/src/errors.d.ts +27 -0
  63. package/build/types/task/src/errors.d.ts.map +1 -0
  64. package/build/types/task/src/getTask.d.ts +4 -4
  65. package/build/types/task/src/getTask.d.ts.map +1 -1
  66. package/build/types/task/src/index.d.ts +2 -1
  67. package/build/types/task/src/index.d.ts.map +1 -1
  68. package/build/types/task/src/ingress.d.ts +26 -0
  69. package/build/types/task/src/ingress.d.ts.map +1 -0
  70. package/build/types/task/src/protectTask.d.ts.map +1 -1
  71. package/build/types/task/src/recreateTask.d.ts +1 -1
  72. package/build/types/task/src/recreateTask.d.ts.map +1 -1
  73. package/build/types/task/src/types.d.ts +10 -10
  74. package/build/types/task/src/utils/getAccessToken.d.ts.map +1 -1
  75. package/build/types/task/src/watchTasks.d.ts +2 -0
  76. package/build/types/task/src/watchTasks.d.ts.map +1 -1
  77. package/package.json +7 -3
  78. package/build/chunk-b4h2we9a.js.map +0 -10
  79. package/build/types/helpers/src/files/RequenceFile.d.ts +0 -40
  80. package/build/types/helpers/src/files/RequenceFile.d.ts.map +0 -1
  81. package/build/types/helpers/src/files/RequenceStream.d.ts +0 -32
  82. package/build/types/helpers/src/files/RequenceStream.d.ts.map +0 -1
  83. package/build/types/helpers/src/files/index.d.ts +0 -7
  84. package/build/types/helpers/src/files/index.d.ts.map +0 -1
  85. package/build/types/helpers/src/files/mapOutput.d.ts +0 -10
  86. package/build/types/helpers/src/files/mapOutput.d.ts.map +0 -1
  87. package/build/types/helpers/src/files/types.d.ts +0 -4
  88. package/build/types/helpers/src/files/types.d.ts.map +0 -1
  89. package/build/types/helpers/src/utils/createObjectProxy.d.ts +0 -2
  90. package/build/types/helpers/src/utils/createObjectProxy.d.ts.map +0 -1
  91. package/build/types/helpers/src/utils/resolveRequenceTypes.d.ts +0 -8
  92. package/build/types/helpers/src/utils/resolveRequenceTypes.d.ts.map +0 -1
  93. /package/build/types/helpers/src/{files → utils}/fileObject.d.ts +0 -0
  94. /package/build/types/helpers/src/{files → utils}/isValidMimeType.d.ts +0 -0
  95. /package/build/types/helpers/src/{files → utils}/streamObject.d.ts +0 -0
package/build/index.js CHANGED
@@ -1,216 +1,203 @@
1
1
  import {
2
- deobfuscate
3
- } from "./chunk-b4h2we9a.js";
2
+ RequenceUnreachableError,
3
+ deobfuscate,
4
+ isUnreachableStatus,
5
+ reachableFetch
6
+ } from "./chunk-f7g9gsa0.js";
4
7
 
5
- // ../helpers/src/utils/callbackToAsyncIterator.ts
6
- function callbackToAsyncIterator(subscribe) {
7
- const pullQueue = [];
8
- const pushQueue = [];
9
- let done = false;
10
- const pushValue = (value) => {
11
- if (pullQueue.length !== 0) {
12
- const resolver = pullQueue.shift();
13
- resolver(value);
14
- } else {
15
- pushQueue.push(value);
16
- }
17
- };
18
- const pullValue = () => new Promise((resolve) => {
19
- if (pushQueue.length !== 0) {
20
- resolve(pushQueue.shift());
21
- } else {
22
- pullQueue.push(resolve);
23
- }
24
- });
25
- const cleanup = subscribe((value) => {
26
- if (!done) {
27
- pushValue({ value });
28
- }
29
- }, (error) => {
30
- if (!done) {
31
- pushValue({ error });
32
- }
33
- }, () => {
34
- if (!done) {
35
- pushValue({ done: true });
36
- }
37
- });
38
- return {
39
- async next() {
40
- if (done) {
41
- return { value: undefined, done: true };
42
- }
43
- const value = await pullValue();
44
- if (value.done) {
45
- done = true;
46
- return { value: undefined, done: true };
8
+ // ../files/src/errors.ts
9
+ class RequenceStreamTruncatedError extends Error {
10
+ constructor(message = "stream truncated") {
11
+ super(message);
12
+ this.name = "RequenceStreamTruncatedError";
13
+ }
14
+ }
15
+
16
+ // ../files/src/streamFraming.ts
17
+ var STREAM_PROTOCOL_HEADER = "x-requence-stream-protocol";
18
+ var STREAM_PROTOCOL_FRAMED = "framed";
19
+ var DATA = 0;
20
+ var END = 1;
21
+ var TRUNCATED = 2;
22
+ var HEADER_BYTES = 5;
23
+ var END_FRAME = new Uint8Array([END, 0, 0, 0, 0]);
24
+ function createFrameDecoder() {
25
+ let buffer = new Uint8Array(0);
26
+ let terminal = false;
27
+ return new TransformStream({
28
+ transform(chunk, controller) {
29
+ if (terminal) {
30
+ if (chunk.byteLength > 0) {
31
+ throw new Error("stream protocol error: bytes after terminal frame");
32
+ }
33
+ return;
47
34
  }
48
- if (value.error) {
49
- done = true;
50
- throw value.error;
35
+ if (buffer.byteLength === 0) {
36
+ buffer = chunk;
37
+ } else {
38
+ const merged = new Uint8Array(buffer.byteLength + chunk.byteLength);
39
+ merged.set(buffer, 0);
40
+ merged.set(chunk, buffer.byteLength);
41
+ buffer = merged;
51
42
  }
52
- return { value: value.value, done: false };
53
- },
54
- async return() {
55
- if (!done) {
56
- done = true;
57
- if (typeof cleanup === "function") {
58
- cleanup();
43
+ while (buffer.byteLength >= HEADER_BYTES) {
44
+ const type = buffer[0];
45
+ const length = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength).getUint32(1, false);
46
+ if (buffer.byteLength < HEADER_BYTES + length) {
47
+ break;
59
48
  }
60
- while (pullQueue.length > 0) {
61
- const resolver = pullQueue.shift();
62
- resolver({ done: true });
49
+ const payload = buffer.slice(HEADER_BYTES, HEADER_BYTES + length);
50
+ buffer = buffer.subarray(HEADER_BYTES + length);
51
+ switch (type) {
52
+ case DATA: {
53
+ if (payload.byteLength > 0) {
54
+ controller.enqueue(payload);
55
+ }
56
+ break;
57
+ }
58
+ case END: {
59
+ terminal = true;
60
+ if (buffer.byteLength > 0) {
61
+ throw new Error("stream protocol error: bytes after terminal frame");
62
+ }
63
+ controller.terminate();
64
+ return;
65
+ }
66
+ case TRUNCATED: {
67
+ terminal = true;
68
+ controller.error(new RequenceStreamTruncatedError(new TextDecoder().decode(payload) || undefined));
69
+ return;
70
+ }
71
+ default: {
72
+ throw new Error(`stream protocol error: unknown frame type ${type}`);
73
+ }
63
74
  }
64
75
  }
65
- return { value: undefined, done: true };
76
+ },
77
+ flush(controller) {
78
+ if (!terminal) {
79
+ controller.error(new RequenceStreamTruncatedError("connection closed before terminal frame"));
80
+ }
66
81
  }
67
- };
82
+ });
68
83
  }
69
- function callbackToAsyncIterable(...args) {
70
- let iterator;
71
- return {
72
- [Symbol.asyncIterator]() {
73
- iterator ??= callbackToAsyncIterator(...args);
74
- return iterator;
84
+
85
+ // ../files/src/remoteBody.ts
86
+ function remoteBody(url, options = {}) {
87
+ const externalSignal = options.signal;
88
+ const timeoutMs = options.stallTimeoutMs && options.stallTimeoutMs > 0 ? options.stallTimeoutMs : 0;
89
+ const controller = new AbortController;
90
+ let reader = null;
91
+ let timer;
92
+ let onExternalAbort;
93
+ const clearTimer = () => {
94
+ if (timer !== undefined) {
95
+ clearTimeout(timer);
96
+ timer = undefined;
75
97
  }
76
98
  };
77
- }
78
-
79
- // ../helpers/src/utils/guards.ts
80
- import { z } from "zod/v4";
81
- var recordSchema = z.record(z.string(), z.unknown());
82
- function isRecord(data) {
83
- return recordSchema.safeParse(data).success;
84
- }
85
- var uuidSchema = z.uuid();
86
-
87
- // ../helpers/src/utils/mapData.ts
88
- function resolve(value, onResolve) {
89
- if (value instanceof Promise) {
90
- return Promise.resolve().then(() => value).then(onResolve);
99
+ const cleanup = () => {
100
+ clearTimer();
101
+ if (externalSignal && onExternalAbort) {
102
+ externalSignal.removeEventListener("abort", onExternalAbort);
103
+ }
104
+ };
105
+ if (externalSignal) {
106
+ if (externalSignal.aborted) {
107
+ controller.abort(externalSignal.reason);
108
+ } else {
109
+ onExternalAbort = () => controller.abort(externalSignal.reason);
110
+ externalSignal.addEventListener("abort", onExternalAbort, {
111
+ once: true
112
+ });
113
+ }
91
114
  }
92
- return onResolve(value);
93
- }
94
- function notUndefined(value, fallback) {
95
- return resolve(value, (resolvedValue) => typeof resolvedValue === "undefined" ? fallback : resolvedValue);
96
- }
97
-
98
- class AbortMapData extends Error {
99
- }
100
- function mapData(data, visitors) {
101
- let aborted = false;
102
- const traverseData = (data2, path) => {
103
- if (aborted) {
104
- return data2;
115
+ const armTimer = () => {
116
+ if (timeoutMs <= 0) {
117
+ return;
105
118
  }
106
- try {
107
- if (Array.isArray(data2)) {
108
- return resolve(visitors.Array?.(data2, path), (resolvedData) => {
109
- if (resolvedData) {
110
- return resolvedData;
111
- }
112
- const items = data2.map((item, index) => traverseData(item, [...path, index]));
113
- if (items.some((item) => item instanceof Promise)) {
114
- return Promise.all(items);
115
- }
116
- return items;
119
+ clearTimer();
120
+ timer = setTimeout(() => {
121
+ controller.abort(new Error(`remote read stalled: no data for ${timeoutMs}ms`));
122
+ }, timeoutMs);
123
+ };
124
+ return new ReadableStream({
125
+ async start(streamController) {
126
+ let response;
127
+ try {
128
+ response = await fetch(url, {
129
+ signal: controller.signal,
130
+ headers: options.framed ? { [STREAM_PROTOCOL_HEADER]: STREAM_PROTOCOL_FRAMED } : undefined
117
131
  });
132
+ } catch (error) {
133
+ cleanup();
134
+ streamController.error(error);
135
+ return;
118
136
  }
119
- if (data2 === null) {
120
- return notUndefined(visitors.Null?.(data2, path), data2);
121
- }
122
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(data2)) {
123
- return notUndefined(visitors.Buffer?.(data2, path), data2);
124
- }
125
- if (typeof data2 === "string") {
126
- return notUndefined(visitors.String?.(data2, path), data2);
127
- }
128
- if (typeof data2 === "number") {
129
- return notUndefined(visitors.Number?.(data2, path), data2);
130
- }
131
- if (typeof data2 === "symbol") {
132
- return notUndefined(visitors.Symbol?.(data2, path), data2);
137
+ if (!response.ok) {
138
+ await response.body?.cancel();
139
+ cleanup();
140
+ streamController.error(new Error(`remote read failed: ${response.status} ${response.statusText}`));
141
+ return;
133
142
  }
134
- if (typeof data2 === "function") {
135
- return notUndefined(visitors.Function?.(data2, path), data2);
143
+ if (!response.body) {
144
+ cleanup();
145
+ streamController.error(new Error("remote read response has no body"));
146
+ return;
136
147
  }
137
- if (isRecord(data2)) {
138
- return resolve(visitors.Object?.(structuredClone(data2), path), (resolvedData) => {
139
- const nextData = resolvedData ?? data2;
140
- if (!isRecord(nextData)) {
141
- return nextData;
142
- }
143
- const entries = Object.entries(nextData).map(([key, value]) => [
144
- key,
145
- traverseData(value, [...path, key])
146
- ]);
147
- if (entries.some(([, value]) => value instanceof Promise)) {
148
- return Promise.all(entries.map(([key, value]) => Promise.resolve().then(() => value).then((resolvedValue) => [key, resolvedValue]))).then((entries2) => Object.fromEntries(entries2));
149
- }
150
- return Object.fromEntries(entries);
151
- });
152
- }
153
- if (typeof data2 === "object" && data2) {
154
- return notUndefined(visitors.Object?.(data2, path), data2);
148
+ const framed = options.framed && response.headers.get(STREAM_PROTOCOL_HEADER) === STREAM_PROTOCOL_FRAMED;
149
+ reader = framed ? response.body.pipeThrough(createFrameDecoder()).getReader() : response.body.getReader();
150
+ },
151
+ async pull(streamController) {
152
+ if (!reader) {
153
+ return;
155
154
  }
156
- return data2;
157
- } catch (error) {
158
- if (error instanceof AbortMapData) {
159
- aborted = true;
160
- return data2;
155
+ armTimer();
156
+ try {
157
+ const { done, value } = await reader.read();
158
+ clearTimer();
159
+ if (done) {
160
+ cleanup();
161
+ streamController.close();
162
+ return;
163
+ }
164
+ streamController.enqueue(value);
165
+ } catch (error) {
166
+ clearTimer();
167
+ cleanup();
168
+ streamController.error(error);
161
169
  }
162
- throw error;
170
+ },
171
+ async cancel(reason) {
172
+ cleanup();
173
+ controller.abort(reason);
174
+ await reader?.cancel(reason);
163
175
  }
164
- };
165
- return traverseData(data, []);
166
- }
167
- mapData.abort = () => {
168
- throw new AbortMapData;
169
- };
170
-
171
- // ../helpers/src/utils/requenceCallback.ts
172
- import { z as z2 } from "zod/v4";
173
- var callbackObjectSchema = z2.object({
174
- sourceId: z2.string(),
175
- outputName: z2.string().nullable(),
176
- propertyPath: z2.array(z2.union([z2.string(), z2.int()])),
177
- callbackId: z2.uuid(),
178
- __REQUENCE_type: z2.literal("RequenceCallback")
179
- });
180
- function isCallbackObject(data) {
181
- return callbackObjectSchema.safeParse(data).success;
176
+ });
182
177
  }
183
178
 
184
- // ../helpers/src/files/fileObject.ts
185
- import { z as z3 } from "zod/v4";
186
- var fileObjectSchema = z3.object({
187
- size: z3.int().positive(),
188
- mime: z3.string(),
189
- url: z3.url(),
190
- __REQUENCE_type: z3.literal("RequenceFile")
191
- });
192
- function toFileObject(fileInfo) {
193
- return {
194
- ...fileInfo,
195
- __REQUENCE_type: "RequenceFile"
196
- };
197
- }
198
- function isFileObject(data) {
199
- return fileObjectSchema.safeParse(data).success;
179
+ // ../files/src/RequenceFile.ts
180
+ function stallTimeoutMs() {
181
+ const raw = typeof process !== "undefined" ? Number(process.env?.REQUENCE_FILE_STALL_TIMEOUT_MS) : Number.NaN;
182
+ return Number.isFinite(raw) && raw > 0 ? raw : 0;
200
183
  }
201
184
 
202
- // ../helpers/src/files/RequenceFile.ts
203
185
  class RequenceFile {
204
186
  #data;
205
187
  #file = null;
188
+ #signal;
206
189
  constructor(blobParts, options) {
207
190
  this.#data = new Blob(blobParts, options);
208
191
  }
209
- static fromFileObject(file) {
192
+ static fromFileObject(file, signal) {
210
193
  const instance = new this([], { type: "x/x" });
211
194
  instance.#file = file;
195
+ instance.#signal = signal;
212
196
  return instance;
213
197
  }
198
+ static canHandle(value) {
199
+ return value instanceof RequenceFile || value instanceof Blob;
200
+ }
214
201
  get fileObject() {
215
202
  return this.#file;
216
203
  }
@@ -226,39 +213,74 @@ class RequenceFile {
226
213
  get subMimeType() {
227
214
  return this.mimeType.split("/")[1];
228
215
  }
216
+ stream() {
217
+ if (!this.#file) {
218
+ return this.#data.stream();
219
+ }
220
+ return remoteBody(this.#file.url, {
221
+ signal: this.#signal,
222
+ stallTimeoutMs: stallTimeoutMs()
223
+ });
224
+ }
225
+ async#bytes() {
226
+ const reader = this.stream().getReader();
227
+ const chunks = [];
228
+ let total = 0;
229
+ for (;; ) {
230
+ const { done, value } = await reader.read();
231
+ if (done) {
232
+ break;
233
+ }
234
+ chunks.push(value);
235
+ total += value.byteLength;
236
+ }
237
+ const out = new Uint8Array(total);
238
+ let offset = 0;
239
+ for (const chunk of chunks) {
240
+ out.set(chunk, offset);
241
+ offset += chunk.byteLength;
242
+ }
243
+ return out;
244
+ }
229
245
  async text() {
230
246
  if (this.#file) {
231
- return fetch(this.#file.url).then((response) => response.text());
247
+ return new TextDecoder().decode(await this.#bytes());
232
248
  }
233
249
  return this.#data.text();
234
250
  }
235
251
  async json() {
236
252
  if (this.#file) {
237
- return fetch(this.#file.url).then((response) => response.json());
253
+ const text = await this.text();
254
+ try {
255
+ return JSON.parse(text);
256
+ } catch (error) {
257
+ throw new Error(`RequenceFile JSON parse failed for ${this.#file.url}`, { cause: error });
258
+ }
238
259
  }
239
260
  return JSON.parse(await this.text());
240
261
  }
241
262
  async blob() {
242
263
  if (this.#file) {
243
- return fetch(this.#file.url).then((response) => response.blob());
264
+ return new Blob([await this.#bytes()], { type: this.#file.mime });
244
265
  }
245
266
  return this.#data;
246
267
  }
247
268
  async arrayBuffer() {
248
269
  if (this.#file) {
249
- return fetch(this.#file.url).then((response) => response.arrayBuffer());
270
+ return (await this.#bytes()).buffer;
250
271
  }
251
272
  return this.#data.arrayBuffer();
252
273
  }
253
274
  toString() {
254
275
  return `RequenceFile<${this.mimeType}>`;
255
276
  }
256
- toJSON() {
257
- return `RequenceFile<${this.mimeType}>`;
258
- }
277
+ }
278
+ // ../files/src/RequenceStream.ts
279
+ function stallTimeoutMs2() {
280
+ const raw = typeof process !== "undefined" ? Number(process.env?.REQUENCE_STREAM_STALL_TIMEOUT_MS) : Number.NaN;
281
+ return Number.isFinite(raw) && raw > 0 ? raw : 0;
259
282
  }
260
283
 
261
- // ../helpers/src/files/RequenceStream.ts
262
284
  class RequenceStream {
263
285
  #data;
264
286
  #stream = null;
@@ -267,13 +289,17 @@ class RequenceStream {
267
289
  this.#data = stream;
268
290
  this.#options = options;
269
291
  }
270
- static fromStreamObject(stream) {
292
+ static fromStreamObject(stream, signal) {
271
293
  const instance = new this(null, {
272
- type: "x/x"
294
+ type: "x/x",
295
+ signal
273
296
  });
274
297
  instance.#stream = stream;
275
298
  return instance;
276
299
  }
300
+ static canHandle(value) {
301
+ return value instanceof RequenceStream || value instanceof Response;
302
+ }
277
303
  get streamObject() {
278
304
  return this.#stream;
279
305
  }
@@ -287,12 +313,14 @@ class RequenceStream {
287
313
  return this.mimeType.split("/")[1];
288
314
  }
289
315
  stream() {
290
- if (this.#stream) {
291
- const { readable, writable } = new TransformStream;
292
- fetch(this.#stream.url).then((response) => response.body?.pipeTo(writable));
293
- return readable;
316
+ if (!this.#stream) {
317
+ return this.#data;
294
318
  }
295
- return this.#data;
319
+ return remoteBody(this.#stream.url, {
320
+ signal: this.#options.signal,
321
+ stallTimeoutMs: stallTimeoutMs2(),
322
+ framed: true
323
+ });
296
324
  }
297
325
  asyncIterable() {
298
326
  const reader = this.stream().getReader();
@@ -306,6 +334,11 @@ class RequenceStream {
306
334
  reader.cancel();
307
335
  reader.releaseLock();
308
336
  return { done: true, value: null };
337
+ },
338
+ async throw() {
339
+ reader.cancel();
340
+ reader.releaseLock();
341
+ return { done: true, value: null };
309
342
  }
310
343
  };
311
344
  }
@@ -314,17 +347,105 @@ class RequenceStream {
314
347
  toString() {
315
348
  return `RequenceStream<${this.mimeType}>`;
316
349
  }
317
- toJSON() {
318
- return `RequenceStream<${this.mimeType}>`;
319
- }
350
+ }
351
+ // ../helpers/src/utils/callbackToAsyncIterator.ts
352
+ function callbackToAsyncIterator(subscribe) {
353
+ const pullQueue = [];
354
+ const pushQueue = [];
355
+ let done = false;
356
+ const pushValue = (value) => {
357
+ if (pullQueue.length !== 0) {
358
+ const resolver = pullQueue.shift();
359
+ resolver(value);
360
+ } else {
361
+ pushQueue.push(value);
362
+ }
363
+ };
364
+ const pullValue = () => new Promise((resolve) => {
365
+ if (pushQueue.length !== 0) {
366
+ resolve(pushQueue.shift());
367
+ } else {
368
+ pullQueue.push(resolve);
369
+ }
370
+ });
371
+ const cleanup = subscribe((value) => {
372
+ if (!done) {
373
+ pushValue({ value });
374
+ }
375
+ }, (error) => {
376
+ if (!done) {
377
+ pushValue({ error });
378
+ }
379
+ }, () => {
380
+ if (!done) {
381
+ pushValue({ done: true });
382
+ }
383
+ });
384
+ return {
385
+ async next() {
386
+ if (done) {
387
+ return { value: undefined, done: true };
388
+ }
389
+ const value = await pullValue();
390
+ if (value.done) {
391
+ done = true;
392
+ return { value: undefined, done: true };
393
+ }
394
+ if (value.error) {
395
+ done = true;
396
+ throw value.error;
397
+ }
398
+ return { value: value.value, done: false };
399
+ },
400
+ async return() {
401
+ if (!done) {
402
+ done = true;
403
+ if (typeof cleanup === "function") {
404
+ cleanup();
405
+ }
406
+ while (pullQueue.length > 0) {
407
+ const resolver = pullQueue.shift();
408
+ resolver({ done: true });
409
+ }
410
+ }
411
+ return { value: undefined, done: true };
412
+ }
413
+ };
414
+ }
415
+ function callbackToAsyncIterable(...args) {
416
+ let iterator;
417
+ return {
418
+ [Symbol.asyncIterator]() {
419
+ iterator ??= callbackToAsyncIterator(...args);
420
+ return iterator;
421
+ }
422
+ };
320
423
  }
321
424
 
322
- // ../helpers/src/files/streamObject.ts
323
- import { z as z4 } from "zod/v4";
324
- var streamObjectSchema = z4.object({
325
- mime: z4.string(),
326
- url: z4.string().url(),
327
- __REQUENCE_type: z4.literal("RequenceStream")
425
+ // ../helpers/src/utils/fileObject.ts
426
+ import { z } from "zod/v4";
427
+ var fileObjectSchema = z.object({
428
+ size: z.int().positive(),
429
+ mime: z.string(),
430
+ url: z.url(),
431
+ __REQUENCE_type: z.literal("RequenceFile")
432
+ });
433
+ function toFileObject(fileInfo) {
434
+ return {
435
+ ...fileInfo,
436
+ __REQUENCE_type: "RequenceFile"
437
+ };
438
+ }
439
+ function isFileObject(data) {
440
+ return fileObjectSchema.safeParse(data).success;
441
+ }
442
+
443
+ // ../helpers/src/utils/streamObject.ts
444
+ import { z as z2 } from "zod/v4";
445
+ var streamObjectSchema = z2.object({
446
+ mime: z2.string(),
447
+ url: z2.string().url(),
448
+ __REQUENCE_type: z2.literal("RequenceStream")
328
449
  });
329
450
  function isStreamObject(data) {
330
451
  return streamObjectSchema.safeParse(data).success;
@@ -336,131 +457,292 @@ function toStreamObject(streamInfo) {
336
457
  };
337
458
  }
338
459
 
339
- // ../helpers/src/files/mapOutput.ts
340
- async function upload(uploadUrl, body, signal, contentType) {
341
- const uploadResponse = await fetch(uploadUrl, {
460
+ // ../helpers/src/utils/claimCheckObject.ts
461
+ import { z as z3 } from "zod/v4";
462
+ var claimCheckObjectSchema = z3.object({
463
+ url: z3.url(),
464
+ size: z3.int().positive(),
465
+ __REQUENCE_type: z3.literal("ClaimCheck")
466
+ });
467
+ function toClaimCheckObject(info) {
468
+ return {
469
+ ...info,
470
+ __REQUENCE_type: "ClaimCheck"
471
+ };
472
+ }
473
+ function isClaimCheckObject(data) {
474
+ return claimCheckObjectSchema.safeParse(data).success;
475
+ }
476
+
477
+ // ../helpers/src/utils/requenceCallback.ts
478
+ import { z as z4 } from "zod/v4";
479
+ var callbackObjectSchema = z4.object({
480
+ sourceId: z4.string(),
481
+ outputName: z4.string().nullable(),
482
+ propertyPath: z4.array(z4.union([z4.string(), z4.int()])),
483
+ callbackId: z4.uuid(),
484
+ __REQUENCE_type: z4.literal("RequenceCallback")
485
+ });
486
+ function isCallbackObject(data) {
487
+ return callbackObjectSchema.safeParse(data).success;
488
+ }
489
+
490
+ // ../files/src/handlers/transport.ts
491
+ async function assertOk(res, url, phase) {
492
+ if (res.ok) {
493
+ return;
494
+ }
495
+ const detail = await res.text().catch(() => "");
496
+ throw new Error(`${phase} failed: ${res.status} ${res.statusText} (${url})${detail ? ` — ${detail}` : ""}`);
497
+ }
498
+
499
+ // ../files/src/handlers/fileHandler.ts
500
+ async function upload(ctx, uploadUrl, body, contentType, maxFileSize) {
501
+ const uploadResponse = await ctx.fetch(uploadUrl, {
342
502
  method: "POST",
343
- signal,
344
- headers: contentType ? {
345
- "Content-Type": contentType
346
- } : {},
503
+ signal: ctx.signal,
504
+ headers: {
505
+ ...contentType ? { "Content-Type": contentType } : {},
506
+ ...maxFileSize !== undefined ? { "file-size": String(maxFileSize) } : {}
507
+ },
347
508
  body
348
509
  });
510
+ await assertOk(uploadResponse, uploadUrl, "upload");
349
511
  const data = await uploadResponse.json();
350
- if (!data || typeof data !== "object") {
351
- throw new Error("invalid upload response");
512
+ if (!data || typeof data !== "object" || typeof data.url !== "string" || !data.url || typeof data.mime !== "string" || typeof data.size !== "number") {
513
+ throw new Error(`malformed upload response (${uploadUrl})`);
352
514
  }
353
515
  return toFileObject(data);
354
516
  }
355
- async function stream(streamUrl, stream2, signal, contentType) {
356
- const [testStream, dataStream] = stream2.tee();
357
- const reader = testStream.getReader();
358
- const dataPromise = reader.read().then(({ done: done2 }) => {
359
- if (done2) {
360
- throw new Error("No streaming date received");
517
+ function createRequenceFileHandler() {
518
+ return {
519
+ tag: "RequenceFile",
520
+ canHandle: (value) => RequenceFile.canHandle(value),
521
+ async serialize(value, ctx) {
522
+ if (value instanceof RequenceFile && value.fileObject) {
523
+ return value.fileObject;
524
+ }
525
+ if (!ctx.uploadUrl) {
526
+ ctx.onOffloadSkip?.();
527
+ return null;
528
+ }
529
+ try {
530
+ if (value instanceof RequenceFile) {
531
+ return await upload(ctx, ctx.uploadUrl, await value.blob(), value.mimeType, ctx.maxFileSize);
532
+ }
533
+ return await upload(ctx, ctx.uploadUrl, value, value.type, ctx.maxFileSize);
534
+ } catch (error) {
535
+ if (!(error instanceof Error)) {
536
+ throw error;
537
+ }
538
+ if (ctx.onOffloadFail) {
539
+ ctx.onOffloadFail(error);
540
+ return null;
541
+ }
542
+ throw error;
543
+ }
544
+ },
545
+ isReference: (value) => isFileObject(value),
546
+ deserialize(ref, ctx) {
547
+ return RequenceFile.fromFileObject(ref, ctx.signal);
361
548
  }
362
- reader.cancel();
363
- });
364
- const streamResponse = await fetch(streamUrl, {
549
+ };
550
+ }
551
+ // ../files/src/withRequenceStreams.ts
552
+ import { AsyncLocalStorage } from "node:async_hooks";
553
+ var pendingUploads = new AsyncLocalStorage;
554
+ async function withRequenceStreams(fn) {
555
+ const uploads = [];
556
+ const value = await pendingUploads.run(uploads, fn);
557
+ return { value, done: Promise.all(uploads).then(() => {
558
+ return;
559
+ }) };
560
+ }
561
+ function registerPendingUpload(work) {
562
+ const store = pendingUploads.getStore();
563
+ if (!store) {
564
+ return false;
565
+ }
566
+ store.push(work);
567
+ return true;
568
+ }
569
+
570
+ // ../files/src/handlers/streamHandler.ts
571
+ async function registerAndUpload(ctx, streamUrl, stream, contentType, maxFileSize) {
572
+ const [testStream, dataStream] = stream.tee();
573
+ const reader = testStream.getReader();
574
+ const { done: isEmpty } = await reader.read();
575
+ reader.cancel();
576
+ const streamResponse = await ctx.fetch(streamUrl, {
365
577
  method: "POST",
366
- signal,
367
- headers: contentType ? { "Content-Type": contentType } : {}
578
+ signal: ctx.signal,
579
+ headers: {
580
+ ...contentType ? { "Content-Type": contentType } : {},
581
+ ...maxFileSize !== undefined ? { "file-size": String(maxFileSize) } : {}
582
+ }
368
583
  });
584
+ await assertOk(streamResponse, streamUrl, "stream registration");
369
585
  const data = await streamResponse.json();
370
- if (!data || typeof data !== "object") {
371
- throw new Error("invalid stream response");
586
+ if (!isStreamObject(toStreamObject(data))) {
587
+ throw new Error(`malformed stream registration response (${streamUrl})`);
372
588
  }
373
589
  const { mime, url } = data;
374
- await dataPromise;
375
- const done = fetch(url, {
376
- method: "POST",
377
- signal,
378
- duplex: "half",
379
- body: dataStream
380
- });
381
- return [toStreamObject({ mime, url }), done];
590
+ if (isEmpty) {
591
+ const emptyResponse = await ctx.fetch(url, {
592
+ method: "POST",
593
+ signal: ctx.signal,
594
+ headers: contentType ? { "Content-Type": contentType } : {},
595
+ body: new Uint8Array(0)
596
+ });
597
+ await assertOk(emptyResponse, url, "stream body upload");
598
+ await emptyResponse.body?.cancel();
599
+ return { ref: toStreamObject({ mime, url }) };
600
+ }
601
+ const bodyUpload = (async () => {
602
+ const bodyResponse = await ctx.fetch(url, {
603
+ method: "POST",
604
+ signal: ctx.signal,
605
+ duplex: "half",
606
+ body: dataStream
607
+ });
608
+ await assertOk(bodyResponse, url, "stream body upload");
609
+ await bodyResponse.body?.cancel();
610
+ })();
611
+ return { ref: toStreamObject({ mime, url }), bodyUpload };
382
612
  }
383
- async function mapOutput(params) {
384
- const streamPromises = [];
385
- const mapped = await mapData(params.value, {
386
- async Object(obj) {
387
- if (obj instanceof Blob || obj instanceof RequenceFile) {
388
- if (obj instanceof RequenceFile && obj.fileObject) {
389
- return obj.fileObject;
390
- }
391
- if (params.options.uploadUrl) {
392
- try {
393
- if (obj instanceof Blob) {
394
- return await upload(params.options.uploadUrl, obj, params.signal, obj.type);
395
- }
396
- if (obj instanceof RequenceFile) {
397
- return await upload(params.options.uploadUrl, await obj.blob(), params.signal, obj.mimeType);
398
- }
399
- } catch (error) {
400
- if (!(error instanceof Error)) {
401
- throw error;
402
- }
403
- params.onFail?.(error);
404
- return null;
405
- }
406
- } else {
407
- params.onSkip?.();
408
- return null;
409
- }
613
+ function createRequenceStreamHandler() {
614
+ return {
615
+ tag: "RequenceStream",
616
+ canHandle: (value) => RequenceStream.canHandle(value),
617
+ async serialize(value, ctx) {
618
+ if (value instanceof RequenceStream && value.streamObject) {
619
+ return value.streamObject;
410
620
  }
411
- if (obj instanceof Response || obj instanceof RequenceStream) {
412
- if (obj instanceof RequenceStream && obj.streamObject) {
413
- return obj.streamObject;
621
+ if (!ctx.streamUrl) {
622
+ ctx.onOffloadSkip?.();
623
+ return null;
624
+ }
625
+ const body = value instanceof Response ? value.body ?? new ReadableStream({
626
+ start(controller) {
627
+ controller.close();
414
628
  }
415
- if (params.options.streamUrl) {
416
- try {
417
- if (obj instanceof Response && obj.body) {
418
- const [streamObject, streamPromise] = await stream(params.options.streamUrl, obj.body, params.signal, obj.headers.get("Content-Type"));
419
- streamPromises.push(streamPromise);
420
- return streamObject;
421
- }
422
- if (obj instanceof RequenceStream) {
423
- const [streamObject, streamPromise] = await stream(params.options.streamUrl, obj.stream(), params.signal, obj.mimeType);
424
- streamPromises.push(streamPromise);
425
- return streamObject;
426
- }
427
- } catch (error) {
428
- if (!(error instanceof Error)) {
429
- throw error;
430
- }
431
- params.onFail?.(error);
432
- return null;
433
- }
434
- } else {
435
- params.onSkip?.();
629
+ }) : value.stream();
630
+ const contentType = value instanceof Response ? value.headers.get("Content-Type") : value.mimeType;
631
+ try {
632
+ const { ref, bodyUpload } = await registerAndUpload(ctx, ctx.streamUrl, body, contentType, ctx.maxFileSize);
633
+ if (bodyUpload && !registerPendingUpload(bodyUpload)) {
634
+ await bodyUpload;
635
+ }
636
+ return ref;
637
+ } catch (error) {
638
+ if (!(error instanceof Error)) {
639
+ throw error;
640
+ }
641
+ if (ctx.onOffloadFail) {
642
+ ctx.onOffloadFail(error);
436
643
  return null;
437
644
  }
645
+ throw error;
438
646
  }
647
+ },
648
+ isReference: (value) => isStreamObject(value),
649
+ deserialize(ref, ctx) {
650
+ return RequenceStream.fromStreamObject(ref, ctx.signal);
439
651
  }
652
+ };
653
+ }
654
+ // ../files/src/handlers/claimCheckHandler.ts
655
+ import { Buffer } from "node:buffer";
656
+ var DEFAULT_MAX_PAYLOAD_SIZE = 4 * 1024 * 1024;
657
+ function isRecord(value) {
658
+ return typeof value === "object" && value !== null && !Array.isArray(value);
659
+ }
660
+ async function offload(ctx, uploadUrl, json) {
661
+ const response = await ctx.fetch(uploadUrl, {
662
+ method: "POST",
663
+ signal: ctx.signal,
664
+ headers: { "Content-Type": "application/json" },
665
+ body: json
440
666
  });
441
- Promise.allSettled(streamPromises).then(() => params.onDone?.());
442
- return mapped;
667
+ await assertOk(response, uploadUrl, "claim-check offload");
668
+ const data = await response.json();
669
+ if (!data || typeof data !== "object" || typeof data.url !== "string" || !data.url || typeof data.size !== "number") {
670
+ throw new Error(`malformed claim-check offload response (${uploadUrl})`);
671
+ }
672
+ return toClaimCheckObject({ url: data.url, size: data.size });
443
673
  }
444
-
445
- // ../helpers/src/utils/resolveRequenceTypes.ts
446
- function resolveRequenceTypes(data, onCallback) {
447
- return mapData(data, {
448
- Object(obj) {
449
- if (isFileObject(obj)) {
450
- return RequenceFile.fromFileObject(obj);
674
+ function jsonByteLength(value) {
675
+ const json = JSON.stringify(value);
676
+ return json === undefined ? 0 : Buffer.byteLength(json);
677
+ }
678
+ function createMessageHandler() {
679
+ return {
680
+ async wrapOutbound(body, ctx) {
681
+ const maxBytes = ctx.maxPayloadSize ?? DEFAULT_MAX_PAYLOAD_SIZE;
682
+ if (maxBytes <= 0 || body === undefined) {
683
+ return body;
451
684
  }
452
- if (isStreamObject(obj)) {
453
- return RequenceStream.fromStreamObject(obj);
685
+ const measure = ctx.measure ?? jsonByteLength;
686
+ if (measure(body) <= maxBytes) {
687
+ return body;
454
688
  }
455
- if (isCallbackObject(obj)) {
456
- return (arg) => {
457
- onCallback?.({ ...obj, arg });
458
- };
689
+ const { uploadUrl } = ctx;
690
+ if (!uploadUrl) {
691
+ ctx.onOffloadSkip?.();
692
+ return body;
693
+ }
694
+ if (!isRecord(body)) {
695
+ const json = JSON.stringify(body);
696
+ if (json === undefined) {
697
+ return body;
698
+ }
699
+ return offload(ctx, uploadUrl, json);
700
+ }
701
+ const entries = Object.entries(body).map(([key, value]) => ({
702
+ key,
703
+ valueJson: JSON.stringify(value),
704
+ size: measure(value)
705
+ })).sort((a, b) => b.size - a.size);
706
+ const wrapped = { ...body };
707
+ let total = measure(body);
708
+ for (const entry of entries) {
709
+ if (total <= maxBytes || entry.valueJson === undefined || entry.size <= 256) {
710
+ break;
711
+ }
712
+ const ref = await offload(ctx, uploadUrl, entry.valueJson);
713
+ wrapped[entry.key] = ref;
714
+ total += measure(ref) - entry.size;
459
715
  }
716
+ return wrapped;
460
717
  }
461
- });
718
+ };
719
+ }
720
+ function createValueHandler() {
721
+ return {
722
+ tag: "ClaimCheck",
723
+ canHandle: () => false,
724
+ serialize() {
725
+ throw new Error("ClaimCheck egress is the bundled MessageHandler (wrapOutbound); it never reaches the value walk");
726
+ },
727
+ isReference: (value) => isClaimCheckObject(value),
728
+ async deserialize(ref, ctx) {
729
+ const response = await ctx.fetch(ref.url, { signal: ctx.signal });
730
+ await assertOk(response, ref.url, "claim-check fetch");
731
+ const text = await response.text();
732
+ try {
733
+ return JSON.parse(text);
734
+ } catch {
735
+ throw new Error(`malformed claim-check payload (${ref.url})`);
736
+ }
737
+ }
738
+ };
739
+ }
740
+ function createClaimCheckHandler() {
741
+ return {
742
+ valueHandler: createValueHandler(),
743
+ messageHandler: createMessageHandler()
744
+ };
462
745
  }
463
-
464
746
  // src/createTask.ts
465
747
  import chalk from "chalk";
466
748
  import { createEventSource } from "eventsource-client";
@@ -500,7 +782,7 @@ class TaskAbortError extends Error {
500
782
  async function abortTask(options) {
501
783
  const { apiBaseUrl, token } = getAccessToken(options.accessToken);
502
784
  const abortUrl = `${apiBaseUrl}/task/abort/${options.taskId}`;
503
- const response = await fetch(abortUrl, {
785
+ const response = await reachableFetch(abortUrl, {
504
786
  method: "POST",
505
787
  body: options.reason ?? "",
506
788
  headers: {
@@ -515,7 +797,7 @@ async function abortTask(options) {
515
797
  // src/ackTask.ts
516
798
  async function ackTask(options) {
517
799
  const { apiBaseUrl, token } = getAccessToken(options.accessToken);
518
- const response = await fetch(`${apiBaseUrl}/task/ack/${options.taskId}`, {
800
+ const response = await reachableFetch(`${apiBaseUrl}/task/ack/${options.taskId}`, {
519
801
  method: "POST",
520
802
  headers: {
521
803
  Authorization: `Bearer ${token}`
@@ -526,6 +808,214 @@ async function ackTask(options) {
526
808
  }
527
809
  }
528
810
 
811
+ // ../callbacks/src/handler.ts
812
+ function createRequenceCallbackHandler() {
813
+ return {
814
+ tag: "RequenceCallback",
815
+ canHandle: (value) => typeof value === "function",
816
+ serialize(callback, ctx, path) {
817
+ if (!ctx.onCallback) {
818
+ throw new Error(`functions are not serializable on this boundary (no ctx.onCallback) at path "${path.join(".")}"`);
819
+ }
820
+ return {
821
+ ...ctx.onCallback(callback),
822
+ outputName: ctx.outputName ?? null,
823
+ propertyPath: [...path],
824
+ __REQUENCE_type: "RequenceCallback"
825
+ };
826
+ },
827
+ isReference: (value) => isCallbackObject(value),
828
+ deserialize(ref, ctx) {
829
+ return (arg) => {
830
+ ctx.onCallbackInvoke?.({ ...ref, arg });
831
+ };
832
+ }
833
+ };
834
+ }
835
+ // ../transformer/src/errors.ts
836
+ function formatPath(path) {
837
+ if (path.length === 0) {
838
+ return "<root>";
839
+ }
840
+ let out = "";
841
+ for (const segment of path) {
842
+ out += typeof segment === "number" ? `[${segment}]` : out ? `.${segment}` : segment;
843
+ }
844
+ return out;
845
+ }
846
+
847
+ class TransformError extends Error {
848
+ path;
849
+ detail;
850
+ constructor(detail, path) {
851
+ super(`${detail} at ${formatPath(path)}`);
852
+ this.name = "TransformError";
853
+ this.path = path;
854
+ this.detail = detail;
855
+ }
856
+ }
857
+
858
+ // ../transformer/src/guards.ts
859
+ var REFERENCE_TAG_KEY = "__REQUENCE_type";
860
+ function isPlainObject(value) {
861
+ if (value === null || typeof value !== "object") {
862
+ return false;
863
+ }
864
+ const proto = Object.getPrototypeOf(value);
865
+ return proto === null || proto === Object.prototype;
866
+ }
867
+ function isComplexValue(value) {
868
+ if (value === null) {
869
+ return false;
870
+ }
871
+ const type = typeof value;
872
+ if (type === "object") {
873
+ return !Array.isArray(value) && !isPlainObject(value);
874
+ }
875
+ return type === "function" || type === "symbol" || type === "bigint";
876
+ }
877
+ function hasReferenceTag(value) {
878
+ return isPlainObject(value) && REFERENCE_TAG_KEY in value;
879
+ }
880
+
881
+ // ../transformer/src/walk.ts
882
+ var recurse = { kind: "recurse" };
883
+ var replaceWith = (value) => ({
884
+ kind: "replace",
885
+ value
886
+ });
887
+ var MAX_REPLACE_DEPTH = 100;
888
+ async function walk(root, visit) {
889
+ const go = async (value, path, replaceDepth) => {
890
+ let node = value;
891
+ if (Array.isArray(node)) {
892
+ node = await Promise.all(node.map((item, index) => go(item, [...path, index], 0)));
893
+ } else if (isPlainObject(node)) {
894
+ const entries = await Promise.all(Object.entries(node).map(async ([key, item]) => [key, await go(item, [...path, key], 0)]));
895
+ node = Object.fromEntries(entries);
896
+ }
897
+ const verdict = await visit(node, path);
898
+ if (verdict.kind === "replace") {
899
+ if (replaceDepth >= MAX_REPLACE_DEPTH) {
900
+ throw new TransformError("transform did not reach a fixpoint (a handler keeps producing handleable output)", path);
901
+ }
902
+ return go(verdict.value, path, replaceDepth + 1);
903
+ }
904
+ return node;
905
+ };
906
+ return go(root, [], 0);
907
+ }
908
+
909
+ // ../transformer/src/transform.ts
910
+ function createTransformer() {
911
+ return build([], []);
912
+ }
913
+ function build(valueHandlers, messageHandlers) {
914
+ const transformer = {
915
+ withHandler(handler) {
916
+ const bundle = "tag" in handler ? { valueHandler: handler } : handler;
917
+ if (!bundle.valueHandler && !bundle.messageHandler) {
918
+ throw new Error("withHandler: bundle provides neither a valueHandler nor a messageHandler");
919
+ }
920
+ if (bundle.valueHandler) {
921
+ const { tag } = bundle.valueHandler;
922
+ if (valueHandlers.some((existing) => existing.tag === tag)) {
923
+ throw new Error(`withHandler: a ValueHandler with tag "${tag}" is already composed`);
924
+ }
925
+ }
926
+ return build(bundle.valueHandler ? [...valueHandlers, bundle.valueHandler] : valueHandlers, bundle.messageHandler ? [...messageHandlers, bundle.messageHandler] : messageHandlers);
927
+ },
928
+ async outbound(value, ctx) {
929
+ const seen = new Map;
930
+ const visit = (node, path) => {
931
+ if (!isComplexValue(node)) {
932
+ return recurse;
933
+ }
934
+ const handler = valueHandlers.find((candidate) => candidate.canHandle(node));
935
+ if (!handler) {
936
+ const withToJSON = node;
937
+ if (typeof node === "object" && typeof withToJSON.toJSON === "function") {
938
+ return replaceWith(withToJSON.toJSON());
939
+ }
940
+ const label = node?.constructor?.name ?? (typeof node === "function" ? "function" : typeof node);
941
+ throw new TransformError(`no composed ValueHandler for complex value of type ${label}`, path);
942
+ }
943
+ if (typeof node === "object" && node !== null) {
944
+ const cached = seen.get(node);
945
+ if (cached) {
946
+ return cached.then(replaceWith);
947
+ }
948
+ const pending = Promise.resolve(handler.serialize(node, ctx, path));
949
+ seen.set(node, pending);
950
+ return pending.then(replaceWith);
951
+ }
952
+ return Promise.resolve(handler.serialize(node, ctx, path)).then(replaceWith);
953
+ };
954
+ const valueTransformed = await walk(value, visit);
955
+ let body = valueTransformed;
956
+ for (const [index, handler] of messageHandlers.entries()) {
957
+ const wrapped = await handler.wrapOutbound(body, ctx);
958
+ assertTopLevelKeysPreserved(body, wrapped, index);
959
+ body = wrapped;
960
+ }
961
+ return body;
962
+ },
963
+ async inbound(value, ctx) {
964
+ const visit = (node, path) => {
965
+ if (!isPlainObject(node)) {
966
+ return recurse;
967
+ }
968
+ const handler = valueHandlers.find((candidate) => candidate.isReference(node));
969
+ if (handler) {
970
+ if (handler.passthrough) {
971
+ return recurse;
972
+ }
973
+ return Promise.resolve(handler.deserialize(node, ctx, path)).then(replaceWith);
974
+ }
975
+ if (hasReferenceTag(node)) {
976
+ const tag = node.__REQUENCE_type;
977
+ throw new TransformError(`no composed ValueHandler owns reference tag ${JSON.stringify(tag)}`, path);
978
+ }
979
+ return recurse;
980
+ };
981
+ return walk(value, visit);
982
+ }
983
+ };
984
+ return transformer;
985
+ }
986
+ function assertTopLevelKeysPreserved(body, wrapped, handlerIndex) {
987
+ if (!isPlainObject(body)) {
988
+ return;
989
+ }
990
+ const label = `MessageHandler #${handlerIndex}`;
991
+ if (!isPlainObject(wrapped)) {
992
+ throw new TransformError(`${label} replaced a record body wholesale — wrapOutbound must preserve a record's top-level keys`, []);
993
+ }
994
+ const before = Object.keys(body);
995
+ const after = new Set(Object.keys(wrapped));
996
+ const removed = before.filter((key) => !after.has(key));
997
+ const added = [...after].filter((key) => !before.includes(key));
998
+ if (removed.length > 0 || added.length > 0) {
999
+ throw new TransformError(`${label} changed a record body's top-level keys (removed: [${removed.join(", ")}], added: [${added.join(", ")}]) — wrapOutbound must preserve them`, []);
1000
+ }
1001
+ }
1002
+ // src/ingress.ts
1003
+ var transformer = createTransformer().withHandler(createRequenceFileHandler()).withHandler(createRequenceStreamHandler()).withHandler(createRequenceCallbackHandler()).withHandler(createClaimCheckHandler());
1004
+ var inbound = (data, opts = {}) => transformer.inbound(data, {
1005
+ fetch: globalThis.fetch,
1006
+ onCallbackInvoke: opts.onCallbackInvoke
1007
+ });
1008
+ var forbidCallbacks = {
1009
+ onCallbackInvoke: () => {
1010
+ throw new Error("input may not have callbacks");
1011
+ }
1012
+ };
1013
+ var observeOnlyCallbacks = {
1014
+ onCallbackInvoke: () => {
1015
+ throw new Error("callbacks in watched data cannot be invoked from a task client");
1016
+ }
1017
+ };
1018
+
529
1019
  // src/protectTask.ts
530
1020
  class TaskProtectError extends Error {
531
1021
  taskId;
@@ -537,7 +1027,7 @@ class TaskProtectError extends Error {
537
1027
  async function protectTask(options) {
538
1028
  const { apiBaseUrl, token } = getAccessToken(options.accessToken);
539
1029
  const protectUrl = `${apiBaseUrl}/task/protect/${options.taskId}`;
540
- const response = await fetch(protectUrl, {
1030
+ const response = await reachableFetch(protectUrl, {
541
1031
  method: "POST",
542
1032
  headers: {
543
1033
  Authorization: `Bearer ${token}`
@@ -670,6 +1160,7 @@ function createTask(options, onUpdate) {
670
1160
  let since = null;
671
1161
  let lastPosition = null;
672
1162
  let lastResponse;
1163
+ let processing = Promise.resolve();
673
1164
  const customFetch = async (url, init) => {
674
1165
  const response = await fetch(url, init);
675
1166
  lastResponse = response;
@@ -695,8 +1186,13 @@ function createTask(options, onUpdate) {
695
1186
  }
696
1187
  },
697
1188
  async onDisconnect() {
698
- if (lastResponse.status === 200) {
1189
+ if (lastResponse?.status === 200) {
699
1190
  eventSource.close();
1191
+ return;
1192
+ }
1193
+ if (lastResponse && isUnreachableStatus(lastResponse.status)) {
1194
+ eventSource.close();
1195
+ resultPromiseWithResolvers.reject(new RequenceUnreachableError(lastResponse.status));
700
1196
  }
701
1197
  },
702
1198
  onMessage({ id, event, data }) {
@@ -710,147 +1206,200 @@ function createTask(options, onUpdate) {
710
1206
  return;
711
1207
  }
712
1208
  const update = updateResult.data;
713
- switch (update.type) {
714
- case "taskStart": {
715
- taskStorage.input = resolveRequenceTypes(update.input, () => {
716
- throw new Error("input may not have callbacks");
717
- });
718
- break;
719
- }
720
- case "nodeUpdate": {
721
- if (update.node.alias) {
722
- taskStorage.data[update.node.alias] = resolveRequenceTypes(update.data);
723
- }
724
- break;
725
- }
726
- case "nodeError": {
727
- if (update.node.alias) {
728
- taskStorage.errors[update.node.alias] = update.error;
729
- }
730
- break;
731
- }
732
- case "taskEnd": {
733
- taskStorage.result = resolveRequenceTypes(update.result);
734
- eventSource.close();
735
- if (update.requireAck) {
736
- ackTask({
737
- taskId: payload.taskId,
738
- accessToken: options.accessToken
739
- }).catch(() => {});
740
- }
741
- break;
1209
+ processing = processing.then(() => applyUpdate(update)).catch((error) => {
1210
+ eventSource.close();
1211
+ resultPromiseWithResolvers.reject(new TaskError(error instanceof Error ? error.message : String(error), options.taskTemplate, payload.taskId));
1212
+ });
1213
+ }
1214
+ });
1215
+ async function applyUpdate(update) {
1216
+ switch (update.type) {
1217
+ case "taskStart": {
1218
+ taskStorage.input = await inbound(update.input, forbidCallbacks);
1219
+ break;
1220
+ }
1221
+ case "nodeUpdate": {
1222
+ if (update.node.alias) {
1223
+ taskStorage.data[update.node.alias] = await inbound(update.data, observeOnlyCallbacks);
742
1224
  }
743
- case "taskError":
744
- case "taskAborted": {
745
- eventSource.close();
746
- if (update.requireAck) {
747
- ackTask({
748
- taskId: payload.taskId,
749
- accessToken: options.accessToken
750
- }).catch(() => {});
751
- }
752
- break;
1225
+ break;
1226
+ }
1227
+ case "nodeError": {
1228
+ if (update.node.alias) {
1229
+ taskStorage.errors[update.node.alias] = update.error;
753
1230
  }
1231
+ break;
754
1232
  }
755
- const context = {
756
- taskId: update.taskId,
757
- input: taskStorage.input,
758
- getNodeData(alias) {
759
- return taskStorage.data[alias] ?? null;
760
- },
761
- getNodeError(alias) {
762
- return taskStorage.errors[alias] ?? null;
763
- },
764
- result: taskStorage.result
765
- };
766
- const contextUpdate = {
767
- ...update,
768
- context
769
- };
770
- if (contextUpdate.type === "taskEnd") {
771
- resultPromiseWithResolvers.resolve({
772
- ...context,
773
- taskUrl: payload.urls?.show ?? ""
774
- });
1233
+ case "taskEnd": {
1234
+ taskStorage.result = await inbound(update.result, observeOnlyCallbacks);
1235
+ eventSource.close();
1236
+ if (update.requireAck) {
1237
+ ackTask({
1238
+ taskId: payload.taskId,
1239
+ accessToken: options.accessToken
1240
+ }).catch(() => {});
1241
+ }
1242
+ break;
775
1243
  }
776
- if (contextUpdate.type === "taskError" || contextUpdate.type === "taskAborted") {
777
- resultPromiseWithResolvers.reject(new TaskError(contextUpdate.reason ?? (contextUpdate.type === "taskError" ? "Task failed" : "Task aborted"), options.taskTemplate, payload.taskId));
1244
+ case "taskError":
1245
+ case "taskAborted": {
1246
+ eventSource.close();
1247
+ if (update.requireAck) {
1248
+ ackTask({
1249
+ taskId: payload.taskId,
1250
+ accessToken: options.accessToken
1251
+ }).catch(() => {});
1252
+ }
1253
+ break;
778
1254
  }
779
- taskUpdateHandlers.forEach((handler) => handler(contextUpdate));
780
1255
  }
781
- });
1256
+ const context = {
1257
+ taskId: update.taskId,
1258
+ input: taskStorage.input,
1259
+ getNodeData(alias) {
1260
+ return taskStorage.data[alias] ?? null;
1261
+ },
1262
+ getNodeError(alias) {
1263
+ return taskStorage.errors[alias] ?? null;
1264
+ },
1265
+ result: taskStorage.result
1266
+ };
1267
+ const contextUpdate = {
1268
+ ...update,
1269
+ context
1270
+ };
1271
+ if (contextUpdate.type === "taskEnd") {
1272
+ resultPromiseWithResolvers.resolve({
1273
+ ...context,
1274
+ taskUrl: payload.urls?.show ?? ""
1275
+ });
1276
+ }
1277
+ if (contextUpdate.type === "taskError" || contextUpdate.type === "taskAborted") {
1278
+ resultPromiseWithResolvers.reject(new TaskError(contextUpdate.reason ?? (contextUpdate.type === "taskError" ? "Task failed" : "Task aborted"), options.taskTemplate, payload.taskId));
1279
+ }
1280
+ taskUpdateHandlers.forEach((handler) => handler(contextUpdate));
1281
+ }
782
1282
  };
783
1283
  const taskIdPromiseWithResolvers = Promise.withResolvers();
1284
+ const preparedTaskIdPromiseWithResolvers = Promise.withResolvers();
1285
+ preparedTaskIdPromiseWithResolvers.promise.catch(() => {});
784
1286
  const taskUrlPromiseWithResolvers = Promise.withResolvers();
785
1287
  const resultPromiseWithResolvers = Promise.withResolvers();
786
- const finalizedPromiseWithResolvers = Promise.withResolvers();
787
- finalizedPromiseWithResolvers.promise.catch(() => {});
788
1288
  let rejectTaskIdPromise = false;
789
1289
  let rejectTaskUrlPromise = false;
790
1290
  (async () => {
791
- const prepareResponse = await fetch(prepareUrl, {
792
- method: "POST",
793
- headers: {
794
- Authorization: `Bearer ${token}`
1291
+ try {
1292
+ const prepareResponse = await reachableFetch(prepareUrl, {
1293
+ method: "POST",
1294
+ headers: {
1295
+ Authorization: `Bearer ${token}`
1296
+ }
1297
+ });
1298
+ if (!prepareResponse.ok) {
1299
+ const error = new TaskPrepareError(await prepareResponse.text(), options.taskTemplate);
1300
+ preparedTaskIdPromiseWithResolvers.reject(error);
1301
+ if (rejectTaskIdPromise) {
1302
+ taskIdPromiseWithResolvers.reject(error);
1303
+ }
1304
+ if (rejectTaskUrlPromise) {
1305
+ taskUrlPromiseWithResolvers.reject(error);
1306
+ }
1307
+ if (isMonitoring) {
1308
+ resultPromiseWithResolvers.reject(error);
1309
+ }
1310
+ return;
795
1311
  }
796
- });
797
- if (!prepareResponse.ok) {
798
- const error = new TaskPrepareError(await prepareResponse.text(), options.taskTemplate);
799
- finalizedPromiseWithResolvers.reject(error);
800
- if (rejectTaskIdPromise) {
801
- taskIdPromiseWithResolvers.reject(error);
1312
+ const prepareData = await prepareResponse.json();
1313
+ if (prepareData.branch !== "live" && !options.suppressBranchWarning) {
1314
+ console.warn(chalk.hex("#eab308")("task is executed in", chalk.bold(prepareData.branch), "branch"));
802
1315
  }
803
- if (rejectTaskUrlPromise) {
804
- taskUrlPromiseWithResolvers.reject(error);
1316
+ preparedTaskIdPromiseWithResolvers.resolve(prepareData.taskId);
1317
+ const streamDone = Promise.withResolvers();
1318
+ streamDone.promise.catch(() => {});
1319
+ let mappedParams;
1320
+ try {
1321
+ const { value, done } = await withRequenceStreams(() => transformer.outbound({
1322
+ name: options.name,
1323
+ input: options.input,
1324
+ priority,
1325
+ requireAck: options.requireAck ?? false
1326
+ }, {
1327
+ fetch: globalThis.fetch,
1328
+ uploadUrl: prepareData.fileUrls?.uploadUrl,
1329
+ streamUrl: prepareData.fileUrls?.streamUrl,
1330
+ maxPayloadSize: prepareData.limits?.maxPayloadSize,
1331
+ maxFileSize: prepareData.limits?.maxFileSize
1332
+ }));
1333
+ mappedParams = value;
1334
+ done.then(() => streamDone.resolve(), (error) => streamDone.reject(error instanceof Error ? error : new Error(String(error))));
1335
+ } catch (error) {
1336
+ const taskError = new TaskError(error instanceof Error ? error.message : String(error), options.taskTemplate, prepareData.taskId);
1337
+ if (rejectTaskIdPromise) {
1338
+ taskIdPromiseWithResolvers.reject(taskError);
1339
+ }
1340
+ if (rejectTaskUrlPromise) {
1341
+ taskUrlPromiseWithResolvers.reject(taskError);
1342
+ }
1343
+ if (isMonitoring) {
1344
+ resultPromiseWithResolvers.reject(taskError);
1345
+ }
1346
+ return;
805
1347
  }
806
- if (isMonitoring) {
807
- resultPromiseWithResolvers.reject(error);
1348
+ const finalizeResponse = await reachableFetch(prepareData.finalizeUrl, {
1349
+ method: "POST",
1350
+ body: JSON.stringify(mappedParams),
1351
+ headers: {
1352
+ Authorization: `Bearer ${token}`,
1353
+ "Content-Type": "application/json"
1354
+ }
1355
+ });
1356
+ if (!finalizeResponse.ok) {
1357
+ const error = new TaskError(await finalizeResponse.text(), options.taskTemplate, prepareData.taskId);
1358
+ if (rejectTaskIdPromise) {
1359
+ taskIdPromiseWithResolvers.reject(error);
1360
+ }
1361
+ if (rejectTaskUrlPromise) {
1362
+ taskUrlPromiseWithResolvers.reject(error);
1363
+ }
1364
+ if (isMonitoring) {
1365
+ resultPromiseWithResolvers.reject(error);
1366
+ }
1367
+ return;
808
1368
  }
809
- return;
810
- }
811
- const prepareData = await prepareResponse.json();
812
- if (prepareData.branch !== "live" && !options.suppressBranchWarning) {
813
- console.warn(chalk.hex("#eab308")("task is executed in", chalk.bold(prepareData.branch), "branch"));
814
- }
815
- taskIdPromiseWithResolvers.resolve(prepareData.taskId);
816
- const mappedParams = await mapOutput({
817
- value: {
818
- name: options.name,
819
- input: options.input,
820
- priority,
821
- requireAck: options.requireAck ?? false
822
- },
823
- options: {
824
- uploadUrl: prepareData.fileUrls?.uploadUrl,
825
- streamUrl: prepareData.fileUrls?.streamUrl
1369
+ try {
1370
+ await streamDone.promise;
1371
+ } catch (error) {
1372
+ const taskError = new TaskError(error instanceof Error ? error.message : String(error), options.taskTemplate, prepareData.taskId);
1373
+ if (rejectTaskIdPromise) {
1374
+ taskIdPromiseWithResolvers.reject(taskError);
1375
+ }
1376
+ if (rejectTaskUrlPromise) {
1377
+ taskUrlPromiseWithResolvers.reject(taskError);
1378
+ }
1379
+ if (isMonitoring) {
1380
+ resultPromiseWithResolvers.reject(taskError);
1381
+ }
1382
+ return;
826
1383
  }
827
- });
828
- const finalizeResponse = await fetch(prepareData.finalizeUrl, {
829
- method: "POST",
830
- body: JSON.stringify(mappedParams),
831
- headers: {
832
- Authorization: `Bearer ${token}`,
833
- "Content-Type": "application/json"
1384
+ const payload = await finalizeResponse.json();
1385
+ taskIdPromiseWithResolvers.resolve(prepareData.taskId);
1386
+ taskUrlPromiseWithResolvers.resolve(payload.urls?.show ?? null);
1387
+ payloadPromiseWithResolvers.resolve(payload);
1388
+ if (onUpdate) {
1389
+ taskUpdateHandlers.add(onUpdate);
1390
+ startMonitoring();
1391
+ }
1392
+ } catch (error) {
1393
+ preparedTaskIdPromiseWithResolvers.reject(error);
1394
+ if (rejectTaskIdPromise) {
1395
+ taskIdPromiseWithResolvers.reject(error);
834
1396
  }
835
- });
836
- if (!finalizeResponse.ok) {
837
- const error = new TaskError(await finalizeResponse.text(), options.taskTemplate, prepareData.taskId);
838
- finalizedPromiseWithResolvers.reject(error);
839
1397
  if (rejectTaskUrlPromise) {
840
1398
  taskUrlPromiseWithResolvers.reject(error);
841
1399
  }
842
1400
  if (isMonitoring) {
843
1401
  resultPromiseWithResolvers.reject(error);
844
1402
  }
845
- return;
846
- }
847
- const payload = await finalizeResponse.json();
848
- finalizedPromiseWithResolvers.resolve(prepareData.taskId);
849
- taskUrlPromiseWithResolvers.resolve(payload.urls?.show ?? null);
850
- payloadPromiseWithResolvers.resolve(payload);
851
- if (onUpdate) {
852
- taskUpdateHandlers.add(onUpdate);
853
- startMonitoring();
854
1403
  }
855
1404
  })();
856
1405
  const asyncIterable = callbackToAsyncIterable((push, _fail, done) => {
@@ -889,7 +1438,7 @@ function createTask(options, onUpdate) {
889
1438
  return taskUrlPromiseWithResolvers.promise;
890
1439
  },
891
1440
  async abort(reason) {
892
- const taskId = await taskIdPromiseWithResolvers.promise;
1441
+ const taskId = await preparedTaskIdPromiseWithResolvers.promise;
893
1442
  await abortTask({
894
1443
  taskId,
895
1444
  accessToken: options.accessToken,
@@ -897,14 +1446,11 @@ function createTask(options, onUpdate) {
897
1446
  });
898
1447
  },
899
1448
  async protect() {
900
- const taskId = await taskIdPromiseWithResolvers.promise;
1449
+ const taskId = await preparedTaskIdPromiseWithResolvers.promise;
901
1450
  await protectTask({
902
1451
  taskId,
903
1452
  accessToken: options.accessToken
904
1453
  });
905
- },
906
- async finalized() {
907
- return finalizedPromiseWithResolvers.promise;
908
1454
  }
909
1455
  };
910
1456
  return Object.defineProperties(asyncIterable, Object.getOwnPropertyDescriptors(methods));
@@ -921,6 +1467,7 @@ function watchTasks(options) {
921
1467
  let startDate = options.since;
922
1468
  let lastPosition = null;
923
1469
  let lastResponse;
1470
+ let processing = Promise.resolve();
924
1471
  const customFetch = async (url, init) => {
925
1472
  const response = await fetch(url, init);
926
1473
  lastResponse = response;
@@ -952,6 +1499,9 @@ function watchTasks(options) {
952
1499
  },
953
1500
  async onDisconnect() {
954
1501
  if (lastResponse) {
1502
+ if (isUnreachableStatus(lastResponse.status)) {
1503
+ options.onUnreachable?.(new RequenceUnreachableError(lastResponse.status));
1504
+ }
955
1505
  options.onError?.(lastResponse.status, lastResponse.statusText);
956
1506
  }
957
1507
  },
@@ -965,82 +1515,85 @@ function watchTasks(options) {
965
1515
  throw new Error("invalid update");
966
1516
  }
967
1517
  const update = updateResult.data;
968
- if (!taskStorage.has(update.taskId)) {
969
- taskStorage.set(update.taskId, {
970
- input: null,
971
- data: {},
972
- errors: {},
973
- result: null,
974
- incomplete: true,
975
- rootTaskId: null
976
- });
1518
+ processing = processing.then(() => applyUpdate(update, id)).catch(() => {
1519
+ eventSource.close();
1520
+ });
1521
+ }
1522
+ });
1523
+ async function applyUpdate(update, updateId) {
1524
+ if (!taskStorage.has(update.taskId)) {
1525
+ taskStorage.set(update.taskId, {
1526
+ input: null,
1527
+ data: {},
1528
+ errors: {},
1529
+ result: null,
1530
+ incomplete: true,
1531
+ rootTaskId: null
1532
+ });
1533
+ }
1534
+ const storageEntry = taskStorage.get(update.taskId);
1535
+ switch (update.type) {
1536
+ case "taskStart": {
1537
+ storageEntry.input = await inbound(update.input, forbidCallbacks);
1538
+ storageEntry.incomplete = false;
1539
+ storageEntry.rootTaskId = update.rootTaskId;
1540
+ break;
977
1541
  }
978
- const storageEntry = taskStorage.get(update.taskId);
979
- switch (update.type) {
980
- case "taskStart": {
981
- storageEntry.input = resolveRequenceTypes(update.input, () => {
982
- throw new Error("input may not have callbacks");
983
- });
984
- storageEntry.incomplete = false;
985
- storageEntry.rootTaskId = update.rootTaskId;
986
- break;
987
- }
988
- case "nodeUpdate": {
989
- if (update.node.alias) {
990
- storageEntry.data[update.node.alias] = resolveRequenceTypes(update.data);
991
- }
992
- break;
1542
+ case "nodeUpdate": {
1543
+ if (update.node.alias) {
1544
+ storageEntry.data[update.node.alias] = await inbound(update.data, observeOnlyCallbacks);
993
1545
  }
994
- case "nodeError": {
995
- if (update.node.alias) {
996
- storageEntry.errors[update.node.alias] = update.error;
997
- }
998
- break;
1546
+ break;
1547
+ }
1548
+ case "nodeError": {
1549
+ if (update.node.alias) {
1550
+ storageEntry.errors[update.node.alias] = update.error;
999
1551
  }
1000
- case "taskEnd": {
1001
- storageEntry.result = resolveRequenceTypes(update.result);
1002
- taskStorage.delete(update.taskId);
1003
- if (update.requireAck) {
1004
- ackTask({
1005
- taskId: update.taskId,
1006
- accessToken: options.accessToken
1007
- }).catch(() => {});
1008
- }
1009
- break;
1552
+ break;
1553
+ }
1554
+ case "taskEnd": {
1555
+ storageEntry.result = await inbound(update.result, observeOnlyCallbacks);
1556
+ taskStorage.delete(update.taskId);
1557
+ if (update.requireAck) {
1558
+ ackTask({
1559
+ taskId: update.taskId,
1560
+ accessToken: options.accessToken
1561
+ }).catch(() => {});
1010
1562
  }
1011
- case "taskError":
1012
- case "taskAborted": {
1013
- taskStorage.delete(update.taskId);
1014
- if (update.requireAck) {
1015
- ackTask({
1016
- taskId: update.taskId,
1017
- accessToken: options.accessToken
1018
- }).catch(() => {});
1019
- }
1020
- break;
1563
+ break;
1564
+ }
1565
+ case "taskError":
1566
+ case "taskAborted": {
1567
+ taskStorage.delete(update.taskId);
1568
+ if (update.requireAck) {
1569
+ ackTask({
1570
+ taskId: update.taskId,
1571
+ accessToken: options.accessToken
1572
+ }).catch(() => {});
1021
1573
  }
1574
+ break;
1022
1575
  }
1023
- const context = {
1024
- taskId: update.taskId,
1025
- input: storageEntry.input,
1026
- getNodeData(alias) {
1027
- return storageEntry.data[alias] ?? null;
1028
- },
1029
- getNodeError(alias) {
1030
- return storageEntry.errors[alias] ?? null;
1031
- },
1032
- result: storageEntry.result
1033
- };
1034
- const contextUpdate = {
1035
- ...update,
1036
- context,
1037
- updateId: id,
1038
- incomplete: storageEntry.incomplete,
1039
- rootTaskId: storageEntry.rootTaskId
1040
- };
1041
- taskUpdateHandlers.forEach((handler) => handler(contextUpdate));
1042
1576
  }
1043
- });
1577
+ const context = {
1578
+ taskId: update.taskId,
1579
+ input: storageEntry.input,
1580
+ getNodeData(alias) {
1581
+ return storageEntry.data[alias] ?? null;
1582
+ },
1583
+ getNodeError(alias) {
1584
+ return storageEntry.errors[alias] ?? null;
1585
+ },
1586
+ result: storageEntry.result
1587
+ };
1588
+ const contextUpdate = {
1589
+ ...update,
1590
+ context,
1591
+ updateId,
1592
+ incomplete: storageEntry.incomplete,
1593
+ rootTaskId: storageEntry.rootTaskId
1594
+ };
1595
+ taskUpdateHandlers.forEach((handler) => handler(contextUpdate));
1596
+ }
1044
1597
  const asyncIterable = callbackToAsyncIterable((push) => {
1045
1598
  taskUpdateHandlers.add(push);
1046
1599
  return () => {
@@ -1076,7 +1629,7 @@ var taskSchema = z6.object({
1076
1629
  async function getTask(taskIdOrOptions) {
1077
1630
  const taskId = typeof taskIdOrOptions === "string" ? taskIdOrOptions : taskIdOrOptions.taskId;
1078
1631
  const { apiBaseUrl, token } = getAccessToken(typeof taskIdOrOptions === "string" ? undefined : taskIdOrOptions.accessToken);
1079
- const response = await fetch(new URL(`${apiBaseUrl}/task/${taskId}`), {
1632
+ const response = await reachableFetch(new URL(`${apiBaseUrl}/task/${taskId}`), {
1080
1633
  headers: {
1081
1634
  Authorization: `Bearer ${token}`
1082
1635
  }
@@ -1085,18 +1638,24 @@ async function getTask(taskIdOrOptions) {
1085
1638
  throw new Error("Task not found");
1086
1639
  }
1087
1640
  const taskData = taskSchema.parse(await response.json());
1641
+ const [input, result, nodesData] = await Promise.all([
1642
+ inbound(taskData.input, forbidCallbacks),
1643
+ inbound(taskData.result, observeOnlyCallbacks),
1644
+ Promise.all(taskData.nodesData.map(async ({ alias, data }) => ({
1645
+ alias,
1646
+ data: await inbound(data, observeOnlyCallbacks)
1647
+ })))
1648
+ ]);
1088
1649
  const context = {
1089
1650
  taskId,
1090
- input: resolveRequenceTypes(taskData.input, () => {
1091
- throw new Error("input may not have callbacks");
1092
- }),
1651
+ input,
1093
1652
  getNodeData(alias) {
1094
- return resolveRequenceTypes(taskData.nodesData.find((d) => d.alias === alias)?.data);
1653
+ return nodesData.find((d) => d.alias === alias)?.data ?? null;
1095
1654
  },
1096
1655
  getNodeError(alias) {
1097
1656
  return taskData.nodesError.find((d) => d.alias === alias)?.error ?? null;
1098
1657
  },
1099
- result: resolveRequenceTypes(taskData.result)
1658
+ result
1100
1659
  };
1101
1660
  return {
1102
1661
  status: taskData.status,
@@ -1126,9 +1685,10 @@ export {
1126
1685
  createTask,
1127
1686
  abortTask,
1128
1687
  TaskError,
1688
+ RequenceUnreachableError,
1129
1689
  RequenceStream,
1130
1690
  RequenceFile
1131
1691
  };
1132
1692
 
1133
- //# debugId=72085AB5595C0E1D64756E2164756E21
1693
+ //# debugId=F96A579BA4EB8E1D64756E2164756E21
1134
1694
  //# sourceMappingURL=index.js.map