@workglow/task-graph 0.1.2 → 0.2.1

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