@workglow/task-graph 0.2.17 → 0.2.19
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.
- package/dist/browser.js +139 -10
- package/dist/browser.js.map +13 -10
- package/dist/bun.js +139 -10
- package/dist/bun.js.map +13 -10
- package/dist/common.d.ts +3 -0
- package/dist/common.d.ts.map +1 -1
- package/dist/node.js +139 -10
- package/dist/node.js.map +13 -10
- package/dist/refcountable.d.ts +29 -0
- package/dist/refcountable.d.ts.map +1 -0
- package/dist/storage/PortCodecRegistry.d.ts +8 -0
- package/dist/storage/PortCodecRegistry.d.ts.map +1 -0
- package/dist/task/GraphAsTaskRunner.d.ts.map +1 -1
- package/dist/task/ITask.d.ts +6 -0
- package/dist/task/ITask.d.ts.map +1 -1
- package/dist/task/InputResolver.d.ts.map +1 -1
- package/dist/task/TaskRunner.d.ts +6 -0
- package/dist/task/TaskRunner.d.ts.map +1 -1
- package/dist/task-graph/IWorkflow.d.ts +2 -0
- package/dist/task-graph/IWorkflow.d.ts.map +1 -1
- package/dist/task-graph/TaskGraph.d.ts +12 -0
- package/dist/task-graph/TaskGraph.d.ts.map +1 -1
- package/dist/task-graph/TaskGraphRunner.d.ts +6 -0
- package/dist/task-graph/TaskGraphRunner.d.ts.map +1 -1
- package/dist/task-graph/Workflow.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/__tests__/public-exports.test.d.ts +0 -7
- package/dist/__tests__/public-exports.test.d.ts.map +0 -1
package/dist/bun.js
CHANGED
|
@@ -585,6 +585,10 @@ function computeGraphEntitlements(graph, options) {
|
|
|
585
585
|
}
|
|
586
586
|
// src/task/InputResolver.ts
|
|
587
587
|
import { getInputResolvers } from "@workglow/util";
|
|
588
|
+
function isPlainObject(value) {
|
|
589
|
+
const proto = Object.getPrototypeOf(value);
|
|
590
|
+
return proto === Object.prototype || proto === null;
|
|
591
|
+
}
|
|
588
592
|
function getSchemaFormat(schema, visited = new WeakSet) {
|
|
589
593
|
if (typeof schema !== "object" || schema === null)
|
|
590
594
|
return;
|
|
@@ -672,6 +676,7 @@ async function resolveSchemaInputs(input, schema, config, visited = new Set) {
|
|
|
672
676
|
for (const [key, propSchema] of Object.entries(properties)) {
|
|
673
677
|
let value = resolved[key];
|
|
674
678
|
const format = getSchemaFormat(propSchema);
|
|
679
|
+
let phase1Transformed = false;
|
|
675
680
|
if (format) {
|
|
676
681
|
let resolver = resolvers.get(format);
|
|
677
682
|
if (!resolver) {
|
|
@@ -682,14 +687,18 @@ async function resolveSchemaInputs(input, schema, config, visited = new Set) {
|
|
|
682
687
|
if (typeof value === "string") {
|
|
683
688
|
value = await resolver(value, format, config.registry);
|
|
684
689
|
resolved[key] = value;
|
|
690
|
+
phase1Transformed = true;
|
|
685
691
|
} else if (Array.isArray(value) && value.some((item) => typeof item === "string")) {
|
|
686
692
|
const results = await Promise.all(value.map((item) => typeof item === "string" ? resolver(item, format, config.registry) : item));
|
|
687
693
|
value = results.filter((result) => result !== undefined);
|
|
688
694
|
resolved[key] = value;
|
|
695
|
+
phase1Transformed = true;
|
|
689
696
|
}
|
|
690
697
|
}
|
|
691
698
|
}
|
|
692
|
-
|
|
699
|
+
const hasFormatResolver = format ? !!(resolvers.get(format) ?? resolvers.get(getFormatPrefix(format))) : false;
|
|
700
|
+
const skipPhase2 = hasFormatResolver && !phase1Transformed;
|
|
701
|
+
if (!skipPhase2 && value !== null && value !== undefined && typeof value === "object" && !Array.isArray(value) && isPlainObject(value)) {
|
|
693
702
|
const objectSchema = getObjectSchema(propSchema);
|
|
694
703
|
if (objectSchema && !visited.has(objectSchema)) {
|
|
695
704
|
visited.add(objectSchema);
|
|
@@ -1135,6 +1144,31 @@ import {
|
|
|
1135
1144
|
uuid4 as uuid43
|
|
1136
1145
|
} from "@workglow/util";
|
|
1137
1146
|
|
|
1147
|
+
// src/refcountable.ts
|
|
1148
|
+
var GLOBAL_KEY = Symbol.for("@workglow/task-graph/refcountable.predicates");
|
|
1149
|
+
var _g = globalThis;
|
|
1150
|
+
if (!Array.isArray(_g[GLOBAL_KEY])) {
|
|
1151
|
+
_g[GLOBAL_KEY] = [];
|
|
1152
|
+
}
|
|
1153
|
+
var predicates = _g[GLOBAL_KEY];
|
|
1154
|
+
function registerRefcountablePredicate(p) {
|
|
1155
|
+
predicates.push(p);
|
|
1156
|
+
}
|
|
1157
|
+
function asRefcountable(v) {
|
|
1158
|
+
if (v === null || v === undefined)
|
|
1159
|
+
return null;
|
|
1160
|
+
if (typeof v !== "object")
|
|
1161
|
+
return null;
|
|
1162
|
+
for (const p of predicates) {
|
|
1163
|
+
if (p(v))
|
|
1164
|
+
return v;
|
|
1165
|
+
}
|
|
1166
|
+
return null;
|
|
1167
|
+
}
|
|
1168
|
+
function _resetRefcountablePredicatesForTests() {
|
|
1169
|
+
predicates.length = 0;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1138
1172
|
// src/storage/TaskOutputRepository.ts
|
|
1139
1173
|
import { createServiceToken as createServiceToken2, EventEmitter as EventEmitter2 } from "@workglow/util";
|
|
1140
1174
|
var TASK_OUTPUT_REPOSITORY = createServiceToken2("taskgraph.taskOutputRepository");
|
|
@@ -1246,6 +1280,7 @@ import {
|
|
|
1246
1280
|
globalServiceRegistry as globalServiceRegistry2,
|
|
1247
1281
|
SpanStatusCode
|
|
1248
1282
|
} from "@workglow/util";
|
|
1283
|
+
import { getPortCodec } from "@workglow/util";
|
|
1249
1284
|
|
|
1250
1285
|
// src/task/StreamTypes.ts
|
|
1251
1286
|
function getPortStreamMode(schema, portId) {
|
|
@@ -1349,6 +1384,42 @@ function hasStructuredOutput(schema) {
|
|
|
1349
1384
|
}
|
|
1350
1385
|
|
|
1351
1386
|
// src/task/TaskRunner.ts
|
|
1387
|
+
async function serializeOutputPorts(output, schema) {
|
|
1388
|
+
if (!schema?.properties)
|
|
1389
|
+
return output;
|
|
1390
|
+
const out = { ...output };
|
|
1391
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
1392
|
+
const codec = prop.format ? getPortCodec(prop.format) : undefined;
|
|
1393
|
+
if (codec && out[key] !== undefined) {
|
|
1394
|
+
out[key] = await codec.serialize(out[key]);
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
return out;
|
|
1398
|
+
}
|
|
1399
|
+
async function deserializeOutputPorts(output, schema) {
|
|
1400
|
+
if (!schema?.properties)
|
|
1401
|
+
return output;
|
|
1402
|
+
const out = { ...output };
|
|
1403
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
1404
|
+
const codec = prop.format ? getPortCodec(prop.format) : undefined;
|
|
1405
|
+
if (codec && out[key] !== undefined) {
|
|
1406
|
+
out[key] = await codec.deserialize(out[key]);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
return out;
|
|
1410
|
+
}
|
|
1411
|
+
async function normalizeInputsForCacheKey(inputs, schema) {
|
|
1412
|
+
if (!schema?.properties)
|
|
1413
|
+
return inputs;
|
|
1414
|
+
const out = { ...inputs };
|
|
1415
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
1416
|
+
const codec = prop.format ? getPortCodec(prop.format) : undefined;
|
|
1417
|
+
if (codec && out[key] !== undefined) {
|
|
1418
|
+
out[key] = await codec.serialize(out[key]);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
return out;
|
|
1422
|
+
}
|
|
1352
1423
|
function hasRunConfig(i) {
|
|
1353
1424
|
return i !== null && typeof i === "object" && "runConfig" in i;
|
|
1354
1425
|
}
|
|
@@ -1365,6 +1436,7 @@ class TaskRunner {
|
|
|
1365
1436
|
timeoutTimer;
|
|
1366
1437
|
pendingTimeoutError;
|
|
1367
1438
|
shouldAccumulate = true;
|
|
1439
|
+
runWithPreviews = false;
|
|
1368
1440
|
telemetrySpan;
|
|
1369
1441
|
constructor(task) {
|
|
1370
1442
|
this.task = task;
|
|
@@ -1404,9 +1476,13 @@ class TaskRunner {
|
|
|
1404
1476
|
getLogger().warn(`Task "${this.task.type}" declares streaming output (x-stream: "${streamMode}") ` + `but does not implement executeStream(). Falling back to non-streaming execute().`);
|
|
1405
1477
|
}
|
|
1406
1478
|
}
|
|
1479
|
+
const inputSchema = this.task.constructor.inputSchema();
|
|
1480
|
+
const outputSchema = this.task.constructor.outputSchema();
|
|
1481
|
+
const inputsForKey = this.outputCache ? await normalizeInputsForCacheKey(inputs, inputSchema) : inputs;
|
|
1407
1482
|
if (this.task.cacheable) {
|
|
1408
|
-
|
|
1409
|
-
if (
|
|
1483
|
+
const cached = await this.outputCache?.getOutput(this.task.type, inputsForKey);
|
|
1484
|
+
if (cached !== undefined) {
|
|
1485
|
+
outputs = await deserializeOutputPorts(cached, outputSchema);
|
|
1410
1486
|
this.telemetrySpan?.addEvent("workglow.task.cache_hit");
|
|
1411
1487
|
if (isStreamable) {
|
|
1412
1488
|
this.task.runOutputData = outputs;
|
|
@@ -1425,7 +1501,8 @@ class TaskRunner {
|
|
|
1425
1501
|
outputs = await this.executeTask(inputs);
|
|
1426
1502
|
}
|
|
1427
1503
|
if (this.task.cacheable && outputs !== undefined) {
|
|
1428
|
-
await
|
|
1504
|
+
const wireOutputs = await serializeOutputPorts(outputs, outputSchema);
|
|
1505
|
+
await this.outputCache?.saveOutput(this.task.type, inputsForKey, wireOutputs);
|
|
1429
1506
|
}
|
|
1430
1507
|
this.task.runOutputData = outputs ?? {};
|
|
1431
1508
|
}
|
|
@@ -1642,6 +1719,7 @@ class TaskRunner {
|
|
|
1642
1719
|
this.outputCache = cache;
|
|
1643
1720
|
}
|
|
1644
1721
|
this.shouldAccumulate = config.shouldAccumulate !== false;
|
|
1722
|
+
this.runWithPreviews = config.runWithPreviews === true;
|
|
1645
1723
|
if (config.updateProgress) {
|
|
1646
1724
|
this.updateProgress = config.updateProgress;
|
|
1647
1725
|
}
|
|
@@ -2813,6 +2891,7 @@ class TaskGraphRunner {
|
|
|
2813
2891
|
graph;
|
|
2814
2892
|
outputCache;
|
|
2815
2893
|
accumulateLeafOutputs = true;
|
|
2894
|
+
runWithPreviews = false;
|
|
2816
2895
|
registry = globalServiceRegistry3;
|
|
2817
2896
|
resourceScope;
|
|
2818
2897
|
abortController;
|
|
@@ -3047,6 +3126,24 @@ class TaskGraphRunner {
|
|
|
3047
3126
|
}
|
|
3048
3127
|
async pushOutputFromNodeToEdges(node, results) {
|
|
3049
3128
|
const dataflows = this.graph.getTargetDataflows(node.id);
|
|
3129
|
+
if (Object.keys(results).length > 0) {
|
|
3130
|
+
const consumerCounts = new Map;
|
|
3131
|
+
for (const dataflow of dataflows) {
|
|
3132
|
+
if (dataflow.stream !== undefined)
|
|
3133
|
+
continue;
|
|
3134
|
+
const port = dataflow.sourceTaskPortId;
|
|
3135
|
+
consumerCounts.set(port, (consumerCounts.get(port) ?? 0) + 1);
|
|
3136
|
+
}
|
|
3137
|
+
for (const [port, count] of consumerCounts) {
|
|
3138
|
+
const extra = this.runWithPreviews ? count : count - 1;
|
|
3139
|
+
if (extra <= 0)
|
|
3140
|
+
continue;
|
|
3141
|
+
const value = results[port];
|
|
3142
|
+
const ref = asRefcountable(value);
|
|
3143
|
+
if (ref)
|
|
3144
|
+
ref.retain(extra);
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3050
3147
|
for (const dataflow of dataflows) {
|
|
3051
3148
|
if (dataflow.stream !== undefined)
|
|
3052
3149
|
continue;
|
|
@@ -3216,7 +3313,8 @@ class TaskGraphRunner {
|
|
|
3216
3313
|
outputCache: this.outputCache ?? false,
|
|
3217
3314
|
updateProgress: async (task2, progress, message, ...args) => await this.handleProgress(task2, progress, message, ...args),
|
|
3218
3315
|
registry: this.registry,
|
|
3219
|
-
resourceScope: this.resourceScope
|
|
3316
|
+
resourceScope: this.resourceScope,
|
|
3317
|
+
runWithPreviews: this.runWithPreviews
|
|
3220
3318
|
});
|
|
3221
3319
|
await this.pushOutputFromNodeToEdges(task, results);
|
|
3222
3320
|
return {
|
|
@@ -3266,7 +3364,8 @@ class TaskGraphRunner {
|
|
|
3266
3364
|
shouldAccumulate,
|
|
3267
3365
|
updateProgress: async (task2, progress, message, ...args) => await this.handleProgress(task2, progress, message, ...args),
|
|
3268
3366
|
registry: this.registry,
|
|
3269
|
-
resourceScope: this.resourceScope
|
|
3367
|
+
resourceScope: this.resourceScope,
|
|
3368
|
+
runWithPreviews: this.runWithPreviews
|
|
3270
3369
|
});
|
|
3271
3370
|
await this.pushOutputFromNodeToEdges(task, results);
|
|
3272
3371
|
return {
|
|
@@ -3341,6 +3440,17 @@ class TaskGraphRunner {
|
|
|
3341
3440
|
}
|
|
3342
3441
|
}
|
|
3343
3442
|
resetTask(graph, task, runId) {
|
|
3443
|
+
const previous = task.runOutputData;
|
|
3444
|
+
if (previous) {
|
|
3445
|
+
for (const port of Object.keys(previous)) {
|
|
3446
|
+
const ref = asRefcountable(previous[port]);
|
|
3447
|
+
if (!ref)
|
|
3448
|
+
continue;
|
|
3449
|
+
try {
|
|
3450
|
+
ref.release();
|
|
3451
|
+
} catch {}
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3344
3454
|
task.status = TaskStatus.PENDING;
|
|
3345
3455
|
task.resetInputData();
|
|
3346
3456
|
task.runOutputData = {};
|
|
@@ -3374,6 +3484,7 @@ class TaskGraphRunner {
|
|
|
3374
3484
|
this.resourceScope = config.resourceScope;
|
|
3375
3485
|
}
|
|
3376
3486
|
this.accumulateLeafOutputs = config?.accumulateLeafOutputs !== false;
|
|
3487
|
+
this.runWithPreviews = config?.runWithPreviews === true;
|
|
3377
3488
|
if (config?.outputCache !== undefined) {
|
|
3378
3489
|
if (typeof config.outputCache === "boolean") {
|
|
3379
3490
|
if (config.outputCache === true) {
|
|
@@ -3473,6 +3584,7 @@ class TaskGraphRunner {
|
|
|
3473
3584
|
throw new TaskConfigurationError(`Graph has ${taskCount} tasks, exceeding the limit of ${config.maxTasks}`);
|
|
3474
3585
|
}
|
|
3475
3586
|
}
|
|
3587
|
+
this.runWithPreviews = false;
|
|
3476
3588
|
this.previewScheduler.reset();
|
|
3477
3589
|
this.previewRunning = true;
|
|
3478
3590
|
}
|
|
@@ -3572,7 +3684,8 @@ class GraphAsTaskRunner extends TaskRunner {
|
|
|
3572
3684
|
parentSignal: this.abortController?.signal,
|
|
3573
3685
|
outputCache: this.outputCache,
|
|
3574
3686
|
registry: this.registry,
|
|
3575
|
-
resourceScope: this.resourceScope
|
|
3687
|
+
resourceScope: this.resourceScope,
|
|
3688
|
+
runWithPreviews: this.runWithPreviews
|
|
3576
3689
|
});
|
|
3577
3690
|
unsubscribe();
|
|
3578
3691
|
return results;
|
|
@@ -4035,7 +4148,8 @@ class TaskGraph {
|
|
|
4035
4148
|
registry: config?.registry,
|
|
4036
4149
|
timeout: config?.timeout,
|
|
4037
4150
|
maxTasks: config?.maxTasks,
|
|
4038
|
-
resourceScope: config?.resourceScope
|
|
4151
|
+
resourceScope: config?.resourceScope,
|
|
4152
|
+
runWithPreviews: config?.runWithPreviews
|
|
4039
4153
|
});
|
|
4040
4154
|
}
|
|
4041
4155
|
runPreview(input = {}, config = {}) {
|
|
@@ -4888,7 +5002,8 @@ class Workflow {
|
|
|
4888
5002
|
parentSignal: this._abortController.signal,
|
|
4889
5003
|
outputCache: this._outputCache,
|
|
4890
5004
|
registry: config?.registry ?? this._registry,
|
|
4891
|
-
resourceScope: config?.resourceScope
|
|
5005
|
+
resourceScope: config?.resourceScope,
|
|
5006
|
+
runWithPreviews: config?.runWithPreviews
|
|
4892
5007
|
});
|
|
4893
5008
|
const results = this.graph.mergeExecuteOutputsToRunOutput(output, PROPERTY_ARRAY);
|
|
4894
5009
|
this.events.emit("complete");
|
|
@@ -8122,6 +8237,14 @@ class TaskOutputTabularRepository extends TaskOutputRepository {
|
|
|
8122
8237
|
this.emit("output_pruned");
|
|
8123
8238
|
}
|
|
8124
8239
|
}
|
|
8240
|
+
// src/storage/PortCodecRegistry.ts
|
|
8241
|
+
import {
|
|
8242
|
+
registerPortCodec,
|
|
8243
|
+
getPortCodec as getPortCodec2,
|
|
8244
|
+
_resetPortCodecsForTests
|
|
8245
|
+
} from "@workglow/util";
|
|
8246
|
+
// src/bun.ts
|
|
8247
|
+
registerRefcountablePredicate((v) => !!v && typeof v === "object" && ("backend" in v) && ("retain" in v) && ("release" in v) && ("materialize" in v));
|
|
8125
8248
|
export {
|
|
8126
8249
|
wrapSchemaInArray,
|
|
8127
8250
|
whileTaskConfigSchema,
|
|
@@ -8144,6 +8267,8 @@ export {
|
|
|
8144
8267
|
resolveIterationBound,
|
|
8145
8268
|
resetMethodNameCache,
|
|
8146
8269
|
removeIterationProperties,
|
|
8270
|
+
registerRefcountablePredicate,
|
|
8271
|
+
registerPortCodec,
|
|
8147
8272
|
registerJobQueueFactory,
|
|
8148
8273
|
registerBuiltInTransforms,
|
|
8149
8274
|
registerBaseTasks,
|
|
@@ -8179,6 +8304,7 @@ export {
|
|
|
8179
8304
|
getSchemaFormat,
|
|
8180
8305
|
getProfileGrants,
|
|
8181
8306
|
getPortStreamMode,
|
|
8307
|
+
getPortCodec2 as getPortCodec,
|
|
8182
8308
|
getOutputStreamMode,
|
|
8183
8309
|
getObjectSchema,
|
|
8184
8310
|
getObjectPortId,
|
|
@@ -8225,9 +8351,12 @@ export {
|
|
|
8225
8351
|
calculateNodeDepths,
|
|
8226
8352
|
buildIterationInputSchema,
|
|
8227
8353
|
autoConnect,
|
|
8354
|
+
asRefcountable,
|
|
8228
8355
|
addIterationContextToSchema,
|
|
8229
8356
|
addBoundaryNodesToGraphJson,
|
|
8230
8357
|
addBoundaryNodesToDependencyJson,
|
|
8358
|
+
_resetRefcountablePredicatesForTests,
|
|
8359
|
+
_resetPortCodecsForTests,
|
|
8231
8360
|
WorkflowError,
|
|
8232
8361
|
Workflow,
|
|
8233
8362
|
WhileTaskRunner,
|
|
@@ -8301,4 +8430,4 @@ export {
|
|
|
8301
8430
|
BROWSER_GRANTS
|
|
8302
8431
|
};
|
|
8303
8432
|
|
|
8304
|
-
//# debugId=
|
|
8433
|
+
//# debugId=AA782C3ACDE0213064756E2164756E21
|