@workglow/task-graph 0.2.17 → 0.2.18

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 CHANGED
@@ -584,6 +584,10 @@ function computeGraphEntitlements(graph, options) {
584
584
  }
585
585
  // src/task/InputResolver.ts
586
586
  import { getInputResolvers } from "@workglow/util";
587
+ function isPlainObject(value) {
588
+ const proto = Object.getPrototypeOf(value);
589
+ return proto === Object.prototype || proto === null;
590
+ }
587
591
  function getSchemaFormat(schema, visited = new WeakSet) {
588
592
  if (typeof schema !== "object" || schema === null)
589
593
  return;
@@ -671,6 +675,7 @@ async function resolveSchemaInputs(input, schema, config, visited = new Set) {
671
675
  for (const [key, propSchema] of Object.entries(properties)) {
672
676
  let value = resolved[key];
673
677
  const format = getSchemaFormat(propSchema);
678
+ let phase1Transformed = false;
674
679
  if (format) {
675
680
  let resolver = resolvers.get(format);
676
681
  if (!resolver) {
@@ -681,14 +686,18 @@ async function resolveSchemaInputs(input, schema, config, visited = new Set) {
681
686
  if (typeof value === "string") {
682
687
  value = await resolver(value, format, config.registry);
683
688
  resolved[key] = value;
689
+ phase1Transformed = true;
684
690
  } else if (Array.isArray(value) && value.some((item) => typeof item === "string")) {
685
691
  const results = await Promise.all(value.map((item) => typeof item === "string" ? resolver(item, format, config.registry) : item));
686
692
  value = results.filter((result) => result !== undefined);
687
693
  resolved[key] = value;
694
+ phase1Transformed = true;
688
695
  }
689
696
  }
690
697
  }
691
- if (value !== null && value !== undefined && typeof value === "object" && !Array.isArray(value)) {
698
+ const hasFormatResolver = format ? !!(resolvers.get(format) ?? resolvers.get(getFormatPrefix(format))) : false;
699
+ const skipPhase2 = hasFormatResolver && !phase1Transformed;
700
+ if (!skipPhase2 && value !== null && value !== undefined && typeof value === "object" && !Array.isArray(value) && isPlainObject(value)) {
692
701
  const objectSchema = getObjectSchema(propSchema);
693
702
  if (objectSchema && !visited.has(objectSchema)) {
694
703
  visited.add(objectSchema);
@@ -1134,6 +1143,31 @@ import {
1134
1143
  uuid4 as uuid43
1135
1144
  } from "@workglow/util";
1136
1145
 
1146
+ // src/refcountable.ts
1147
+ var GLOBAL_KEY = Symbol.for("@workglow/task-graph/refcountable.predicates");
1148
+ var _g = globalThis;
1149
+ if (!Array.isArray(_g[GLOBAL_KEY])) {
1150
+ _g[GLOBAL_KEY] = [];
1151
+ }
1152
+ var predicates = _g[GLOBAL_KEY];
1153
+ function registerRefcountablePredicate(p) {
1154
+ predicates.push(p);
1155
+ }
1156
+ function asRefcountable(v) {
1157
+ if (v === null || v === undefined)
1158
+ return null;
1159
+ if (typeof v !== "object")
1160
+ return null;
1161
+ for (const p of predicates) {
1162
+ if (p(v))
1163
+ return v;
1164
+ }
1165
+ return null;
1166
+ }
1167
+ function _resetRefcountablePredicatesForTests() {
1168
+ predicates.length = 0;
1169
+ }
1170
+
1137
1171
  // src/storage/TaskOutputRepository.ts
1138
1172
  import { createServiceToken as createServiceToken2, EventEmitter as EventEmitter2 } from "@workglow/util";
1139
1173
  var TASK_OUTPUT_REPOSITORY = createServiceToken2("taskgraph.taskOutputRepository");
@@ -1245,6 +1279,7 @@ import {
1245
1279
  globalServiceRegistry as globalServiceRegistry2,
1246
1280
  SpanStatusCode
1247
1281
  } from "@workglow/util";
1282
+ import { getPortCodec } from "@workglow/util";
1248
1283
 
1249
1284
  // src/task/StreamTypes.ts
1250
1285
  function getPortStreamMode(schema, portId) {
@@ -1348,6 +1383,42 @@ function hasStructuredOutput(schema) {
1348
1383
  }
1349
1384
 
1350
1385
  // src/task/TaskRunner.ts
1386
+ async function serializeOutputPorts(output, schema) {
1387
+ if (!schema?.properties)
1388
+ return output;
1389
+ const out = { ...output };
1390
+ for (const [key, prop] of Object.entries(schema.properties)) {
1391
+ const codec = prop.format ? getPortCodec(prop.format) : undefined;
1392
+ if (codec && out[key] !== undefined) {
1393
+ out[key] = await codec.serialize(out[key]);
1394
+ }
1395
+ }
1396
+ return out;
1397
+ }
1398
+ async function deserializeOutputPorts(output, schema) {
1399
+ if (!schema?.properties)
1400
+ return output;
1401
+ const out = { ...output };
1402
+ for (const [key, prop] of Object.entries(schema.properties)) {
1403
+ const codec = prop.format ? getPortCodec(prop.format) : undefined;
1404
+ if (codec && out[key] !== undefined) {
1405
+ out[key] = await codec.deserialize(out[key]);
1406
+ }
1407
+ }
1408
+ return out;
1409
+ }
1410
+ async function normalizeInputsForCacheKey(inputs, schema) {
1411
+ if (!schema?.properties)
1412
+ return inputs;
1413
+ const out = { ...inputs };
1414
+ for (const [key, prop] of Object.entries(schema.properties)) {
1415
+ const codec = prop.format ? getPortCodec(prop.format) : undefined;
1416
+ if (codec && out[key] !== undefined) {
1417
+ out[key] = await codec.serialize(out[key]);
1418
+ }
1419
+ }
1420
+ return out;
1421
+ }
1351
1422
  function hasRunConfig(i) {
1352
1423
  return i !== null && typeof i === "object" && "runConfig" in i;
1353
1424
  }
@@ -1403,9 +1474,13 @@ class TaskRunner {
1403
1474
  getLogger().warn(`Task "${this.task.type}" declares streaming output (x-stream: "${streamMode}") ` + `but does not implement executeStream(). Falling back to non-streaming execute().`);
1404
1475
  }
1405
1476
  }
1477
+ const inputSchema = this.task.constructor.inputSchema();
1478
+ const outputSchema = this.task.constructor.outputSchema();
1479
+ const inputsForKey = this.outputCache ? await normalizeInputsForCacheKey(inputs, inputSchema) : inputs;
1406
1480
  if (this.task.cacheable) {
1407
- outputs = await this.outputCache?.getOutput(this.task.type, inputs);
1408
- if (outputs) {
1481
+ const cached = await this.outputCache?.getOutput(this.task.type, inputsForKey);
1482
+ if (cached !== undefined) {
1483
+ outputs = await deserializeOutputPorts(cached, outputSchema);
1409
1484
  this.telemetrySpan?.addEvent("workglow.task.cache_hit");
1410
1485
  if (isStreamable) {
1411
1486
  this.task.runOutputData = outputs;
@@ -1424,7 +1499,8 @@ class TaskRunner {
1424
1499
  outputs = await this.executeTask(inputs);
1425
1500
  }
1426
1501
  if (this.task.cacheable && outputs !== undefined) {
1427
- await this.outputCache?.saveOutput(this.task.type, inputs, outputs);
1502
+ const wireOutputs = await serializeOutputPorts(outputs, outputSchema);
1503
+ await this.outputCache?.saveOutput(this.task.type, inputsForKey, wireOutputs);
1428
1504
  }
1429
1505
  this.task.runOutputData = outputs ?? {};
1430
1506
  }
@@ -3046,6 +3122,23 @@ class TaskGraphRunner {
3046
3122
  }
3047
3123
  async pushOutputFromNodeToEdges(node, results) {
3048
3124
  const dataflows = this.graph.getTargetDataflows(node.id);
3125
+ if (Object.keys(results).length > 0) {
3126
+ const consumerCounts = new Map;
3127
+ for (const dataflow of dataflows) {
3128
+ if (dataflow.stream !== undefined)
3129
+ continue;
3130
+ const port = dataflow.sourceTaskPortId;
3131
+ consumerCounts.set(port, (consumerCounts.get(port) ?? 0) + 1);
3132
+ }
3133
+ for (const [port, count] of consumerCounts) {
3134
+ if (count <= 1)
3135
+ continue;
3136
+ const value = results[port];
3137
+ const ref = asRefcountable(value);
3138
+ if (ref)
3139
+ ref.retain(count - 1);
3140
+ }
3141
+ }
3049
3142
  for (const dataflow of dataflows) {
3050
3143
  if (dataflow.stream !== undefined)
3051
3144
  continue;
@@ -8121,6 +8214,12 @@ class TaskOutputTabularRepository extends TaskOutputRepository {
8121
8214
  this.emit("output_pruned");
8122
8215
  }
8123
8216
  }
8217
+ // src/storage/PortCodecRegistry.ts
8218
+ import {
8219
+ registerPortCodec,
8220
+ getPortCodec as getPortCodec2,
8221
+ _resetPortCodecsForTests
8222
+ } from "@workglow/util";
8124
8223
  // src/debug/console/ConsoleFormatters.ts
8125
8224
  import { DirectedAcyclicGraph as DirectedAcyclicGraph2 } from "@workglow/util/graph";
8126
8225
  function formatDuration(ms) {
@@ -8756,6 +8855,8 @@ function installDevToolsFormatters() {
8756
8855
  window.devtoolsFormatters = window.devtoolsFormatters || [];
8757
8856
  window.devtoolsFormatters.push(new WorkflowAPIConsoleFormatter, new CreateWorkflowConsoleFormatter, new WorkflowConsoleFormatter, new TaskConsoleFormatter, new ReactElementConsoleFormatter, new DataflowConsoleFormatter, new DAGConsoleFormatter);
8758
8857
  }
8858
+ // src/browser.ts
8859
+ registerRefcountablePredicate((v) => !!v && typeof v === "object" && ("backend" in v) && ("retain" in v) && ("release" in v) && ("materialize" in v));
8759
8860
  export {
8760
8861
  wrapSchemaInArray,
8761
8862
  whileTaskConfigSchema,
@@ -8778,6 +8879,8 @@ export {
8778
8879
  resolveIterationBound,
8779
8880
  resetMethodNameCache,
8780
8881
  removeIterationProperties,
8882
+ registerRefcountablePredicate,
8883
+ registerPortCodec,
8781
8884
  registerJobQueueFactory,
8782
8885
  registerBuiltInTransforms,
8783
8886
  registerBaseTasks,
@@ -8815,6 +8918,7 @@ export {
8815
8918
  getSchemaFormat,
8816
8919
  getProfileGrants,
8817
8920
  getPortStreamMode,
8921
+ getPortCodec2 as getPortCodec,
8818
8922
  getOutputStreamMode,
8819
8923
  getObjectSchema,
8820
8924
  getObjectPortId,
@@ -8861,9 +8965,12 @@ export {
8861
8965
  calculateNodeDepths,
8862
8966
  buildIterationInputSchema,
8863
8967
  autoConnect,
8968
+ asRefcountable,
8864
8969
  addIterationContextToSchema,
8865
8970
  addBoundaryNodesToGraphJson,
8866
8971
  addBoundaryNodesToDependencyJson,
8972
+ _resetRefcountablePredicatesForTests,
8973
+ _resetPortCodecsForTests,
8867
8974
  WorkflowError,
8868
8975
  Workflow,
8869
8976
  WhileTaskRunner,
@@ -8937,4 +9044,4 @@ export {
8937
9044
  BROWSER_GRANTS
8938
9045
  };
8939
9046
 
8940
- //# debugId=8B5B3A49FDB4C28B64756E2164756E21
9047
+ //# debugId=09531002308E754B64756E2164756E21