@workglow/task-graph 0.1.2 → 0.2.0

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 (84) hide show
  1. package/dist/browser.js +810 -189
  2. package/dist/browser.js.map +40 -33
  3. package/dist/bun.js +810 -189
  4. package/dist/bun.js.map +40 -33
  5. package/dist/common.d.ts +2 -0
  6. package/dist/common.d.ts.map +1 -1
  7. package/dist/node.js +810 -189
  8. package/dist/node.js.map +40 -33
  9. package/dist/storage/TaskOutputTabularRepository.d.ts +1 -1
  10. package/dist/storage/TaskOutputTabularRepository.d.ts.map +1 -1
  11. package/dist/task/ConditionalTask.d.ts +7 -2
  12. package/dist/task/ConditionalTask.d.ts.map +1 -1
  13. package/dist/task/EntitlementEnforcer.d.ts +55 -0
  14. package/dist/task/EntitlementEnforcer.d.ts.map +1 -0
  15. package/dist/task/EntitlementPolicy.d.ts +60 -0
  16. package/dist/task/EntitlementPolicy.d.ts.map +1 -0
  17. package/dist/task/EntitlementProfiles.d.ts +49 -0
  18. package/dist/task/EntitlementProfiles.d.ts.map +1 -0
  19. package/dist/task/EntitlementResolver.d.ts +50 -0
  20. package/dist/task/EntitlementResolver.d.ts.map +1 -0
  21. package/dist/task/FallbackTask.d.ts +11 -4
  22. package/dist/task/FallbackTask.d.ts.map +1 -1
  23. package/dist/task/FallbackTaskRunner.d.ts +2 -2
  24. package/dist/task/FallbackTaskRunner.d.ts.map +1 -1
  25. package/dist/task/GraphAsTask.d.ts +18 -6
  26. package/dist/task/GraphAsTask.d.ts.map +1 -1
  27. package/dist/task/GraphAsTaskRunner.d.ts +3 -2
  28. package/dist/task/GraphAsTaskRunner.d.ts.map +1 -1
  29. package/dist/task/ITask.d.ts +12 -1
  30. package/dist/task/ITask.d.ts.map +1 -1
  31. package/dist/task/InputCompactor.d.ts +1 -1
  32. package/dist/task/InputCompactor.d.ts.map +1 -1
  33. package/dist/task/InputResolver.d.ts +3 -3
  34. package/dist/task/InputResolver.d.ts.map +1 -1
  35. package/dist/task/IteratorTask.d.ts +9 -4
  36. package/dist/task/IteratorTask.d.ts.map +1 -1
  37. package/dist/task/IteratorTaskRunner.d.ts +1 -1
  38. package/dist/task/IteratorTaskRunner.d.ts.map +1 -1
  39. package/dist/task/MapTask.d.ts +8 -3
  40. package/dist/task/MapTask.d.ts.map +1 -1
  41. package/dist/task/ReduceTask.d.ts +9 -4
  42. package/dist/task/ReduceTask.d.ts.map +1 -1
  43. package/dist/task/StreamTypes.d.ts +6 -2
  44. package/dist/task/StreamTypes.d.ts.map +1 -1
  45. package/dist/task/Task.d.ts +37 -7
  46. package/dist/task/Task.d.ts.map +1 -1
  47. package/dist/task/TaskEntitlements.d.ts +134 -0
  48. package/dist/task/TaskEntitlements.d.ts.map +1 -0
  49. package/dist/task/TaskError.d.ts +7 -0
  50. package/dist/task/TaskError.d.ts.map +1 -1
  51. package/dist/task/TaskEvents.d.ts +3 -0
  52. package/dist/task/TaskEvents.d.ts.map +1 -1
  53. package/dist/task/TaskJSON.d.ts +14 -1
  54. package/dist/task/TaskJSON.d.ts.map +1 -1
  55. package/dist/task/TaskRegistry.d.ts +16 -3
  56. package/dist/task/TaskRegistry.d.ts.map +1 -1
  57. package/dist/task/TaskRunner.d.ts +5 -4
  58. package/dist/task/TaskRunner.d.ts.map +1 -1
  59. package/dist/task/TaskTypes.d.ts +10 -2
  60. package/dist/task/TaskTypes.d.ts.map +1 -1
  61. package/dist/task/WhileTask.d.ts +8 -4
  62. package/dist/task/WhileTask.d.ts.map +1 -1
  63. package/dist/task/WhileTaskRunner.d.ts +1 -1
  64. package/dist/task/WhileTaskRunner.d.ts.map +1 -1
  65. package/dist/task/index.d.ts +5 -0
  66. package/dist/task/index.d.ts.map +1 -1
  67. package/dist/task/iterationSchema.d.ts +2 -1
  68. package/dist/task/iterationSchema.d.ts.map +1 -1
  69. package/dist/task-graph/Dataflow.d.ts +1 -1
  70. package/dist/task-graph/Dataflow.d.ts.map +1 -1
  71. package/dist/task-graph/GraphEntitlementUtils.d.ts +30 -0
  72. package/dist/task-graph/GraphEntitlementUtils.d.ts.map +1 -0
  73. package/dist/task-graph/GraphFormatScanner.d.ts +41 -0
  74. package/dist/task-graph/GraphFormatScanner.d.ts.map +1 -0
  75. package/dist/task-graph/GraphToWorkflowCode.d.ts.map +1 -1
  76. package/dist/task-graph/TaskGraph.d.ts +23 -5
  77. package/dist/task-graph/TaskGraph.d.ts.map +1 -1
  78. package/dist/task-graph/TaskGraphEvents.d.ts +3 -0
  79. package/dist/task-graph/TaskGraphEvents.d.ts.map +1 -1
  80. package/dist/task-graph/TaskGraphRunner.d.ts +13 -1
  81. package/dist/task-graph/TaskGraphRunner.d.ts.map +1 -1
  82. package/dist/task-graph/Workflow.d.ts +29 -17
  83. package/dist/task-graph/Workflow.d.ts.map +1 -1
  84. package/package.json +12 -7
package/dist/node.js CHANGED
@@ -38,6 +38,11 @@ var TaskConfigSchema = {
38
38
  type: "object",
39
39
  additionalProperties: true,
40
40
  "x-ui-hidden": true
41
+ },
42
+ defaults: {
43
+ type: "object",
44
+ additionalProperties: true,
45
+ "x-ui-hidden": true
41
46
  }
42
47
  },
43
48
  additionalProperties: false
@@ -256,6 +261,316 @@ class DataflowArrow extends Dataflow {
256
261
  super(sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId);
257
262
  }
258
263
  }
264
+ // src/task/TaskEntitlements.ts
265
+ var Entitlements = {
266
+ NETWORK: "network",
267
+ NETWORK_HTTP: "network:http",
268
+ NETWORK_WEBSOCKET: "network:websocket",
269
+ NETWORK_PRIVATE: "network:private",
270
+ FILESYSTEM: "filesystem",
271
+ FILESYSTEM_READ: "filesystem:read",
272
+ FILESYSTEM_WRITE: "filesystem:write",
273
+ CODE_EXECUTION: "code-execution",
274
+ CODE_EXECUTION_JS: "code-execution:javascript",
275
+ CREDENTIAL: "credential",
276
+ AI: "ai",
277
+ AI_MODEL: "ai:model",
278
+ AI_INFERENCE: "ai:inference",
279
+ MCP: "mcp",
280
+ MCP_TOOL_CALL: "mcp:tool-call",
281
+ MCP_RESOURCE_READ: "mcp:resource-read",
282
+ MCP_PROMPT_GET: "mcp:prompt-get",
283
+ MCP_STDIO: "mcp:stdio",
284
+ STORAGE: "storage",
285
+ STORAGE_READ: "storage:read",
286
+ STORAGE_WRITE: "storage:write"
287
+ };
288
+ var EMPTY_ENTITLEMENTS = Object.freeze({
289
+ entitlements: Object.freeze([])
290
+ });
291
+ function entitlementCovers(granted, required) {
292
+ return required === granted || required.startsWith(granted + ":");
293
+ }
294
+ function resourcePatternMatches(grantPattern, requiredResource) {
295
+ if (grantPattern === requiredResource)
296
+ return true;
297
+ const starIdx = grantPattern.indexOf("*");
298
+ if (starIdx === -1)
299
+ return false;
300
+ const prefix = grantPattern.slice(0, starIdx);
301
+ const suffix = grantPattern.slice(starIdx + 1);
302
+ if (!requiredResource.startsWith(prefix))
303
+ return false;
304
+ if (!requiredResource.endsWith(suffix))
305
+ return false;
306
+ return requiredResource.length >= prefix.length + suffix.length;
307
+ }
308
+ function grantCoversResources(grant, required) {
309
+ if (grant.resources === undefined)
310
+ return true;
311
+ if (required.resources === undefined)
312
+ return false;
313
+ return required.resources.every((req) => grant.resources.some((pat) => resourcePatternMatches(pat, req)));
314
+ }
315
+ function mergeEntitlements(a, b) {
316
+ if (a.entitlements.length === 0)
317
+ return b;
318
+ if (b.entitlements.length === 0)
319
+ return a;
320
+ const merged = new Map;
321
+ for (const entitlement of a.entitlements) {
322
+ merged.set(entitlement.id, entitlement);
323
+ }
324
+ for (const entitlement of b.entitlements) {
325
+ const existing = merged.get(entitlement.id);
326
+ if (existing) {
327
+ merged.set(entitlement.id, mergeEntitlementPair(existing, entitlement));
328
+ } else {
329
+ merged.set(entitlement.id, entitlement);
330
+ }
331
+ }
332
+ return { entitlements: Array.from(merged.values()) };
333
+ }
334
+ function mergeEntitlementPair(a, b) {
335
+ const optional = (a.optional ?? false) && (b.optional ?? false) ? true : undefined;
336
+ const reason = a.reason ?? b.reason;
337
+ const resources = mergeResources(a.resources, b.resources);
338
+ const result = {
339
+ id: a.id,
340
+ ...reason !== undefined && { reason },
341
+ ...optional === true && { optional: true },
342
+ ...resources !== undefined && { resources }
343
+ };
344
+ return result;
345
+ }
346
+ function mergeResources(a, b) {
347
+ if (a === undefined || b === undefined)
348
+ return;
349
+ const set = new Set([...a, ...b]);
350
+ return Array.from(set);
351
+ }
352
+
353
+ // src/task-graph/GraphEntitlementUtils.ts
354
+ function computeGraphEntitlements(graph, options) {
355
+ const tasks = graph.getTasks();
356
+ if (tasks.length === 0)
357
+ return EMPTY_ENTITLEMENTS;
358
+ const trackOrigins = options?.trackOrigins ?? false;
359
+ const conditionalBranches = options?.conditionalBranches ?? "all";
360
+ const merged = new Map;
361
+ for (const task of tasks) {
362
+ if (conditionalBranches === "active" && task.status !== undefined) {
363
+ if (task.status === TaskStatus.DISABLED)
364
+ continue;
365
+ }
366
+ const taskEntitlements = task.entitlements();
367
+ for (const entitlement of taskEntitlements.entitlements) {
368
+ const existing = merged.get(entitlement.id);
369
+ if (existing) {
370
+ existing.entitlement = mergeEntitlementPair(existing.entitlement, entitlement);
371
+ if (trackOrigins) {
372
+ existing.sourceTaskIds.push(task.id);
373
+ }
374
+ } else {
375
+ merged.set(entitlement.id, {
376
+ entitlement,
377
+ sourceTaskIds: trackOrigins ? [task.id] : []
378
+ });
379
+ }
380
+ }
381
+ }
382
+ if (merged.size === 0)
383
+ return EMPTY_ENTITLEMENTS;
384
+ if (trackOrigins) {
385
+ const entitlements = [];
386
+ for (const { entitlement, sourceTaskIds } of merged.values()) {
387
+ entitlements.push({ ...entitlement, sourceTaskIds });
388
+ }
389
+ return { entitlements };
390
+ }
391
+ return { entitlements: Array.from(merged.values()).map((e) => e.entitlement) };
392
+ }
393
+ // src/task/InputResolver.ts
394
+ import { getInputResolvers } from "@workglow/util";
395
+ function getSchemaFormat(schema, visited = new WeakSet) {
396
+ if (typeof schema !== "object" || schema === null)
397
+ return;
398
+ if (visited.has(schema))
399
+ return;
400
+ visited.add(schema);
401
+ const s = schema;
402
+ if (typeof s.format === "string")
403
+ return s.format;
404
+ const variants = s.oneOf ?? s.anyOf;
405
+ if (Array.isArray(variants)) {
406
+ for (const variant of variants) {
407
+ if (typeof variant === "object" && variant !== null) {
408
+ const v = variant;
409
+ if (typeof v.format === "string")
410
+ return v.format;
411
+ }
412
+ }
413
+ }
414
+ const allOf = s.allOf;
415
+ if (Array.isArray(allOf)) {
416
+ for (const sub of allOf) {
417
+ const fmt = getSchemaFormat(sub, visited);
418
+ if (fmt !== undefined)
419
+ return fmt;
420
+ }
421
+ }
422
+ return;
423
+ }
424
+ function getObjectSchema(schema, visited = new WeakSet) {
425
+ if (typeof schema !== "object" || schema === null)
426
+ return;
427
+ if (visited.has(schema))
428
+ return;
429
+ visited.add(schema);
430
+ const s = schema;
431
+ if (s.type === "object" && s.properties && typeof s.properties === "object") {
432
+ return s;
433
+ }
434
+ const variants = s.oneOf ?? s.anyOf;
435
+ if (Array.isArray(variants)) {
436
+ for (const variant of variants) {
437
+ if (typeof variant === "object" && variant !== null) {
438
+ const v = variant;
439
+ if (v.type === "object" && v.properties && typeof v.properties === "object") {
440
+ return v;
441
+ }
442
+ }
443
+ }
444
+ }
445
+ const allOf = s.allOf;
446
+ if (Array.isArray(allOf)) {
447
+ for (const sub of allOf) {
448
+ const result = getObjectSchema(sub, visited);
449
+ if (result !== undefined)
450
+ return result;
451
+ }
452
+ }
453
+ return;
454
+ }
455
+ function getFormatPrefix(format) {
456
+ const colonIndex = format.indexOf(":");
457
+ return colonIndex >= 0 ? format.substring(0, colonIndex) : format;
458
+ }
459
+ function schemaHasFormatAnnotations(schema) {
460
+ if (typeof schema === "boolean")
461
+ return false;
462
+ const properties = schema.properties;
463
+ if (!properties || typeof properties !== "object")
464
+ return false;
465
+ for (const propSchema of Object.values(properties)) {
466
+ if (getSchemaFormat(propSchema) !== undefined)
467
+ return true;
468
+ }
469
+ return false;
470
+ }
471
+ async function resolveSchemaInputs(input, schema, config, visited = new Set) {
472
+ if (typeof schema === "boolean")
473
+ return input;
474
+ const properties = schema.properties;
475
+ if (!properties || typeof properties !== "object")
476
+ return input;
477
+ const resolvers = getInputResolvers();
478
+ const resolved = { ...input };
479
+ for (const [key, propSchema] of Object.entries(properties)) {
480
+ let value = resolved[key];
481
+ const format = getSchemaFormat(propSchema);
482
+ if (format) {
483
+ let resolver = resolvers.get(format);
484
+ if (!resolver) {
485
+ const prefix = getFormatPrefix(format);
486
+ resolver = resolvers.get(prefix);
487
+ }
488
+ if (resolver) {
489
+ if (typeof value === "string") {
490
+ value = await resolver(value, format, config.registry);
491
+ resolved[key] = value;
492
+ } else if (Array.isArray(value) && value.some((item) => typeof item === "string")) {
493
+ const results = await Promise.all(value.map((item) => typeof item === "string" ? resolver(item, format, config.registry) : item));
494
+ value = results.filter((result) => result !== undefined);
495
+ resolved[key] = value;
496
+ }
497
+ }
498
+ }
499
+ if (value !== null && value !== undefined && typeof value === "object" && !Array.isArray(value)) {
500
+ const objectSchema = getObjectSchema(propSchema);
501
+ if (objectSchema && !visited.has(objectSchema)) {
502
+ visited.add(objectSchema);
503
+ try {
504
+ resolved[key] = await resolveSchemaInputs(value, objectSchema, config, visited);
505
+ } finally {
506
+ visited.delete(objectSchema);
507
+ }
508
+ }
509
+ }
510
+ }
511
+ return resolved;
512
+ }
513
+
514
+ // src/task-graph/GraphFormatScanner.ts
515
+ function schemaHasFormat(schema, targetFormat) {
516
+ if (typeof schema !== "object" || schema === null)
517
+ return false;
518
+ const s = schema;
519
+ const properties = s.properties;
520
+ if (properties && typeof properties === "object") {
521
+ for (const propSchema of Object.values(properties)) {
522
+ const format = getSchemaFormat(propSchema);
523
+ if (format === targetFormat)
524
+ return true;
525
+ const objectSchema = getObjectSchema(propSchema);
526
+ if (objectSchema && schemaHasFormat(objectSchema, targetFormat))
527
+ return true;
528
+ }
529
+ }
530
+ return false;
531
+ }
532
+ function scanGraphForFormat(graph, targetFormat) {
533
+ for (const task of graph.getTasks()) {
534
+ const inputSchema = task.inputSchema();
535
+ if (typeof inputSchema !== "boolean" && schemaHasFormat(inputSchema, targetFormat)) {
536
+ return true;
537
+ }
538
+ const configSchema = task.configSchema();
539
+ if (typeof configSchema !== "boolean" && schemaHasFormat(configSchema, targetFormat)) {
540
+ return true;
541
+ }
542
+ }
543
+ return false;
544
+ }
545
+ function scanGraphForCredentials(graph) {
546
+ const credentialFormats = new Set;
547
+ for (const task of graph.getTasks()) {
548
+ collectCredentialFormats(task.inputSchema(), credentialFormats);
549
+ collectCredentialFormats(task.configSchema(), credentialFormats);
550
+ }
551
+ return {
552
+ needsCredentials: credentialFormats.size > 0,
553
+ credentialFormats
554
+ };
555
+ }
556
+ function collectCredentialFormats(schema, formats) {
557
+ if (typeof schema === "boolean" || typeof schema !== "object" || schema === null)
558
+ return;
559
+ const s = schema;
560
+ const properties = s.properties;
561
+ if (!properties || typeof properties !== "object")
562
+ return;
563
+ for (const propSchema of Object.values(properties)) {
564
+ const format = getSchemaFormat(propSchema);
565
+ if (format === "credential") {
566
+ formats.add(format);
567
+ }
568
+ const objectSchema = getObjectSchema(propSchema);
569
+ if (objectSchema) {
570
+ collectCredentialFormats(objectSchema, formats);
571
+ }
572
+ }
573
+ }
259
574
  // src/task-graph/GraphSchemaUtils.ts
260
575
  import { uuid4 } from "@workglow/util";
261
576
  function calculateNodeDepths(graph) {
@@ -605,8 +920,8 @@ function addBoundaryNodesToDependencyJson(items, graph) {
605
920
  return [...prependItems, ...items, ...appendItems];
606
921
  }
607
922
  // src/task-graph/TaskGraph.ts
608
- import { DirectedAcyclicGraph } from "@workglow/util/graph";
609
923
  import { EventEmitter as EventEmitter4, uuid4 as uuid44 } from "@workglow/util";
924
+ import { DirectedAcyclicGraph } from "@workglow/util/graph";
610
925
 
611
926
  // src/task/GraphAsTask.ts
612
927
  import { getLogger as getLogger4 } from "@workglow/util";
@@ -724,8 +1039,8 @@ function getNestedValue(obj, path) {
724
1039
  }
725
1040
 
726
1041
  // src/task/Task.ts
727
- import { compileSchema } from "@workglow/util/schema";
728
1042
  import { deepEqual, EventEmitter as EventEmitter3, uuid4 as uuid42 } from "@workglow/util";
1043
+ import { compileSchema } from "@workglow/util/schema";
729
1044
 
730
1045
  // src/task/TaskError.ts
731
1046
  import { BaseError } from "@workglow/util";
@@ -805,6 +1120,13 @@ class TaskInvalidInputError extends TaskError {
805
1120
  }
806
1121
  }
807
1122
 
1123
+ class TaskEntitlementError extends TaskError {
1124
+ static type = "TaskEntitlementError";
1125
+ constructor(message = "Required entitlements denied") {
1126
+ super(message);
1127
+ }
1128
+ }
1129
+
808
1130
  class TaskSerializationError extends TaskError {
809
1131
  static type = "TaskSerializationError";
810
1132
  constructor(taskType) {
@@ -820,100 +1142,6 @@ import {
820
1142
  SpanStatusCode
821
1143
  } from "@workglow/util";
822
1144
 
823
- // src/task/InputResolver.ts
824
- import { getInputResolvers } from "@workglow/util";
825
- function getSchemaFormat(schema) {
826
- if (typeof schema !== "object" || schema === null)
827
- return;
828
- const s = schema;
829
- if (typeof s.format === "string")
830
- return s.format;
831
- const variants = s.oneOf ?? s.anyOf;
832
- if (Array.isArray(variants)) {
833
- for (const variant of variants) {
834
- if (typeof variant === "object" && variant !== null) {
835
- const v = variant;
836
- if (typeof v.format === "string")
837
- return v.format;
838
- }
839
- }
840
- }
841
- return;
842
- }
843
- function getObjectSchema(schema) {
844
- if (typeof schema !== "object" || schema === null)
845
- return;
846
- const s = schema;
847
- if (s.type === "object" && s.properties && typeof s.properties === "object") {
848
- return s;
849
- }
850
- const variants = s.oneOf ?? s.anyOf;
851
- if (Array.isArray(variants)) {
852
- for (const variant of variants) {
853
- if (typeof variant === "object" && variant !== null) {
854
- const v = variant;
855
- if (v.type === "object" && v.properties && typeof v.properties === "object") {
856
- return v;
857
- }
858
- }
859
- }
860
- }
861
- return;
862
- }
863
- function getFormatPrefix(format) {
864
- const colonIndex = format.indexOf(":");
865
- return colonIndex >= 0 ? format.substring(0, colonIndex) : format;
866
- }
867
- function schemaHasFormatAnnotations(schema) {
868
- if (typeof schema === "boolean")
869
- return false;
870
- const properties = schema.properties;
871
- if (!properties || typeof properties !== "object")
872
- return false;
873
- for (const propSchema of Object.values(properties)) {
874
- if (getSchemaFormat(propSchema) !== undefined)
875
- return true;
876
- }
877
- return false;
878
- }
879
- async function resolveSchemaInputs(input, schema, config) {
880
- if (typeof schema === "boolean")
881
- return input;
882
- const properties = schema.properties;
883
- if (!properties || typeof properties !== "object")
884
- return input;
885
- const resolvers = getInputResolvers();
886
- const resolved = { ...input };
887
- for (const [key, propSchema] of Object.entries(properties)) {
888
- let value = resolved[key];
889
- const format = getSchemaFormat(propSchema);
890
- if (format) {
891
- let resolver = resolvers.get(format);
892
- if (!resolver) {
893
- const prefix = getFormatPrefix(format);
894
- resolver = resolvers.get(prefix);
895
- }
896
- if (resolver) {
897
- if (typeof value === "string") {
898
- value = await resolver(value, format, config.registry);
899
- resolved[key] = value;
900
- } else if (Array.isArray(value) && value.some((item) => typeof item === "string")) {
901
- const results = await Promise.all(value.map((item) => typeof item === "string" ? resolver(item, format, config.registry) : item));
902
- value = results.filter((result) => result !== undefined);
903
- resolved[key] = value;
904
- }
905
- }
906
- }
907
- if (value !== null && value !== undefined && typeof value === "object" && !Array.isArray(value)) {
908
- const objectSchema = getObjectSchema(propSchema);
909
- if (objectSchema) {
910
- resolved[key] = await resolveSchemaInputs(value, objectSchema, config);
911
- }
912
- }
913
- }
914
- return resolved;
915
- }
916
-
917
1145
  // src/task/StreamTypes.ts
918
1146
  function getPortStreamMode(schema, portId) {
919
1147
  if (typeof schema === "boolean")
@@ -1205,11 +1433,29 @@ class TaskRunner {
1205
1433
  }
1206
1434
  case "object-delta": {
1207
1435
  if (accumulatedObjects) {
1208
- accumulatedObjects.set(event.port, event.objectDelta);
1436
+ const existing = accumulatedObjects.get(event.port);
1437
+ if (Array.isArray(event.objectDelta)) {
1438
+ const arr = Array.isArray(existing) ? [...existing] : [];
1439
+ for (const item of event.objectDelta) {
1440
+ const itemObj = item;
1441
+ if (itemObj && typeof itemObj === "object" && "id" in itemObj) {
1442
+ const idx = arr.findIndex((e) => e.id === itemObj.id);
1443
+ if (idx >= 0)
1444
+ arr[idx] = item;
1445
+ else
1446
+ arr.push(item);
1447
+ } else {
1448
+ arr.push(item);
1449
+ }
1450
+ }
1451
+ accumulatedObjects.set(event.port, arr);
1452
+ } else {
1453
+ accumulatedObjects.set(event.port, event.objectDelta);
1454
+ }
1209
1455
  }
1210
1456
  this.task.runOutputData = {
1211
1457
  ...this.task.runOutputData,
1212
- [event.port]: event.objectDelta
1458
+ [event.port]: accumulatedObjects?.get(event.port) ?? event.objectDelta
1213
1459
  };
1214
1460
  this.task.emit("stream_chunk", event);
1215
1461
  const progress = Math.min(99, Math.round(100 * (1 - Math.exp(-0.05 * chunkCount))));
@@ -1270,11 +1516,6 @@ class TaskRunner {
1270
1516
  this.abortController.signal.addEventListener("abort", () => {
1271
1517
  this.handleAbort();
1272
1518
  });
1273
- if (config.signal?.aborted) {
1274
- this.abortController.abort();
1275
- } else if (config.signal) {
1276
- config.signal.addEventListener("abort", () => this.abortController.abort(), { once: true });
1277
- }
1278
1519
  const cache = config.outputCache ?? this.task.runConfig?.outputCache;
1279
1520
  if (cache === true) {
1280
1521
  let instance = globalServiceRegistry.get(TASK_OUTPUT_REPOSITORY);
@@ -1285,6 +1526,21 @@ class TaskRunner {
1285
1526
  this.outputCache = cache;
1286
1527
  }
1287
1528
  this.shouldAccumulate = config.shouldAccumulate !== false;
1529
+ if (config.updateProgress) {
1530
+ this.updateProgress = config.updateProgress;
1531
+ }
1532
+ if (config.registry) {
1533
+ this.registry = config.registry;
1534
+ }
1535
+ if (config.signal) {
1536
+ const onAbort = () => this.abortController.abort();
1537
+ config.signal.addEventListener("abort", onAbort, { once: true });
1538
+ if (config.signal.aborted) {
1539
+ config.signal.removeEventListener("abort", onAbort);
1540
+ this.abortController.abort();
1541
+ return;
1542
+ }
1543
+ }
1288
1544
  const timeout = this.task.config.timeout;
1289
1545
  if (timeout !== undefined && timeout > 0) {
1290
1546
  this.pendingTimeoutError = new TaskTimeoutError(timeout);
@@ -1292,12 +1548,6 @@ class TaskRunner {
1292
1548
  this.abort();
1293
1549
  }, timeout);
1294
1550
  }
1295
- if (config.updateProgress) {
1296
- this.updateProgress = config.updateProgress;
1297
- }
1298
- if (config.registry) {
1299
- this.registry = config.registry;
1300
- }
1301
1551
  const telemetry = getTelemetryProvider();
1302
1552
  if (telemetry.isEnabled) {
1303
1553
  this.telemetrySpan = telemetry.startSpan("workglow.task.run", {
@@ -1434,6 +1684,11 @@ class Task {
1434
1684
  static hasDynamicSchemas = false;
1435
1685
  static passthroughInputsToOutputs = false;
1436
1686
  static customizable = false;
1687
+ static isGraphOutput = false;
1688
+ static hasDynamicEntitlements = false;
1689
+ static entitlements() {
1690
+ return EMPTY_ENTITLEMENTS;
1691
+ }
1437
1692
  static inputSchema() {
1438
1693
  return {
1439
1694
  type: "object",
@@ -1488,6 +1743,13 @@ class Task {
1488
1743
  configSchema() {
1489
1744
  return this.constructor.configSchema();
1490
1745
  }
1746
+ entitlements() {
1747
+ return this.constructor.entitlements();
1748
+ }
1749
+ emitEntitlementChange(entitlements) {
1750
+ const final = entitlements ?? this.entitlements();
1751
+ this.emit("entitlementChange", final);
1752
+ }
1491
1753
  get type() {
1492
1754
  return this.constructor.type;
1493
1755
  }
@@ -1525,15 +1787,16 @@ class Task {
1525
1787
  return this._events;
1526
1788
  }
1527
1789
  _events;
1528
- constructor(callerDefaultInputs = {}, config = {}, runConfig = {}) {
1790
+ constructor(config = {}, runConfig = {}) {
1791
+ const { defaults: callerDefaultInputs, ...restConfig } = config;
1529
1792
  const inputDefaults = this.getDefaultInputsFromStaticInputDefinitions();
1530
- const mergedDefaults = Object.assign(inputDefaults, callerDefaultInputs);
1793
+ const mergedDefaults = Object.assign(inputDefaults, callerDefaultInputs ?? {});
1531
1794
  this.defaults = this.stripSymbols(mergedDefaults);
1532
1795
  this.resetInputData();
1533
1796
  const title = this.constructor.title || undefined;
1534
1797
  const baseConfig = Object.assign({
1535
1798
  ...title ? { title } : {}
1536
- }, config);
1799
+ }, restConfig);
1537
1800
  if (baseConfig.id === undefined) {
1538
1801
  baseConfig.id = uuid42();
1539
1802
  }
@@ -1880,6 +2143,10 @@ class Task {
1880
2143
  if (Object.keys(config).length > 0) {
1881
2144
  base.config = config;
1882
2145
  }
2146
+ const taskEntitlements = this.entitlements();
2147
+ if (taskEntitlements.entitlements.length > 0) {
2148
+ base.entitlements = taskEntitlements;
2149
+ }
1883
2150
  return this.stripSymbols(base);
1884
2151
  }
1885
2152
  toDependencyJSON(options) {
@@ -2009,7 +2276,7 @@ class ConditionalTask extends Task {
2009
2276
  }
2010
2277
  }
2011
2278
  } catch (error) {
2012
- getLogger2().warn(`Condition evaluation failed for branch "${branch.id}":`, { error });
2279
+ getLogger2().error(`Condition evaluation failed for branch "${branch.id}":`, { error });
2013
2280
  }
2014
2281
  }
2015
2282
  if (this.activeBranches.size === 0 && defaultBranch) {
@@ -2133,6 +2400,111 @@ class ConditionalTask extends Task {
2133
2400
  }
2134
2401
  }
2135
2402
 
2403
+ // src/task/EntitlementEnforcer.ts
2404
+ import { createServiceToken as createServiceToken3 } from "@workglow/util";
2405
+
2406
+ // src/task/EntitlementPolicy.ts
2407
+ var EMPTY_POLICY = Object.freeze({
2408
+ deny: Object.freeze([]),
2409
+ grant: Object.freeze([]),
2410
+ ask: Object.freeze([])
2411
+ });
2412
+ function ruleCovers(rule, required) {
2413
+ if (!entitlementCovers(rule.id, required.id))
2414
+ return false;
2415
+ return grantCoversResources(rule, required);
2416
+ }
2417
+ function evaluatePolicy(policy, required) {
2418
+ const results = [];
2419
+ for (const entitlement of required.entitlements) {
2420
+ if (entitlement.optional)
2421
+ continue;
2422
+ const denyMatch = policy.deny.find((rule) => ruleCovers(rule, entitlement));
2423
+ if (denyMatch) {
2424
+ results.push({ verdict: "denied", entitlement, matchedRule: denyMatch });
2425
+ continue;
2426
+ }
2427
+ const grantMatch = policy.grant.find((rule) => ruleCovers(rule, entitlement));
2428
+ if (grantMatch) {
2429
+ results.push({ verdict: "granted", entitlement, matchedRule: grantMatch });
2430
+ continue;
2431
+ }
2432
+ const askMatch = policy.ask.find((rule) => ruleCovers(rule, entitlement));
2433
+ if (askMatch) {
2434
+ results.push({ verdict: "ask", entitlement, matchedRule: askMatch });
2435
+ continue;
2436
+ }
2437
+ results.push({ verdict: "denied", entitlement });
2438
+ }
2439
+ return results;
2440
+ }
2441
+
2442
+ // src/task/EntitlementResolver.ts
2443
+ import { createServiceToken as createServiceToken2 } from "@workglow/util";
2444
+ var PERMISSIVE_RESOLVER = {
2445
+ lookup: () => "grant",
2446
+ prompt: async () => "grant",
2447
+ save: () => {}
2448
+ };
2449
+ var DENY_ALL_RESOLVER = {
2450
+ lookup: () => "deny",
2451
+ prompt: async () => "deny",
2452
+ save: () => {}
2453
+ };
2454
+ var ENTITLEMENT_RESOLVER = createServiceToken2("workglow.entitlementResolver");
2455
+
2456
+ // src/task/EntitlementEnforcer.ts
2457
+ var PERMISSIVE_ENFORCER = {
2458
+ checkAll: async () => [],
2459
+ checkTask: async () => []
2460
+ };
2461
+ function createPolicyEnforcer(policy, resolver = PERMISSIVE_RESOLVER) {
2462
+ async function resolveAsks(required, taskType, taskId) {
2463
+ const results = evaluatePolicy(policy, required);
2464
+ const denied = [];
2465
+ for (const result of results) {
2466
+ if (result.verdict === "denied") {
2467
+ denied.push(result.entitlement);
2468
+ } else if (result.verdict === "ask") {
2469
+ const request = {
2470
+ entitlement: result.entitlement,
2471
+ taskType: taskType ?? "unknown",
2472
+ taskId: taskId ?? "unknown"
2473
+ };
2474
+ const saved = resolver.lookup(request);
2475
+ if (saved !== undefined) {
2476
+ if (saved === "deny") {
2477
+ denied.push(result.entitlement);
2478
+ }
2479
+ continue;
2480
+ }
2481
+ const answer = await resolver.prompt(request);
2482
+ resolver.save(request, answer);
2483
+ if (answer === "deny") {
2484
+ denied.push(result.entitlement);
2485
+ }
2486
+ }
2487
+ }
2488
+ return denied;
2489
+ }
2490
+ return {
2491
+ async checkAll(required) {
2492
+ return resolveAsks(required);
2493
+ },
2494
+ async checkTask(task) {
2495
+ const entitlements = task.entitlements();
2496
+ return resolveAsks(entitlements, task.constructor.type, task.id);
2497
+ }
2498
+ };
2499
+ }
2500
+ function createScopedEnforcer(grants) {
2501
+ return createPolicyEnforcer({ deny: [], grant: grants, ask: [] });
2502
+ }
2503
+ function createGrantListEnforcer(grants) {
2504
+ return createScopedEnforcer(grants.map((id) => ({ id })));
2505
+ }
2506
+ var ENTITLEMENT_ENFORCER = createServiceToken3("workglow.entitlementEnforcer");
2507
+
2136
2508
  // src/task-graph/TaskGraphScheduler.ts
2137
2509
  class TopologicalScheduler {
2138
2510
  dag;
@@ -2301,6 +2673,7 @@ class TaskGraphRunner {
2301
2673
  telemetrySpan;
2302
2674
  graphTimeoutTimer;
2303
2675
  pendingGraphTimeoutError;
2676
+ activeEnforcer;
2304
2677
  constructor(graph, outputCache, processScheduler = new DependencyBasedScheduler(graph), reactiveScheduler = new TopologicalScheduler(graph)) {
2305
2678
  this.processScheduler = processScheduler;
2306
2679
  this.reactiveScheduler = reactiveScheduler;
@@ -2369,7 +2742,7 @@ class TaskGraphRunner {
2369
2742
  throw new TaskAbortedError;
2370
2743
  }
2371
2744
  await this.handleComplete();
2372
- return results;
2745
+ return this.filterLeafResults(results);
2373
2746
  }
2374
2747
  async runGraphReactive(input = {}, config) {
2375
2748
  await this.handleStartReactive(config);
@@ -2393,7 +2766,7 @@ class TaskGraphRunner {
2393
2766
  }
2394
2767
  }
2395
2768
  await this.handleCompleteReactive();
2396
- return results;
2769
+ return this.filterLeafResults(results);
2397
2770
  } catch (error) {
2398
2771
  await this.handleErrorReactive();
2399
2772
  throw error;
@@ -2425,6 +2798,15 @@ class TaskGraphRunner {
2425
2798
  task.regenerateGraph();
2426
2799
  }
2427
2800
  }
2801
+ filterLeafResults(results) {
2802
+ if (results.length <= 1)
2803
+ return results;
2804
+ const graphOutputResults = results.filter((r) => {
2805
+ const task = this.graph.getTask(r.id);
2806
+ return task && task.constructor.isGraphOutput;
2807
+ });
2808
+ return graphOutputResults.length > 0 ? graphOutputResults : results;
2809
+ }
2428
2810
  mergeExecuteOutputsToRunOutput(results, compoundMerge) {
2429
2811
  if (compoundMerge === GRAPH_RESULT_ARRAY) {
2430
2812
  return results;
@@ -2606,6 +2988,12 @@ class TaskGraphRunner {
2606
2988
  }
2607
2989
  await this.awaitStreamInputs(task);
2608
2990
  this.copyInputFromEdgesToNode(task);
2991
+ if (this.activeEnforcer && task.constructor.hasDynamicEntitlements) {
2992
+ const denied = await this.activeEnforcer.checkTask(task);
2993
+ if (denied.length > 0) {
2994
+ throw new TaskEntitlementError(`Task ${task.constructor.type} denied entitlements: ${denied.map((e) => e.id).join(", ")}`);
2995
+ }
2996
+ }
2609
2997
  if (isStreamable) {
2610
2998
  return this.runStreamingTask(task, input);
2611
2999
  }
@@ -2775,12 +3163,6 @@ class TaskGraphRunner {
2775
3163
  }
2776
3164
  this.graph.outputCache = this.outputCache;
2777
3165
  }
2778
- if (config?.maxTasks !== undefined && config.maxTasks > 0) {
2779
- const taskCount = this.graph.getTasks().length;
2780
- if (taskCount > config.maxTasks) {
2781
- throw new TaskConfigurationError(`Graph has ${taskCount} tasks, exceeding the limit of ${config.maxTasks}`);
2782
- }
2783
- }
2784
3166
  if (this.running || this.reactiveRunning) {
2785
3167
  throw new TaskConfigurationError("Graph is already running");
2786
3168
  }
@@ -2796,13 +3178,16 @@ class TaskGraphRunner {
2796
3178
  this.abortController?.abort();
2797
3179
  }, config.timeout);
2798
3180
  }
2799
- if (config?.parentSignal?.aborted) {
2800
- this.abortController.abort();
2801
- return;
2802
- } else {
2803
- config?.parentSignal?.addEventListener("abort", () => {
3181
+ if (config?.parentSignal) {
3182
+ const onParentAbort = () => {
2804
3183
  this.abortController?.abort();
2805
- }, { once: true });
3184
+ };
3185
+ config.parentSignal.addEventListener("abort", onParentAbort, { once: true });
3186
+ if (config.parentSignal.aborted) {
3187
+ config.parentSignal.removeEventListener("abort", onParentAbort);
3188
+ this.abortController.abort();
3189
+ return;
3190
+ }
2806
3191
  }
2807
3192
  this.runId = uuid43();
2808
3193
  this.resetGraph(this.graph, this.runId);
@@ -2810,6 +3195,36 @@ class TaskGraphRunner {
2810
3195
  this.inProgressTasks.clear();
2811
3196
  this.inProgressFunctions.clear();
2812
3197
  this.failedTaskErrors.clear();
3198
+ try {
3199
+ if (config?.maxTasks !== undefined && config.maxTasks > 0) {
3200
+ const taskCount = this.graph.getTasks().length;
3201
+ if (taskCount > config.maxTasks) {
3202
+ throw new TaskConfigurationError(`Graph has ${taskCount} tasks, exceeding the limit of ${config.maxTasks}`);
3203
+ }
3204
+ }
3205
+ if (config?.enforceEntitlements) {
3206
+ if (!this.registry.has(ENTITLEMENT_ENFORCER)) {
3207
+ throw new TaskConfigurationError("enforceEntitlements is enabled but no IEntitlementEnforcer is registered. " + "Register an enforcer via ENTITLEMENT_ENFORCER before running the graph.");
3208
+ }
3209
+ const enforcer = this.registry.get(ENTITLEMENT_ENFORCER);
3210
+ const denied = await enforcer.checkAll(computeGraphEntitlements(this.graph));
3211
+ if (denied.length > 0) {
3212
+ throw new TaskEntitlementError(`Denied entitlements: ${denied.map((e) => e.id).join(", ")}`);
3213
+ }
3214
+ this.activeEnforcer = enforcer;
3215
+ } else {
3216
+ this.activeEnforcer = undefined;
3217
+ }
3218
+ } catch (err) {
3219
+ if (this.graphTimeoutTimer !== undefined) {
3220
+ clearTimeout(this.graphTimeoutTimer);
3221
+ this.graphTimeoutTimer = undefined;
3222
+ }
3223
+ this.abortController = undefined;
3224
+ this.activeEnforcer = undefined;
3225
+ this.running = false;
3226
+ throw err;
3227
+ }
2813
3228
  const telemetry = getTelemetryProvider2();
2814
3229
  if (telemetry.isEnabled) {
2815
3230
  this.telemetrySpan = telemetry.startSpan("workglow.graph.run", {
@@ -2847,6 +3262,7 @@ class TaskGraphRunner {
2847
3262
  async handleComplete() {
2848
3263
  this.clearGraphTimeout();
2849
3264
  this.running = false;
3265
+ this.activeEnforcer = undefined;
2850
3266
  if (this.telemetrySpan) {
2851
3267
  this.telemetrySpan.setStatus(SpanStatusCode2.OK);
2852
3268
  this.telemetrySpan.end();
@@ -2865,6 +3281,7 @@ class TaskGraphRunner {
2865
3281
  }
2866
3282
  }));
2867
3283
  this.running = false;
3284
+ this.activeEnforcer = undefined;
2868
3285
  if (this.telemetrySpan) {
2869
3286
  this.telemetrySpan.setStatus(SpanStatusCode2.ERROR, error.message);
2870
3287
  this.telemetrySpan.setAttributes({ "workglow.graph.error": error.message });
@@ -2884,6 +3301,7 @@ class TaskGraphRunner {
2884
3301
  }
2885
3302
  }));
2886
3303
  this.running = false;
3304
+ this.activeEnforcer = undefined;
2887
3305
  if (this.telemetrySpan) {
2888
3306
  this.telemetrySpan.setStatus(SpanStatusCode2.ERROR, "aborted");
2889
3307
  this.telemetrySpan.addEvent("workglow.graph.aborted");
@@ -2985,9 +3403,10 @@ class GraphAsTask extends Task {
2985
3403
  static category = "Flow Control";
2986
3404
  static compoundMerge = PROPERTY_ARRAY;
2987
3405
  static hasDynamicSchemas = true;
2988
- constructor(input = {}, config = {}) {
3406
+ static hasDynamicEntitlements = true;
3407
+ constructor(config = {}) {
2989
3408
  const { subGraph, ...rest } = config;
2990
- super(input, rest);
3409
+ super(rest);
2991
3410
  if (subGraph) {
2992
3411
  this.subGraph = subGraph;
2993
3412
  }
@@ -3034,6 +3453,12 @@ class GraphAsTask extends Task {
3034
3453
  }
3035
3454
  return computeGraphOutputSchema(this.subGraph);
3036
3455
  }
3456
+ entitlements() {
3457
+ if (!this.hasChildren()) {
3458
+ return this.constructor.entitlements();
3459
+ }
3460
+ return computeGraphEntitlements(this.subGraph);
3461
+ }
3037
3462
  resetInputData() {
3038
3463
  super.resetInputData();
3039
3464
  if (this.hasChildren()) {
@@ -3072,26 +3497,44 @@ class GraphAsTask extends Task {
3072
3497
  }
3073
3498
  }
3074
3499
  const eventQueue = [];
3075
- let resolveWaiting;
3076
3500
  let subgraphDone = false;
3501
+ let { promise: notifyPromise, resolve: notifyResolve } = Promise.withResolvers();
3502
+ let isWaiting = false;
3503
+ let hasPending = false;
3504
+ const notify = () => {
3505
+ if (isWaiting) {
3506
+ notifyResolve();
3507
+ ({ promise: notifyPromise, resolve: notifyResolve } = Promise.withResolvers());
3508
+ isWaiting = false;
3509
+ } else {
3510
+ hasPending = true;
3511
+ }
3512
+ };
3077
3513
  const unsub = this.subGraph.subscribeToTaskStreaming({
3078
3514
  onStreamChunk: (taskId, event) => {
3079
3515
  if (endingNodeIds.has(taskId) && event.type !== "finish") {
3080
3516
  eventQueue.push(event);
3081
- resolveWaiting?.();
3517
+ notify();
3082
3518
  }
3083
3519
  }
3084
3520
  });
3085
3521
  const runPromise = this.subGraph.run(input, { parentSignal: context.signal, accumulateLeafOutputs: false }).then((results2) => {
3086
3522
  subgraphDone = true;
3087
- resolveWaiting?.();
3523
+ notify();
3088
3524
  return results2;
3525
+ }, (err) => {
3526
+ subgraphDone = true;
3527
+ notify();
3528
+ throw err;
3089
3529
  });
3090
3530
  while (!subgraphDone) {
3091
3531
  if (eventQueue.length === 0) {
3092
- await new Promise((resolve) => {
3093
- resolveWaiting = resolve;
3094
- });
3532
+ if (hasPending) {
3533
+ hasPending = false;
3534
+ } else {
3535
+ isWaiting = true;
3536
+ await notifyPromise;
3537
+ }
3095
3538
  }
3096
3539
  while (eventQueue.length > 0) {
3097
3540
  yield eventQueue.shift();
@@ -3111,6 +3554,7 @@ class GraphAsTask extends Task {
3111
3554
  regenerateGraph() {
3112
3555
  this._inputSchemaNode = undefined;
3113
3556
  this.events.emit("regenerate");
3557
+ this.emitEntitlementChange();
3114
3558
  }
3115
3559
  toJSON(options) {
3116
3560
  let json = super.toJSON(options);
@@ -3145,8 +3589,8 @@ function getWrapperClasses() {
3145
3589
  if (!_OwnGraphTask) {
3146
3590
 
3147
3591
  class ListeningGraphAsTask extends GraphAsTask {
3148
- constructor(input, config) {
3149
- super(input, config);
3592
+ constructor(config) {
3593
+ super(config);
3150
3594
  this.subGraph.on("start", () => {
3151
3595
  this.emit("start");
3152
3596
  });
@@ -3207,7 +3651,7 @@ function convertPipeFunctionToTask(fn, config) {
3207
3651
  return fn(input, context);
3208
3652
  }
3209
3653
  }
3210
- return new QuickTask({}, config);
3654
+ return new QuickTask(config);
3211
3655
  }
3212
3656
  function isWorkflowLike(arg) {
3213
3657
  return arg != null && typeof arg === "object" && "graph" in arg && arg.graph instanceof TaskGraph && "run" in arg && typeof arg.run === "function";
@@ -3220,18 +3664,18 @@ function ensureTask(arg, config = {}) {
3220
3664
  getWrapperClasses();
3221
3665
  const { isOwned, ...cleanConfig } = config;
3222
3666
  if (isOwned) {
3223
- return new _OwnGraphTask({}, { ...cleanConfig, subGraph: arg });
3667
+ return new _OwnGraphTask({ ...cleanConfig, subGraph: arg });
3224
3668
  } else {
3225
- return new _GraphTask({}, { ...cleanConfig, subGraph: arg });
3669
+ return new _GraphTask({ ...cleanConfig, subGraph: arg });
3226
3670
  }
3227
3671
  }
3228
3672
  if (isWorkflowLike(arg)) {
3229
3673
  getWrapperClasses();
3230
3674
  const { isOwned, ...cleanConfig } = config;
3231
3675
  if (isOwned) {
3232
- return new _OwnWorkflowTask({}, { ...cleanConfig, subGraph: arg.graph });
3676
+ return new _OwnWorkflowTask({ ...cleanConfig, subGraph: arg.graph });
3233
3677
  } else {
3234
- return new _ConvWorkflowTask({}, { ...cleanConfig, subGraph: arg.graph });
3678
+ return new _ConvWorkflowTask({ ...cleanConfig, subGraph: arg.graph });
3235
3679
  }
3236
3680
  }
3237
3681
  return convertPipeFunctionToTask(arg, config);
@@ -3499,6 +3943,43 @@ class TaskGraph {
3499
3943
  unsubscribes.forEach((unsub) => unsub());
3500
3944
  };
3501
3945
  }
3946
+ subscribeToTaskEntitlements(callback) {
3947
+ const globalUnsubs = [];
3948
+ const taskUnsubs = new Map;
3949
+ const emitChange = () => {
3950
+ const entitlements = computeGraphEntitlements(this);
3951
+ this.emit("entitlementChange", entitlements);
3952
+ callback(entitlements);
3953
+ };
3954
+ const subscribeTask = (taskId) => {
3955
+ const task = this.getTask(taskId);
3956
+ if (!task || typeof task.subscribe !== "function")
3957
+ return;
3958
+ const unsub = task.subscribe("entitlementChange", () => emitChange());
3959
+ taskUnsubs.set(taskId, unsub);
3960
+ };
3961
+ for (const task of this.getTasks()) {
3962
+ subscribeTask(task.id);
3963
+ }
3964
+ emitChange();
3965
+ globalUnsubs.push(this.subscribe("task_added", (taskId) => {
3966
+ subscribeTask(taskId);
3967
+ emitChange();
3968
+ }));
3969
+ globalUnsubs.push(this.subscribe("task_removed", (taskId) => {
3970
+ const unsub = taskUnsubs.get(taskId);
3971
+ if (unsub) {
3972
+ unsub();
3973
+ taskUnsubs.delete(taskId);
3974
+ }
3975
+ emitChange();
3976
+ }));
3977
+ return () => {
3978
+ globalUnsubs.forEach((unsub) => unsub());
3979
+ taskUnsubs.forEach((unsub) => unsub());
3980
+ taskUnsubs.clear();
3981
+ };
3982
+ }
3502
3983
  on(name, fn) {
3503
3984
  const dagEvent = EventTaskGraphToDagMapping[name];
3504
3985
  if (dagEvent) {
@@ -3543,11 +4024,7 @@ function serialGraph(tasks, inputHandle, outputHandle) {
3543
4024
  return graph;
3544
4025
  }
3545
4026
  // src/task-graph/Workflow.ts
3546
- import {
3547
- EventEmitter as EventEmitter5,
3548
- getLogger as getLogger5,
3549
- uuid4 as uuid45
3550
- } from "@workglow/util";
4027
+ import { EventEmitter as EventEmitter5, getLogger as getLogger5, uuid4 as uuid45 } from "@workglow/util";
3551
4028
  function getLastTask(workflow) {
3552
4029
  const tasks = workflow.graph.getTasks();
3553
4030
  return tasks.length > 0 ? tasks[tasks.length - 1] : undefined;
@@ -3570,7 +4047,6 @@ function pipe(args, workflow = new Workflow) {
3570
4047
  function parallel(args, mergeFn = PROPERTY_ARRAY, workflow = new Workflow) {
3571
4048
  let previousTask = getLastTask(workflow);
3572
4049
  const tasks = args.map((arg) => ensureTask(arg));
3573
- const input = {};
3574
4050
  const config = {
3575
4051
  compoundMerge: mergeFn
3576
4052
  };
@@ -3579,7 +4055,7 @@ function parallel(args, mergeFn = PROPERTY_ARRAY, workflow = new Workflow) {
3579
4055
  class ParallelTask extends GraphAsTask {
3580
4056
  static type = name;
3581
4057
  }
3582
- const mergeTask = new ParallelTask(input, config);
4058
+ const mergeTask = new ParallelTask(config);
3583
4059
  mergeTask.subGraph.addTasks(tasks);
3584
4060
  workflow.graph.addTask(mergeTask);
3585
4061
  if (previousTask) {
@@ -3674,6 +4150,7 @@ class Workflow {
3674
4150
  _error = "";
3675
4151
  _outputCache;
3676
4152
  _registry;
4153
+ _entitlementUnsub;
3677
4154
  _abortController;
3678
4155
  _parentWorkflow;
3679
4156
  _iteratorTask;
@@ -3689,7 +4166,11 @@ class Workflow {
3689
4166
  const helper = function(input = {}, config = {}) {
3690
4167
  this._error = "";
3691
4168
  const parent = getLastTask(this);
3692
- const task = this.addTaskToGraph(taskClass, input, { id: uuid45(), ...config });
4169
+ const task = this.addTaskToGraph(taskClass, {
4170
+ id: uuid45(),
4171
+ ...config,
4172
+ defaults: input
4173
+ });
3693
4174
  if (this._dataFlows.length > 0) {
3694
4175
  this._dataFlows.forEach((dataflow) => {
3695
4176
  const taskSchema = task.inputSchema();
@@ -3824,6 +4305,9 @@ class Workflow {
3824
4305
  toDependencyJSON(options = { withBoundaryNodes: true }) {
3825
4306
  return this._graph.toDependencyJSON(options);
3826
4307
  }
4308
+ entitlements(options) {
4309
+ return computeGraphEntitlements(this._graph, options);
4310
+ }
3827
4311
  pipe(...args) {
3828
4312
  return pipe(args, this);
3829
4313
  }
@@ -3908,6 +4392,7 @@ class Workflow {
3908
4392
  this._graph.on("dataflow_added", this._onChanged);
3909
4393
  this._graph.on("dataflow_replaced", this._onChanged);
3910
4394
  this._graph.on("dataflow_removed", this._onChanged);
4395
+ this._entitlementUnsub = this._graph.subscribeToTaskEntitlements((entitlements) => this.events.emit("entitlementChange", entitlements));
3911
4396
  }
3912
4397
  clearEvents() {
3913
4398
  this._graph.off("task_added", this._onChanged);
@@ -3916,6 +4401,8 @@ class Workflow {
3916
4401
  this._graph.off("dataflow_added", this._onChanged);
3917
4402
  this._graph.off("dataflow_replaced", this._onChanged);
3918
4403
  this._graph.off("dataflow_removed", this._onChanged);
4404
+ this._entitlementUnsub?.();
4405
+ this._entitlementUnsub = undefined;
3919
4406
  }
3920
4407
  _onChanged(id) {
3921
4408
  this.events.emit("changed", id);
@@ -3947,8 +4434,8 @@ class Workflow {
3947
4434
  this.graph.addDataflow(dataflow);
3948
4435
  return this;
3949
4436
  }
3950
- addTaskToGraph(taskClass, input, config) {
3951
- const task = new taskClass(input, config, this._registry ? { registry: this._registry } : undefined);
4437
+ addTaskToGraph(taskClass, config) {
4438
+ const task = new taskClass(config, this._registry ? { registry: this._registry } : undefined);
3952
4439
  const id = this.graph.addTask(task);
3953
4440
  this.events.emit("changed", id);
3954
4441
  return task;
@@ -3960,7 +4447,7 @@ class Workflow {
3960
4447
  addLoopTask(taskClass, config = {}) {
3961
4448
  this._error = "";
3962
4449
  const parent = getLastTask(this);
3963
- const task = this.addTaskToGraph(taskClass, {}, { id: uuid45(), ...config });
4450
+ const task = this.addTaskToGraph(taskClass, { id: uuid45(), ...config });
3964
4451
  if (this._dataFlows.length > 0) {
3965
4452
  this._dataFlows.forEach((dataflow) => {
3966
4453
  const taskSchema = task.inputSchema();
@@ -4057,10 +4544,29 @@ class Workflow {
4057
4544
  const sourceSchema = sourceTask.outputSchema();
4058
4545
  if (typeof sourceSchema === "boolean")
4059
4546
  continue;
4060
- const prop = sourceSchema.properties?.[df.sourceTaskPortId];
4547
+ let prop = sourceSchema.properties?.[df.sourceTaskPortId];
4548
+ let propRequired = sourceSchema.required?.includes(df.sourceTaskPortId) ?? false;
4549
+ if (!prop && sourceSchema.additionalProperties === true && sourceTask.constructor.passthroughInputsToOutputs === true) {
4550
+ const upstreamDfs = graph.getSourceDataflows(sourceTask.id);
4551
+ for (const udf of upstreamDfs) {
4552
+ if (udf.targetTaskPortId !== df.sourceTaskPortId)
4553
+ continue;
4554
+ const upstreamTask = graph.getTask(udf.sourceTaskId);
4555
+ if (!upstreamTask)
4556
+ continue;
4557
+ const upstreamSchema = upstreamTask.outputSchema();
4558
+ if (typeof upstreamSchema === "boolean")
4559
+ continue;
4560
+ prop = upstreamSchema.properties?.[udf.sourceTaskPortId];
4561
+ if (prop) {
4562
+ propRequired = upstreamSchema.required?.includes(udf.sourceTaskPortId) ?? false;
4563
+ break;
4564
+ }
4565
+ }
4566
+ }
4061
4567
  if (prop && typeof prop !== "boolean") {
4062
4568
  properties[df.targetTaskPortId] = prop;
4063
- if (sourceSchema.required?.includes(df.sourceTaskPortId) && !required.includes(df.targetTaskPortId)) {
4569
+ if (propRequired && !required.includes(df.targetTaskPortId)) {
4064
4570
  required.push(df.targetTaskPortId);
4065
4571
  }
4066
4572
  }
@@ -4160,11 +4666,30 @@ class Workflow {
4160
4666
  const makeMatch = (fromSchema, toSchema, fromTaskId, toTaskId, comparator) => {
4161
4667
  if (typeof fromSchema === "object") {
4162
4668
  if (toSchema === true || typeof toSchema === "object" && toSchema.additionalProperties === true) {
4163
- for (const fromOutputPortId of Object.keys(fromSchema.properties || {})) {
4164
- if (matches.has(fromOutputPortId))
4165
- continue;
4166
- matches.set(fromOutputPortId, fromOutputPortId);
4167
- graph.addDataflow(new Dataflow(fromTaskId, fromOutputPortId, toTaskId, fromOutputPortId));
4669
+ const outputKeys = Object.keys(fromSchema.properties || {});
4670
+ if (outputKeys.length > 0) {
4671
+ for (const fromOutputPortId of outputKeys) {
4672
+ if (matches.has(fromOutputPortId))
4673
+ continue;
4674
+ matches.set(fromOutputPortId, fromOutputPortId);
4675
+ graph.addDataflow(new Dataflow(fromTaskId, fromOutputPortId, toTaskId, fromOutputPortId));
4676
+ }
4677
+ } else if (fromSchema.additionalProperties === true) {
4678
+ const sourceGraphTask = graph.getTask(fromTaskId);
4679
+ if (sourceGraphTask && sourceGraphTask.constructor.passthroughInputsToOutputs === true) {
4680
+ const incomingDfs = graph.getSourceDataflows(fromTaskId);
4681
+ for (const df of incomingDfs) {
4682
+ const portId = df.targetTaskPortId;
4683
+ if (portId === DATAFLOW_ALL_PORTS)
4684
+ continue;
4685
+ if (matches.has(portId))
4686
+ continue;
4687
+ if (connectedInputKeys.has(portId))
4688
+ continue;
4689
+ matches.set(portId, portId);
4690
+ graph.addDataflow(new Dataflow(fromTaskId, portId, toTaskId, portId));
4691
+ }
4692
+ }
4168
4693
  }
4169
4694
  return;
4170
4695
  }
@@ -4647,6 +5172,37 @@ ${baseIndent}}`;
4647
5172
  function resetMethodNameCache() {
4648
5173
  methodNameCache = undefined;
4649
5174
  }
5175
+ // src/task/EntitlementProfiles.ts
5176
+ var BROWSER_GRANTS = [
5177
+ { id: Entitlements.NETWORK },
5178
+ { id: Entitlements.AI },
5179
+ { id: Entitlements.MCP_TOOL_CALL },
5180
+ { id: Entitlements.MCP_RESOURCE_READ },
5181
+ { id: Entitlements.MCP_PROMPT_GET },
5182
+ { id: Entitlements.STORAGE },
5183
+ { id: Entitlements.CREDENTIAL }
5184
+ ];
5185
+ var DESKTOP_GRANTS = [
5186
+ ...BROWSER_GRANTS,
5187
+ { id: Entitlements.FILESYSTEM },
5188
+ { id: Entitlements.CODE_EXECUTION },
5189
+ { id: Entitlements.MCP_STDIO }
5190
+ ];
5191
+ var SERVER_GRANTS = [...DESKTOP_GRANTS];
5192
+ var PROFILE_GRANTS = {
5193
+ browser: BROWSER_GRANTS,
5194
+ desktop: DESKTOP_GRANTS,
5195
+ server: SERVER_GRANTS
5196
+ };
5197
+ function createProfilePolicy(profile) {
5198
+ return { deny: [], grant: PROFILE_GRANTS[profile], ask: [] };
5199
+ }
5200
+ function createProfileEnforcer(profile, resolver) {
5201
+ return createPolicyEnforcer(createProfilePolicy(profile), resolver);
5202
+ }
5203
+ function getProfileGrants(profile) {
5204
+ return PROFILE_GRANTS[profile];
5205
+ }
4650
5206
  // src/task/FallbackTaskRunner.ts
4651
5207
  class FallbackTaskRunner extends GraphAsTaskRunner {
4652
5208
  async executeTask(input) {
@@ -4848,22 +5404,32 @@ queueMicrotask(() => {
4848
5404
  });
4849
5405
  // src/task/InputCompactor.ts
4850
5406
  import { getInputCompactors } from "@workglow/util";
4851
- function schemaAllowsString(schema) {
5407
+ function schemaAllowsString(schema, visited = new WeakSet) {
4852
5408
  if (typeof schema !== "object" || schema === null)
4853
5409
  return false;
5410
+ if (visited.has(schema))
5411
+ return false;
5412
+ visited.add(schema);
4854
5413
  const s = schema;
4855
5414
  if (s.type === "string")
4856
5415
  return true;
4857
5416
  const variants = s.oneOf ?? s.anyOf;
4858
5417
  if (Array.isArray(variants)) {
4859
5418
  for (const variant of variants) {
4860
- if (schemaAllowsString(variant))
5419
+ if (schemaAllowsString(variant, visited))
5420
+ return true;
5421
+ }
5422
+ }
5423
+ const allOf = s.allOf;
5424
+ if (Array.isArray(allOf)) {
5425
+ for (const sub of allOf) {
5426
+ if (schemaAllowsString(sub, visited))
4861
5427
  return true;
4862
5428
  }
4863
5429
  }
4864
5430
  return false;
4865
5431
  }
4866
- async function compactSchemaInputs(input, schema, config) {
5432
+ async function compactSchemaInputs(input, schema, config, visited = new Set) {
4867
5433
  if (typeof schema === "boolean")
4868
5434
  return input;
4869
5435
  const properties = schema.properties;
@@ -4901,8 +5467,13 @@ async function compactSchemaInputs(input, schema, config) {
4901
5467
  }
4902
5468
  if (value !== null && value !== undefined && typeof value === "object" && !Array.isArray(value)) {
4903
5469
  const objectSchema = getObjectSchema(propSchema);
4904
- if (objectSchema) {
4905
- compacted[key] = await compactSchemaInputs(value, objectSchema, config);
5470
+ if (objectSchema && !visited.has(objectSchema)) {
5471
+ visited.add(objectSchema);
5472
+ try {
5473
+ compacted[key] = await compactSchemaInputs(value, objectSchema, config, visited);
5474
+ } finally {
5475
+ visited.delete(objectSchema);
5476
+ }
4906
5477
  }
4907
5478
  }
4908
5479
  }
@@ -5026,7 +5597,7 @@ class IteratorTaskRunner extends GraphAsTaskRunner {
5026
5597
  const newId = uuid46();
5027
5598
  idMap.set(task.config.id, newId);
5028
5599
  const clonedConfig = { ...task.config, id: newId };
5029
- const newTask = new ctor(task.defaults, clonedConfig, task.runConfig);
5600
+ const newTask = new ctor({ ...clonedConfig, defaults: task.defaults }, task.runConfig);
5030
5601
  if (task.hasChildren()) {
5031
5602
  newTask.subGraph = this.cloneGraph(task.subGraph);
5032
5603
  }
@@ -5226,9 +5797,6 @@ class IteratorTask extends GraphAsTask {
5226
5797
  }
5227
5798
  _iteratorPortInfo;
5228
5799
  _iterationInputSchema;
5229
- constructor(input = {}, config = {}) {
5230
- super(input, config);
5231
- }
5232
5800
  get runner() {
5233
5801
  if (!this._runner) {
5234
5802
  this._runner = new IteratorTaskRunner(this);
@@ -5639,9 +6207,6 @@ class WhileTask extends GraphAsTask {
5639
6207
  canSerializeConfig() {
5640
6208
  return typeof this.config.condition !== "function";
5641
6209
  }
5642
- constructor(input = {}, config = {}) {
5643
- super(input, config);
5644
- }
5645
6210
  get runner() {
5646
6211
  if (!this._runner) {
5647
6212
  this._runner = new WhileTaskRunner(this);
@@ -6163,8 +6728,8 @@ import {
6163
6728
  JobQueueServer
6164
6729
  } from "@workglow/job-queue";
6165
6730
  import { InMemoryQueueStorage } from "@workglow/storage";
6166
- import { createServiceToken as createServiceToken2, globalServiceRegistry as globalServiceRegistry3 } from "@workglow/util";
6167
- var JOB_QUEUE_FACTORY = createServiceToken2("taskgraph.jobQueueFactory");
6731
+ import { createServiceToken as createServiceToken4, globalServiceRegistry as globalServiceRegistry3 } from "@workglow/util";
6732
+ var JOB_QUEUE_FACTORY = createServiceToken4("taskgraph.jobQueueFactory");
6168
6733
  var defaultJobQueueFactory = async ({
6169
6734
  queueName,
6170
6735
  jobClass,
@@ -6329,13 +6894,13 @@ class ReduceTask extends IteratorTask {
6329
6894
  static configSchema() {
6330
6895
  return reduceTaskConfigSchema;
6331
6896
  }
6332
- constructor(input = {}, config = {}) {
6897
+ constructor(config = {}) {
6333
6898
  const reduceConfig = {
6334
6899
  ...config,
6335
6900
  concurrencyLimit: 1,
6336
6901
  batchSize: 1
6337
6902
  };
6338
- super(input, reduceConfig);
6903
+ super(reduceConfig);
6339
6904
  }
6340
6905
  get initialValue() {
6341
6906
  return this.config.initialValue ?? {};
@@ -6407,24 +6972,48 @@ queueMicrotask(() => {
6407
6972
  });
6408
6973
  // src/task/TaskRegistry.ts
6409
6974
  import {
6410
- createServiceToken as createServiceToken3,
6975
+ createServiceToken as createServiceToken5,
6976
+ getLogger as getLogger6,
6411
6977
  globalServiceRegistry as globalServiceRegistry4,
6412
6978
  registerInputCompactor,
6413
6979
  registerInputResolver
6414
6980
  } from "@workglow/util";
6981
+ import { validateSchema } from "@workglow/util/schema";
6415
6982
  var taskConstructors = new Map;
6416
6983
  function registerTask(baseClass) {
6417
- if (taskConstructors.has(baseClass.type)) {}
6984
+ const existing = taskConstructors.get(baseClass.type);
6985
+ if (existing) {
6986
+ if (existing === baseClass)
6987
+ return;
6988
+ throw new Error(`Task type "${baseClass.type}" is already registered. Unregister it first to replace.`);
6989
+ }
6418
6990
  taskConstructors.set(baseClass.type, baseClass);
6991
+ const schemas = [
6992
+ { name: "inputSchema", schema: baseClass.inputSchema() },
6993
+ { name: "outputSchema", schema: baseClass.outputSchema() }
6994
+ ];
6995
+ for (const { name, schema } of schemas) {
6996
+ const result = validateSchema(schema);
6997
+ if (!result.valid) {
6998
+ const messages = result.errors.map((e) => `${e.path}: ${e.message}`).join("; ");
6999
+ getLogger6().warn(`Task "${baseClass.type}" has invalid ${name}: ${messages}`, {
7000
+ taskType: baseClass.type,
7001
+ schemaName: name,
7002
+ errors: result.errors
7003
+ });
7004
+ }
7005
+ }
7006
+ }
7007
+ function unregisterTask(type) {
7008
+ return taskConstructors.delete(type);
6419
7009
  }
6420
7010
  var TaskRegistry = {
6421
7011
  all: taskConstructors,
6422
- registerTask
7012
+ registerTask,
7013
+ unregisterTask
6423
7014
  };
6424
- var TASK_CONSTRUCTORS = createServiceToken3("task.constructors");
6425
- if (!globalServiceRegistry4.has(TASK_CONSTRUCTORS)) {
6426
- globalServiceRegistry4.register(TASK_CONSTRUCTORS, () => TaskRegistry.all, true);
6427
- }
7015
+ var TASK_CONSTRUCTORS = createServiceToken5("task.constructors");
7016
+ globalServiceRegistry4.registerIfAbsent(TASK_CONSTRUCTORS, () => TaskRegistry.all, true);
6428
7017
  function getGlobalTaskConstructors() {
6429
7018
  return globalServiceRegistry4.get(TASK_CONSTRUCTORS);
6430
7019
  }
@@ -6482,11 +7071,15 @@ var createSingleTaskFromJSON = (item, registry, options) => {
6482
7071
  const taskClass = constructors.get(item.type);
6483
7072
  if (!taskClass)
6484
7073
  throw new TaskJSONError(`Task type ${item.type} not found, perhaps not registered?`);
7074
+ if (typeof taskClass !== "function" || typeof taskClass.type !== "string") {
7075
+ throw new TaskJSONError(`Task type ${item.type} resolved to an invalid constructor`);
7076
+ }
6485
7077
  const taskConfig = {
6486
7078
  ...item.config,
6487
- id: item.id
7079
+ id: item.id,
7080
+ defaults: item.defaults ?? {}
6488
7081
  };
6489
- const task = new taskClass(item.defaults ?? {}, taskConfig, registry ? { registry } : {});
7082
+ const task = new taskClass(taskConfig, registry ? { registry } : {});
6490
7083
  return task;
6491
7084
  };
6492
7085
  var createTaskFromDependencyJSON = (item, registry, options) => {
@@ -6580,8 +7173,8 @@ var registerBaseTasks = () => {
6580
7173
  return tasks;
6581
7174
  };
6582
7175
  // src/storage/TaskGraphRepository.ts
6583
- import { createServiceToken as createServiceToken4, EventEmitter as EventEmitter7 } from "@workglow/util";
6584
- var TASK_GRAPH_REPOSITORY = createServiceToken4("taskgraph.taskGraphRepository");
7176
+ import { createServiceToken as createServiceToken6, EventEmitter as EventEmitter7 } from "@workglow/util";
7177
+ var TASK_GRAPH_REPOSITORY = createServiceToken6("taskgraph.taskGraphRepository");
6585
7178
 
6586
7179
  class TaskGraphRepository {
6587
7180
  type = "TaskGraphRepository";
@@ -6747,6 +7340,9 @@ export {
6747
7340
  serialGraph,
6748
7341
  schemaHasFormatAnnotations,
6749
7342
  schemaAcceptsArray,
7343
+ scanGraphForFormat,
7344
+ scanGraphForCredentials,
7345
+ resourcePatternMatches,
6750
7346
  resolveSchemaInputs,
6751
7347
  resetMethodNameCache,
6752
7348
  removeIterationProperties,
@@ -6755,6 +7351,9 @@ export {
6755
7351
  reduceTaskConfigSchema,
6756
7352
  pipe,
6757
7353
  parallel,
7354
+ mergeResources,
7355
+ mergeEntitlements,
7356
+ mergeEntitlementPair,
6758
7357
  mergeChainedOutputToInput,
6759
7358
  mapTaskConfigSchema,
6760
7359
  iteratorTaskConfigSchema,
@@ -6767,11 +7366,13 @@ export {
6767
7366
  hasStructuredOutput,
6768
7367
  graphToWorkflowCode,
6769
7368
  graphAsTaskConfigSchema,
7369
+ grantCoversResources,
6770
7370
  getTaskQueueRegistry,
6771
7371
  getTaskConstructors,
6772
7372
  getStructuredOutputSchemas,
6773
7373
  getStreamingPorts,
6774
7374
  getSchemaFormat,
7375
+ getProfileGrants,
6775
7376
  getPortStreamMode,
6776
7377
  getOutputStreamMode,
6777
7378
  getObjectSchema,
@@ -6790,20 +7391,28 @@ export {
6790
7391
  fallbackTaskConfigSchema,
6791
7392
  extractIterationProperties,
6792
7393
  extractBaseSchema,
7394
+ evaluatePolicy,
6793
7395
  evaluateCondition,
7396
+ entitlementCovers,
6794
7397
  ensureTask,
6795
7398
  edgeNeedsAccumulation,
6796
7399
  createTaskFromGraphJSON,
6797
7400
  createTaskFromDependencyJSON,
7401
+ createScopedEnforcer,
7402
+ createProfilePolicy,
7403
+ createProfileEnforcer,
7404
+ createPolicyEnforcer,
6798
7405
  createJobQueueFactoryWithOptions,
6799
7406
  createGraphFromGraphJSON,
6800
7407
  createGraphFromDependencyJSON,
7408
+ createGrantListEnforcer,
6801
7409
  createFlexibleSchema,
6802
7410
  createArraySchema,
6803
7411
  connect,
6804
7412
  conditionalTaskConfigSchema,
6805
7413
  computeGraphOutputSchema,
6806
7414
  computeGraphInputSchema,
7415
+ computeGraphEntitlements,
6807
7416
  compactSchemaInputs,
6808
7417
  calculateNodeDepths,
6809
7418
  buildIterationInputSchema,
@@ -6835,6 +7444,7 @@ export {
6835
7444
  TaskGraph,
6836
7445
  TaskFailedError,
6837
7446
  TaskError,
7447
+ TaskEntitlementError,
6838
7448
  TaskConfigurationError,
6839
7449
  TaskConfigSchema,
6840
7450
  TaskAbortedError,
@@ -6842,8 +7452,11 @@ export {
6842
7452
  TASK_OUTPUT_REPOSITORY,
6843
7453
  TASK_GRAPH_REPOSITORY,
6844
7454
  TASK_CONSTRUCTORS,
7455
+ SERVER_GRANTS,
6845
7456
  ReduceTask,
6846
7457
  PROPERTY_ARRAY,
7458
+ PERMISSIVE_RESOLVER,
7459
+ PERMISSIVE_ENFORCER,
6847
7460
  MapTask,
6848
7461
  JobTaskFailedError,
6849
7462
  JOB_QUEUE_FACTORY,
@@ -6857,15 +7470,23 @@ export {
6857
7470
  FallbackTask,
6858
7471
  EventTaskGraphToDagMapping,
6859
7472
  EventDagToTaskGraphMapping,
7473
+ Entitlements,
7474
+ ENTITLEMENT_RESOLVER,
7475
+ ENTITLEMENT_ENFORCER,
7476
+ EMPTY_POLICY,
7477
+ EMPTY_ENTITLEMENTS,
6860
7478
  DataflowArrow,
6861
7479
  Dataflow,
7480
+ DESKTOP_GRANTS,
7481
+ DENY_ALL_RESOLVER,
6862
7482
  DATAFLOW_ERROR_PORT,
6863
7483
  DATAFLOW_ALL_PORTS,
6864
7484
  CreateWorkflow,
6865
7485
  CreateLoopWorkflow,
6866
7486
  CreateEndLoopWorkflow,
6867
7487
  CreateAdaptiveWorkflow,
6868
- ConditionalTask
7488
+ ConditionalTask,
7489
+ BROWSER_GRANTS
6869
7490
  };
6870
7491
 
6871
- //# debugId=F0FF9D519957480A64756E2164756E21
7492
+ //# debugId=B1EF4C881FE1D2EF64756E2164756E21