@oomol-lab/open-flow 0.1.0-beta.76 → 0.1.0-beta.78

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 (74) hide show
  1. package/README.md +3 -0
  2. package/dist/browser/{ContentIcon-Cm1hbVzW.js → ContentIcon-CMn0c-kl.js} +99 -6
  3. package/dist/browser/{FlowCanvas-NzKtla_c.js → FlowCanvas-BQGBcfoL.js} +1709 -613
  4. package/dist/browser/{createResourceDialog-BgdedQqu.js → createResourceDialog-DCGxfKFM.js} +63 -57
  5. package/dist/browser/{dialog-aSElFFw2.js → dialog-WzR4CRFH.js} +76 -77
  6. package/dist/browser/{exportSvg-Dcz4HTo_.js → exportSvg-CYwyYiuH.js} +2 -2
  7. package/dist/browser/{flowChanges-NZyS7HSp.js → flowChanges-Bz4dbDN_.js} +6875 -11091
  8. package/dist/browser/{flowWorkspace-Bl0SDehy.js → flowWorkspace-BI6L6a4r.js} +1415 -3037
  9. package/dist/browser/licenses.md +1 -1
  10. package/dist/browser/preview.css +619 -462
  11. package/dist/browser/preview.js +9016 -14956
  12. package/dist/browser/theme.css +4 -2
  13. package/dist/browser/{tooltip-3XMK9jkr.js → tooltip-BDcVTNpu.js} +65 -2
  14. package/dist/browser/{typeScriptSession-C9sBGOKZ.js → typeScriptSession-CRoezJPN.js} +1 -1
  15. package/dist/browser/ui.css +112 -24
  16. package/dist/browser/ui.js +3 -2
  17. package/dist/browser/workbench.css +10020 -9842
  18. package/dist/browser/workbench.d.ts +5 -2
  19. package/dist/browser/workbench.js +2382 -2668
  20. package/dist/browser/{workbenchSelect-DBGP7Y4Z.js → workbenchSelect-DtAd0zc4.js} +2 -2
  21. package/dist/command/index.js +48 -48
  22. package/dist/common/authoring.d.ts +4 -4
  23. package/dist/common/authoringExamples.d.ts +3 -2
  24. package/dist/common/authoringSchema.d.ts +15 -4
  25. package/dist/common/control-api-conformance.js +155 -15
  26. package/dist/common/control-api-errors.d.ts +12 -0
  27. package/dist/common/control-api.d.ts +39 -2
  28. package/dist/common/control-api.js +180 -37
  29. package/dist/common/control-requests.d.ts +23 -3
  30. package/dist/common/control-requests.js +141 -14
  31. package/dist/common/engine-contract.d.ts +3 -2
  32. package/dist/common/flow-authoring.js +47 -7
  33. package/dist/common/flow-change-schema.d.ts +1 -1
  34. package/dist/common/flow-change.d.ts +2 -2
  35. package/dist/common/flow-change.js +48 -8
  36. package/dist/common/flow-encoding.js +47 -7
  37. package/dist/common/flow-semantics.js +86 -8
  38. package/dist/common/flow-state.d.ts +100 -0
  39. package/dist/common/flow-state.js +5794 -0
  40. package/dist/common/mcp.d.ts +96 -3
  41. package/dist/common/mcp.js +158 -13
  42. package/dist/common/run-events.js +19 -8
  43. package/dist/common/runtime-contract.d.ts +14 -0
  44. package/dist/common/runtime-contract.js +124 -17
  45. package/dist/common/runtime-nodejs-compat.js +11 -12
  46. package/dist/common/scheduler-node-execution.d.ts +1 -0
  47. package/dist/common/scheduler.d.ts +2 -1
  48. package/dist/common/scheduler.js +95 -40
  49. package/dist/common/state-conformance.d.ts +16 -0
  50. package/dist/common/tags.d.ts +4 -0
  51. package/dist/index.d.ts +11 -0
  52. package/package.json +5 -1
  53. package/src/control/common/api.ts +101 -11
  54. package/src/control/common/authoring.ts +7 -1
  55. package/src/control/common/authoringExamples.ts +9 -0
  56. package/src/control/common/authoringSchema.ts +18 -12
  57. package/src/control/common/errors.ts +6 -0
  58. package/src/control/common/flowDecoders.ts +1 -0
  59. package/src/control/common/mcp.ts +16 -0
  60. package/src/control/common/requests.ts +16 -2
  61. package/src/control/common/tags.ts +20 -0
  62. package/src/execution/common/events.ts +22 -7
  63. package/src/execution/common/node-execution.ts +3 -0
  64. package/src/execution/common/scheduler.ts +29 -13
  65. package/src/flow/common/change.ts +2 -1
  66. package/src/flow/common/changeSchema.ts +11 -1
  67. package/src/flow/common/errorHandling.ts +1 -1
  68. package/src/flow/common/semantics.ts +27 -1
  69. package/src/runtime/common/engineContract.ts +6 -3
  70. package/src/runtime/common/nodejsGuest.generated.json +11 -12
  71. package/src/runtime/common/runtime.ts +122 -7
  72. package/src/state/common/conformance.ts +81 -0
  73. package/src/state/common/state.ts +141 -0
  74. package/src/types/index.ts +11 -0
@@ -10,7 +10,7 @@ export declare class AuthoringError extends Error {
10
10
  }
11
11
  export declare function authoringNode(content: RevisionContent, ref: string): {
12
12
  ref: string;
13
- type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
13
+ type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "skip-duplicates" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
14
14
  name: string;
15
15
  readOnly: boolean;
16
16
  description?: string | undefined;
@@ -82,7 +82,6 @@ export declare function authoringNode(content: RevisionContent, ref: string): {
82
82
  })[];
83
83
  };
84
84
  export declare function readAuthoring(content: RevisionContent, query?: AuthoringRead): {
85
- nodes?: undefined;
86
85
  text: {
87
86
  node: string;
88
87
  field: "code" | "prompt";
@@ -93,12 +92,13 @@ export declare function readAuthoring(content: RevisionContent, query?: Authorin
93
92
  nextStart?: number | undefined;
94
93
  truncated: boolean;
95
94
  };
95
+ nodes?: undefined;
96
96
  edges?: undefined;
97
97
  } | {
98
98
  text?: undefined;
99
99
  nodes: {
100
100
  ref: string;
101
- type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
101
+ type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "skip-duplicates" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
102
102
  name: string;
103
103
  readOnly: boolean;
104
104
  description?: string | undefined;
@@ -174,7 +174,7 @@ export declare function readAuthoring(content: RevisionContent, query?: Authorin
174
174
  text?: undefined;
175
175
  nodes: {
176
176
  ref: string;
177
- type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
177
+ type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "skip-duplicates" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
178
178
  name: string;
179
179
  readOnly: boolean;
180
180
  inputHandles: string[];
@@ -8,6 +8,7 @@ declare const descriptions: {
8
8
  readonly poll: 'Gmail polling by key; replace CONNECTION_ID with an active Gmail connection.';
9
9
  readonly integration: 'Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.';
10
10
  readonly decision: 'AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running.';
11
+ readonly 'skip-duplicates': 'Skip items already recorded by successful Runs. Configure identity fields; an empty list uses each string or numeric item. History is private to the node and only commits after Run success.';
11
12
  readonly 'http-request': 'A single HTTP request. Bind url and request inputs; outputs are body, statusCode and headers.';
12
13
  readonly openapi: 'A fixed JSON API operation. Replace the example document and URL before running.';
13
14
  readonly connector: 'A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show. Set connectionId to an empty string to defer account configuration; execution will require an account.';
@@ -23,8 +24,8 @@ declare const descriptions: {
23
24
  };
24
25
  export declare const authoringExampleNames: (keyof typeof descriptions)[];
25
26
  export declare const authoringExamples: {
26
- name: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm-chat" | "llm-json" | "openapi" | "poll" | "poll-notification" | "start" | "value" | "wait" | "webhook" | "webhook-response";
27
- description: "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show. Set connectionId to an empty string to defer account configuration; execution will require an account." | "A Flow Error node. Select upstream Flows, then publish and enable this Flow to listen for failures in their automatic runs." | "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions." | "A Start node with a required message parameter. Supply it through trigger.outputs." | "A Wait with a continue action and a built-in notification output." | "A Webhook start node." | "A condition with true and false execution branches." | "A fixed JSON API operation. Replace the example document and URL before running." | "A fixed value node." | "A single HTTP request. Bind url and request inputs; outputs are body, statusCode and headers." | "AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running." | "An Agent with code computation enabled. Configure a model available in the deployment." | "An Approval with approve and reject decision branches and a built-in notification output." | "An HTTP response node with body, statusCode and headers inputs. Select it from a reachable Webhook." | "An LLM JSON Task and its node; configure a model available in the deployment." | "An LLM chat Task and its node; configure a model available in the deployment." | "An hourly scheduled start node." | "Gmail events → JavaScript text formatting → Connector notification. Replace connection/action IDs and match the notification input ports." | "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection." | "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.";
27
+ name: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm-chat" | "llm-json" | "openapi" | "poll" | "poll-notification" | "skip-duplicates" | "start" | "value" | "wait" | "webhook" | "webhook-response";
28
+ description: "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show. Set connectionId to an empty string to defer account configuration; execution will require an account." | "A Flow Error node. Select upstream Flows, then publish and enable this Flow to listen for failures in their automatic runs." | "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions." | "A Start node with a required message parameter. Supply it through trigger.outputs." | "A Wait with a continue action and a built-in notification output." | "A Webhook start node." | "A condition with true and false execution branches." | "A fixed JSON API operation. Replace the example document and URL before running." | "A fixed value node." | "A single HTTP request. Bind url and request inputs; outputs are body, statusCode and headers." | "AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running." | "An Agent with code computation enabled. Configure a model available in the deployment." | "An Approval with approve and reject decision branches and a built-in notification output." | "An HTTP response node with body, statusCode and headers inputs. Select it from a reachable Webhook." | "An LLM JSON Task and its node; configure a model available in the deployment." | "An LLM chat Task and its node; configure a model available in the deployment." | "An hourly scheduled start node." | "Gmail events → JavaScript text formatting → Connector notification. Replace connection/action IDs and match the notification input ports." | "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection." | "Skip items already recorded by successful Runs. Configure identity fields; an empty list uses each string or numeric item. History is private to the node and only commits after Run success." | "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.";
28
29
  }[];
29
30
  export declare function authoringExample(name: string): {
30
31
  version: 1;
@@ -1,6 +1,6 @@
1
1
  import type { JsonValue } from '../index.js';
2
2
  import { z } from 'zod';
3
- export declare const authoringTypes: readonly ['start', 'outputs', 'webhook-response', 'workflow', 'webhook', 'cron', 'error', 'poll', 'integration', 'code', 'connector', 'agent', 'llm', 'decision', 'openapi', 'http-request', 'condition', 'value', 'wait', 'approval'];
3
+ export declare const authoringTypes: readonly ['start', 'outputs', 'webhook-response', 'workflow', 'webhook', 'cron', 'error', 'poll', 'integration', 'code', 'connector', 'agent', 'llm', 'decision', 'openapi', 'http-request', 'skip-duplicates', 'condition', 'value', 'wait', 'approval'];
4
4
  declare const type: z.ZodEnum<{
5
5
  agent: "agent";
6
6
  approval: "approval";
@@ -16,6 +16,7 @@ declare const type: z.ZodEnum<{
16
16
  openapi: "openapi";
17
17
  outputs: "outputs";
18
18
  poll: "poll";
19
+ "skip-duplicates": "skip-duplicates";
19
20
  start: "start";
20
21
  value: "value";
21
22
  wait: "wait";
@@ -303,6 +304,9 @@ export declare const authoringConfigurations: {
303
304
  success: "success";
304
305
  }>>;
305
306
  }, z.core.$strict>;
307
+ 'skip-duplicates': z.ZodObject<{
308
+ fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
309
+ }, z.core.$strict>;
306
310
  agent: z.ZodObject<{
307
311
  code: z.ZodOptional<z.ZodBoolean>;
308
312
  model: z.ZodString;
@@ -704,6 +708,7 @@ export declare const authoringEditSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
704
708
  openapi: "openapi";
705
709
  outputs: "outputs";
706
710
  poll: "poll";
711
+ "skip-duplicates": "skip-duplicates";
707
712
  start: "start";
708
713
  value: "value";
709
714
  wait: "wait";
@@ -875,6 +880,7 @@ export declare const authoringRequestSchema: z.ZodObject<{
875
880
  openapi: "openapi";
876
881
  outputs: "outputs";
877
882
  poll: "poll";
883
+ "skip-duplicates": "skip-duplicates";
878
884
  start: "start";
879
885
  value: "value";
880
886
  wait: "wait";
@@ -1060,6 +1066,7 @@ export declare const authoringSearchSchema: z.ZodObject<{
1060
1066
  openapi: "openapi";
1061
1067
  outputs: "outputs";
1062
1068
  poll: "poll";
1069
+ "skip-duplicates": "skip-duplicates";
1063
1070
  start: "start";
1064
1071
  value: "value";
1065
1072
  wait: "wait";
@@ -1091,6 +1098,7 @@ export declare const authoringSchemaQuery: z.ZodObject<{
1091
1098
  openapi: "openapi";
1092
1099
  outputs: "outputs";
1093
1100
  poll: "poll";
1101
+ "skip-duplicates": "skip-duplicates";
1094
1102
  start: "start";
1095
1103
  value: "value";
1096
1104
  wait: "wait";
@@ -1123,6 +1131,7 @@ export declare function authoringRequestContract(name: string): {
1123
1131
  openapi: "openapi";
1124
1132
  outputs: "outputs";
1125
1133
  poll: "poll";
1134
+ "skip-duplicates": "skip-duplicates";
1126
1135
  start: "start";
1127
1136
  value: "value";
1128
1137
  wait: "wait";
@@ -1305,6 +1314,7 @@ export declare function authoringRequestContract(name: string): {
1305
1314
  openapi: "openapi";
1306
1315
  outputs: "outputs";
1307
1316
  poll: "poll";
1317
+ "skip-duplicates": "skip-duplicates";
1308
1318
  start: "start";
1309
1319
  value: "value";
1310
1320
  wait: "wait";
@@ -1398,7 +1408,7 @@ export declare function authoringRequestContract(name: string): {
1398
1408
  } | undefined;
1399
1409
  export declare function authoringSchema(kind?: AuthoringType): {
1400
1410
  type?: undefined;
1401
- types: readonly ["start", "outputs", "webhook-response", "workflow", "webhook", "cron", "error", "poll", "integration", "code", "connector", "agent", "llm", "decision", "openapi", "http-request", "condition", "value", "wait", "approval"];
1411
+ types: readonly ["start", "outputs", "webhook-response", "workflow", "webhook", "cron", "error", "poll", "integration", "code", "connector", "agent", "llm", "decision", "openapi", "http-request", "skip-duplicates", "condition", "value", "wait", "approval"];
1402
1412
  request: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
1403
1413
  baseRevision: z.ZodString;
1404
1414
  requestId: z.ZodString;
@@ -1420,6 +1430,7 @@ export declare function authoringSchema(kind?: AuthoringType): {
1420
1430
  openapi: "openapi";
1421
1431
  outputs: "outputs";
1422
1432
  poll: "poll";
1433
+ "skip-duplicates": "skip-duplicates";
1423
1434
  start: "start";
1424
1435
  value: "value";
1425
1436
  wait: "wait";
@@ -1582,7 +1593,7 @@ export declare function authoringSchema(kind?: AuthoringType): {
1582
1593
  } | {
1583
1594
  types?: undefined;
1584
1595
  request?: undefined;
1585
- type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
1596
+ type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "skip-duplicates" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
1586
1597
  onError: boolean | {
1587
1598
  enum: string[];
1588
1599
  };
@@ -1596,7 +1607,7 @@ export declare function authoringSchema(kind?: AuthoringType): {
1596
1607
  example: {
1597
1608
  op: string;
1598
1609
  as: string;
1599
- type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
1610
+ type: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "decision" | "error" | "http-request" | "integration" | "llm" | "openapi" | "outputs" | "poll" | "skip-duplicates" | "start" | "value" | "wait" | "webhook" | "webhook-response" | "workflow";
1600
1611
  name: string;
1601
1612
  };
1602
1613
  configuration: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{}, z.core.$strict>>;
@@ -8628,6 +8628,44 @@ var httpRequestConfigSchema = strictObject({
8628
8628
  statusPolicy: _enum(["success", "all"]).default("success")
8629
8629
  });
8630
8630
  var httpRequestExecutorSchema = httpRequestConfigSchema.extend({ kind: literal("http-request") });
8631
+ strictObject({
8632
+ scope: _enum(["draft", "live"]),
8633
+ values: boolean().optional()
8634
+ });
8635
+ strictObject({
8636
+ scope: _enum(["draft", "live"]),
8637
+ key: string$1().min(1).refine((key) => new TextEncoder().encode(key).length <= 256).optional()
8638
+ });
8639
+ strictObject({
8640
+ scope: _enum(["draft", "live"]),
8641
+ space: string$1().regex(/^(flow|node:.+)$/)
8642
+ });
8643
+ var skipDuplicatesConfigSchema = strictObject({ fields: array(string$1().refine((field) => field.length > 0 && field.split(".").every((part) => part.length > 0), "Use a nonempty dot-separated field path.")).refine((fields) => new Set(fields).size === fields.length, "Identity fields must be distinct.").default([]) });
8644
+ var skipDuplicatesExecutorSchema = skipDuplicatesConfigSchema.extend({ kind: literal("skip-duplicates") });
8645
+ var flowStateViewSchema = object({
8646
+ version: literal(1),
8647
+ scope: _enum(["draft", "live"]),
8648
+ limits: object({
8649
+ maxValueBytes: number().positive(),
8650
+ maxValues: number().int().positive(),
8651
+ maxSpaces: number().int().positive(),
8652
+ maxIdentities: number().positive(),
8653
+ maxRunWrites: number().positive()
8654
+ }),
8655
+ values: array(object({
8656
+ key: string$1(),
8657
+ size: number().nonnegative(),
8658
+ updatedAt: number(),
8659
+ value: json$4().optional()
8660
+ })),
8661
+ spaces: array(object({
8662
+ space: string$1(),
8663
+ count: number().nonnegative(),
8664
+ pendingCount: number().nonnegative(),
8665
+ reservedCount: number().nonnegative(),
8666
+ updatedAt: number()
8667
+ }))
8668
+ });
8631
8669
  function checkJsonDepth(value, depth = 0) {
8632
8670
  if (depth > 64) throw new TypeError("Value exceeds the maximum JSON depth.");
8633
8671
  if (value != null && typeof value == "object") for (const child of Object.values(value)) checkJsonDepth(child, depth + 1);
@@ -8916,7 +8954,8 @@ var managedFields = object({
8916
8954
  flowId: text,
8917
8955
  revisionId: text
8918
8956
  }),
8919
- httpRequestExecutorSchema
8957
+ httpRequestExecutorSchema,
8958
+ skipDuplicatesExecutorSchema
8920
8959
  ])
8921
8960
  });
8922
8961
  var managed = managedFields.transform(limitDecisionTask);
@@ -9186,7 +9225,8 @@ var revision = object({
9186
9225
  literal(9),
9187
9226
  literal(10),
9188
9227
  literal(11),
9189
- literal(12)
9228
+ literal(12),
9229
+ literal(13)
9190
9230
  ]),
9191
9231
  document,
9192
9232
  modules: record$3(text, module)
@@ -9387,6 +9427,7 @@ array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, sha
9387
9427
  ...shape
9388
9428
  })])).values()])).min(1);
9389
9429
  function checkModelVersion(content) {
9430
+ if (content.modelVersion < 13 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind === "task" && "executor" in candidateNode.task && candidateNode.task.executor.kind === "skip-duplicates")) throw new Error("Skip Duplicates requires Flow model v13.");
9390
9431
  if (content.modelVersion < 12 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "moduleId" in candidateNode.task && candidateNode.task.capabilities?.some((item) => item.kind == "http"))) throw new TypeError("Code HTTP access requires Flow model version 12.");
9391
9432
  if (content.modelVersion < 11 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "executor" in candidateNode.task && candidateNode.task.executor.kind == "http-request")) throw new TypeError("HTTP Request requires Flow model version 11.");
9392
9433
  if (content.modelVersion < 11 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && ("moduleId" in candidateNode.task ? candidateNode.task.capabilities?.some((item) => item.kind == "workflow") : candidateNode.task.executor.kind == "agent" && candidateNode.task.executor.tools.some((item) => item.kind == "workflow")))) throw new TypeError("Workflow tools require Flow model version 11.");
@@ -9416,10 +9457,10 @@ function upgradeRevisionContent(content) {
9416
9457
  function upgradeDecodedRevisionContent(content) {
9417
9458
  const graph = content.document.graph;
9418
9459
  const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
9419
- if (!hasManual && content.modelVersion == 12) return content;
9460
+ if (!hasManual && content.modelVersion == 13) return content;
9420
9461
  return {
9421
9462
  ...content,
9422
- modelVersion: 12,
9463
+ modelVersion: 13,
9423
9464
  document: {
9424
9465
  ...content.document,
9425
9466
  graph: hasManual ? {
@@ -9438,8 +9479,8 @@ function upgradeManualTrigger(node) {
9438
9479
  }
9439
9480
  //#endregion
9440
9481
  //#region src/runtime/common/engineContract.ts
9441
- /** v9 is a single contract: the Node compatibility builtins, `context.fetch`, and no `context.egress`. */
9442
- var currentEngineContract = "open-flow-engine/v9";
9482
+ /** v10 adds persistent Flow State to the published v9 Node compatibility and fetch contract. */
9483
+ var currentEngineContract = "open-flow-engine/v10";
9443
9484
  /** The published v8 Node compatibility contract, retained for existing Publications and Runs. */
9444
9485
  var nodejsEngineContract = "open-flow-engine/v8/nodejs-compat-v1";
9445
9486
  var platformSource = (contract) => `export const engineContract = ${JSON.stringify(contract)}
@@ -9484,13 +9525,19 @@ var nodejsContract = {
9484
9525
  ].flatMap((name) => [name, `node:${name}`])),
9485
9526
  platformSource: platformSource(nodejsEngineContract)
9486
9527
  };
9487
- var currentContract = {
9528
+ var v9Contract = {
9488
9529
  ...nodejsContract,
9489
9530
  codeFetch: true,
9531
+ platformSource: platformSource("open-flow-engine/v9")
9532
+ };
9533
+ var currentContract = {
9534
+ ...v9Contract,
9535
+ flowState: true,
9490
9536
  platformSource: platformSource(currentEngineContract)
9491
9537
  };
9492
9538
  function findEngineContract(contract) {
9493
- if (contract == "open-flow-engine/v9") return currentContract;
9539
+ if (contract == "open-flow-engine/v10") return currentContract;
9540
+ if (contract == "open-flow-engine/v9") return v9Contract;
9494
9541
  if (contract == "open-flow-engine/v8") return v8Contract;
9495
9542
  if (contract == "open-flow-engine/v8/nodejs-compat-v1") return nodejsContract;
9496
9543
  if (contract == "open-flow-engine/v7" || contract == "open-flow-engine/v7/nodejs-compat-v1") return {
@@ -9594,6 +9641,7 @@ var type = _enum([
9594
9641
  "decision",
9595
9642
  "openapi",
9596
9643
  "http-request",
9644
+ "skip-duplicates",
9597
9645
  "condition",
9598
9646
  "value",
9599
9647
  "wait",
@@ -9724,6 +9772,7 @@ var authoringConfigurations = {
9724
9772
  "connector": authoringDefinitionSchemas.connector.omit({ outputMode: true }).strict(),
9725
9773
  "openapi": authoringOpenApiSchema,
9726
9774
  "http-request": httpRequestConfigSchema,
9775
+ "skip-duplicates": skipDuplicatesConfigSchema,
9727
9776
  "agent": authoringDefinitionSchemas.agent.omit({
9728
9777
  prompt: true,
9729
9778
  tools: true
@@ -9954,11 +10003,14 @@ var controlErrorCode = {
9954
10003
  triggerKeyInvalid: "trigger-key.invalid",
9955
10004
  triggerKeyNotFound: "trigger-key.not-found",
9956
10005
  triggerNotFound: "trigger.not-found",
10006
+ tagInvalid: "tag.invalid",
10007
+ tagConflict: "tag.conflict",
10008
+ tagNotFound: "tag.not-found",
9957
10009
  variableInvalid: "variable.invalid",
9958
10010
  variableLimitReached: "variable.limit-reached",
9959
10011
  variableNotFound: "variable.not-found"
9960
10012
  };
9961
- controlErrorCode.eventSourceInvalid, controlErrorCode.eventSourceIdentityUnavailable, controlErrorCode.eventSourceNotFound, controlErrorCode.eventSourceConflict, controlErrorCode.authenticationRequired, controlErrorCode.authorizationDenied, controlErrorCode.bindingUnresolved, controlErrorCode.connectorActionNotFound, controlErrorCode.connectorAccessConflict, controlErrorCode.connectorAccessInvalid, controlErrorCode.connectorAccessRequired, controlErrorCode.connectorAccessUnsupported, controlErrorCode.connectorUnconfigured, controlErrorCode.connectorUnavailable, controlErrorCode.connectorConsoleUnconfigured, controlErrorCode.engineUnavailable, controlErrorCode.engineUnsupported, controlErrorCode.flowInvalid, controlErrorCode.flowRepairRequired, controlErrorCode.flowUpgradeRequired, controlErrorCode.flowNotFound, controlErrorCode.flowBusy, controlErrorCode.flowConflict, controlErrorCode.flowPresentationConflict, controlErrorCode.flowRevisionConflict, controlErrorCode.liveConflict, controlErrorCode.liveNotFound, controlErrorCode.pageInvalidCursor, controlErrorCode.publicationConflict, controlErrorCode.publicationNotFound, controlErrorCode.publicationUnsupported, controlErrorCode.publishOperationNotFound, controlErrorCode.routeNotFound, controlErrorCode.runConflict, controlErrorCode.runEventsExpired, controlErrorCode.runInvalid, controlErrorCode.runNotFound, controlErrorCode.runNotTerminal, controlErrorCode.runOverloaded, controlErrorCode.runWaitNotFound, controlErrorCode.triggerKeyInvalid, controlErrorCode.triggerKeyNotFound, controlErrorCode.triggerNotFound, controlErrorCode.variableInvalid, controlErrorCode.variableLimitReached, controlErrorCode.variableNotFound;
10013
+ controlErrorCode.eventSourceInvalid, controlErrorCode.eventSourceIdentityUnavailable, controlErrorCode.eventSourceNotFound, controlErrorCode.eventSourceConflict, controlErrorCode.authenticationRequired, controlErrorCode.authorizationDenied, controlErrorCode.bindingUnresolved, controlErrorCode.connectorActionNotFound, controlErrorCode.connectorAccessConflict, controlErrorCode.connectorAccessInvalid, controlErrorCode.connectorAccessRequired, controlErrorCode.connectorAccessUnsupported, controlErrorCode.connectorUnconfigured, controlErrorCode.connectorUnavailable, controlErrorCode.connectorConsoleUnconfigured, controlErrorCode.engineUnavailable, controlErrorCode.engineUnsupported, controlErrorCode.flowInvalid, controlErrorCode.flowRepairRequired, controlErrorCode.flowUpgradeRequired, controlErrorCode.flowNotFound, controlErrorCode.flowBusy, controlErrorCode.flowConflict, controlErrorCode.flowPresentationConflict, controlErrorCode.flowRevisionConflict, controlErrorCode.liveConflict, controlErrorCode.liveNotFound, controlErrorCode.pageInvalidCursor, controlErrorCode.publicationConflict, controlErrorCode.publicationNotFound, controlErrorCode.publicationUnsupported, controlErrorCode.publishOperationNotFound, controlErrorCode.routeNotFound, controlErrorCode.runConflict, controlErrorCode.runEventsExpired, controlErrorCode.runInvalid, controlErrorCode.runNotFound, controlErrorCode.runNotTerminal, controlErrorCode.runOverloaded, controlErrorCode.runWaitNotFound, controlErrorCode.triggerKeyInvalid, controlErrorCode.triggerKeyNotFound, controlErrorCode.triggerNotFound, controlErrorCode.tagInvalid, controlErrorCode.tagConflict, controlErrorCode.tagNotFound, controlErrorCode.variableInvalid, controlErrorCode.variableLimitReached, controlErrorCode.variableNotFound;
9962
10014
  var ApiError = class extends Error {
9963
10015
  constructor(status, code, message, details) {
9964
10016
  super(message);
@@ -11230,6 +11282,7 @@ function flow(value) {
11230
11282
  publicationId: string(target.publicationId),
11231
11283
  revisionId: string(target.revisionId)
11232
11284
  } },
11285
+ tagIds: source.tagIds === void 0 ? [] : strings(source.tagIds),
11233
11286
  createdAt: string(source.createdAt),
11234
11287
  ...source.connectorTeamId == null ? {} : { connectorTeamId: string(source.connectorTeamId) },
11235
11288
  draftRevisionId: string(source.draftRevisionId),
@@ -11675,6 +11728,33 @@ function randomId() {
11675
11728
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
11676
11729
  }
11677
11730
  //#endregion
11731
+ //#region src/control/common/tags.ts
11732
+ function normalizeFlowQuery(query = {}) {
11733
+ return {
11734
+ query: query.query?.trim().toLowerCase() ?? "",
11735
+ tagIds: [...new Set(query.tagIds ?? [])].toSorted(),
11736
+ untagged: query.untagged ?? false
11737
+ };
11738
+ }
11739
+ function decodeTag(value) {
11740
+ const source = record$1(value);
11741
+ if (source.version != 1) return invalidResponse();
11742
+ return {
11743
+ tagId: string(source.tagId),
11744
+ name: string(source.name),
11745
+ version: 1
11746
+ };
11747
+ }
11748
+ function decodeTagListItem(value) {
11749
+ const source = record$1(value);
11750
+ const referenceCount = integer(source.referenceCount);
11751
+ if (referenceCount < 0) return invalidResponse();
11752
+ return {
11753
+ ...decodeTag(source),
11754
+ referenceCount
11755
+ };
11756
+ }
11757
+ //#endregion
11678
11758
  //#region src/control/common/api.ts
11679
11759
  function decodeRunEvent(value) {
11680
11760
  const source = record$1(value);
@@ -11778,7 +11858,7 @@ function decodeRunEvent(value) {
11778
11858
  switch (kind) {
11779
11859
  case "node.started": {
11780
11860
  const nodeKind = payload.nodeKind;
11781
- if (nodeKind !== void 0 && nodeKind !== "approval" && nodeKind !== "condition" && nodeKind !== "connector" && nodeKind !== "javascript" && nodeKind !== "decision" && nodeKind !== "openapi" && nodeKind !== "http-request" && nodeKind !== "llm" && nodeKind !== "agent" && nodeKind !== "value" && nodeKind !== "outputs" && nodeKind !== "webhook-response" && nodeKind !== "workflow" && nodeKind !== "wait") return invalidResponse();
11861
+ if (nodeKind !== void 0 && nodeKind !== "approval" && nodeKind !== "condition" && nodeKind !== "connector" && nodeKind !== "javascript" && nodeKind !== "decision" && nodeKind !== "openapi" && nodeKind !== "http-request" && nodeKind !== "skip-duplicates" && nodeKind !== "llm" && nodeKind !== "agent" && nodeKind !== "value" && nodeKind !== "outputs" && nodeKind !== "webhook-response" && nodeKind !== "workflow" && nodeKind !== "wait") return invalidResponse();
11782
11862
  return {
11783
11863
  ...base,
11784
11864
  kind,
@@ -11905,6 +11985,10 @@ var ControlClient = class {
11905
11985
  }
11906
11986
  async listFlows(options = {}) {
11907
11987
  const parameters = new URLSearchParams();
11988
+ const filter = normalizeFlowQuery(options);
11989
+ if (filter.query) parameters.set("query", filter.query);
11990
+ if (filter.tagIds.length) parameters.set("tagIds", filter.tagIds.join(","));
11991
+ if (filter.untagged) parameters.set("untagged", "true");
11908
11992
  if (options.cursor != null) parameters.set("cursor", options.cursor);
11909
11993
  if (options.limit != null) parameters.set("limit", String(options.limit));
11910
11994
  if (options.includeTotal != null) parameters.set("includeTotal", String(options.includeTotal));
@@ -11994,15 +12078,18 @@ var ControlClient = class {
11994
12078
  file,
11995
12079
  name: options.name,
11996
12080
  teamId: options.teamId,
12081
+ tagIds: options.tagIds,
11997
12082
  version: 1
11998
12083
  })
11999
12084
  }));
12000
12085
  }
12001
- async createFlow(name, idempotencyKey = `flow-${randomId()}`, teamId) {
12086
+ async createFlow(name, idempotencyKey = `flow-${randomId()}`, teamId, tagIds, initialPresentation) {
12002
12087
  return flow(await this.request("/v1/flows", {
12003
12088
  body: JSON.stringify({
12004
12089
  name,
12005
12090
  ...teamId == null ? {} : { teamId },
12091
+ ...tagIds == null ? {} : { tagIds },
12092
+ ...initialPresentation == null ? {} : { presentation: initialPresentation },
12006
12093
  version: 1
12007
12094
  }),
12008
12095
  headers: { "idempotency-key": idempotencyKey },
@@ -12037,15 +12124,68 @@ var ControlClient = class {
12037
12124
  if (source.version != 1 || !Array.isArray(source.listeners)) return invalidResponse();
12038
12125
  return source.listeners.map(errorListener);
12039
12126
  }
12040
- async renameFlow(flowId, name) {
12041
- return flow(await this.request(`/v1/flows/${segment(flowId)}`, {
12127
+ async listTags(signal) {
12128
+ const source = record$1(await this.request("/v1/tags", { signal }));
12129
+ if (source.version != 1 || !Array.isArray(source.tags)) return invalidResponse();
12130
+ return {
12131
+ tags: source.tags.map(decodeTagListItem),
12132
+ version: 1
12133
+ };
12134
+ }
12135
+ async createTag(name) {
12136
+ return decodeTag(await this.request("/v1/tags", {
12137
+ method: "POST",
12042
12138
  body: JSON.stringify({
12043
12139
  name,
12044
12140
  version: 1
12045
- }),
12046
- method: "PATCH"
12141
+ })
12142
+ }));
12143
+ }
12144
+ async renameTag(tagId, name) {
12145
+ return decodeTag(await this.request(`/v1/tags/${segment(tagId)}`, {
12146
+ method: "PATCH",
12147
+ body: JSON.stringify({
12148
+ name,
12149
+ version: 1
12150
+ })
12151
+ }));
12152
+ }
12153
+ async deleteTag(tagId) {
12154
+ if (record$1(await this.request(`/v1/tags/${segment(tagId)}`, { method: "DELETE" })).version != 1) invalidResponse();
12155
+ }
12156
+ async setFlowTags(flowId, tagIds) {
12157
+ return flow(await this.request(`/v1/flows/${segment(flowId)}/tags`, {
12158
+ method: "PUT",
12159
+ body: JSON.stringify({
12160
+ tagIds,
12161
+ version: 1
12162
+ })
12163
+ }));
12164
+ }
12165
+ async updateFlow(flowId, changes) {
12166
+ return flow(await this.request(`/v1/flows/${segment(flowId)}`, {
12167
+ method: "PATCH",
12168
+ body: JSON.stringify({
12169
+ ...changes,
12170
+ version: 1
12171
+ })
12047
12172
  }));
12048
12173
  }
12174
+ async getFlowState(flowId, scope, values = false) {
12175
+ const result = flowStateViewSchema.safeParse(await this.request(`/v1/flows/${segment(flowId)}/state?scope=${scope}&values=${values}`));
12176
+ return result.success && result.data.scope === scope ? result.data : invalidResponse();
12177
+ }
12178
+ async clearFlowState(flowId, scope, key) {
12179
+ const source = record$1(await this.request(`/v1/flows/${segment(flowId)}/state?scope=${scope}${key == null ? "" : `&key=${encodeURIComponent(key)}`}`, { method: "DELETE" }));
12180
+ if (source.version !== 1 || source.cleared !== true) invalidResponse();
12181
+ }
12182
+ async clearFlowDedupe(flowId, scope, space) {
12183
+ const source = record$1(await this.request(`/v1/flows/${segment(flowId)}/dedupe?scope=${scope}&space=${encodeURIComponent(space)}`, { method: "DELETE" }));
12184
+ if (source.version !== 1 || source.cleared !== true) invalidResponse();
12185
+ }
12186
+ async renameFlow(flowId, name) {
12187
+ return this.updateFlow(flowId, { name });
12188
+ }
12049
12189
  async deleteFlow(flowId) {
12050
12190
  return flow(await this.request(`/v1/flows/${segment(flowId)}`, { method: "DELETE" }));
12051
12191
  }
@@ -42,6 +42,9 @@ export declare const controlErrorCode: {
42
42
  readonly triggerKeyInvalid: 'trigger-key.invalid';
43
43
  readonly triggerKeyNotFound: 'trigger-key.not-found';
44
44
  readonly triggerNotFound: 'trigger.not-found';
45
+ readonly tagInvalid: 'tag.invalid';
46
+ readonly tagConflict: 'tag.conflict';
47
+ readonly tagNotFound: 'tag.not-found';
45
48
  readonly variableInvalid: 'variable.invalid';
46
49
  readonly variableLimitReached: 'variable.limit-reached';
47
50
  readonly variableNotFound: 'variable.not-found';
@@ -177,6 +180,15 @@ export declare const controlErrorMetadata: {
177
180
  readonly "trigger.not-found": {
178
181
  readonly status: 404;
179
182
  };
183
+ readonly "tag.invalid": {
184
+ readonly status: 400;
185
+ };
186
+ readonly "tag.conflict": {
187
+ readonly status: 409;
188
+ };
189
+ readonly "tag.not-found": {
190
+ readonly status: 404;
191
+ };
180
192
  readonly "variable.invalid": {
181
193
  readonly status: 400;
182
194
  };
@@ -1,4 +1,5 @@
1
1
  import type { CanvasCommand } from './canvas-commands.js';
2
+ import type { FlowStateView, StateScope } from './flow-state.js';
2
3
  export type { CanvasCommand, CanvasCommandSubscriber } from './canvas-commands.js';
3
4
  import type { LiveDetails } from './liveDetails.js';
4
5
  export { liveEntries } from './liveDetails.js';
@@ -34,6 +35,7 @@ export type { JsonValue, TriggerKeySnapshot, WaitAction } from './flow-change.js
34
35
  export type { RunStatus } from './run-lifecycle.js';
35
36
  export { ApiError, controlErrorCode, controlErrorMetadata, type ControlErrorCode } from './control-api-errors.js';
36
37
  export type { FlowCatalogEvent, FlowChangeEvent } from './flow-notifications.js';
38
+ export { normalizeFlowQuery } from './tags.js';
37
39
  export interface CanvasBroadcast {
38
40
  readonly version: 1;
39
41
  readonly flowId: string;
@@ -59,7 +61,25 @@ export interface FlowResources {
59
61
  }[];
60
62
  };
61
63
  }
64
+ export interface FlowUpdate {
65
+ readonly name?: string;
66
+ readonly tagIds?: readonly string[];
67
+ }
68
+ export interface FlowQuery {
69
+ readonly query?: string;
70
+ readonly tagIds?: readonly string[];
71
+ readonly untagged?: boolean;
72
+ }
73
+ export interface Tag {
74
+ readonly tagId: string;
75
+ readonly name: string;
76
+ readonly version: 1;
77
+ }
78
+ export interface TagListItem extends Tag {
79
+ readonly referenceCount: number;
80
+ }
62
81
  export interface Flow {
82
+ readonly tagIds?: readonly string[];
63
83
  readonly live?: {
64
84
  readonly enabled: boolean;
65
85
  readonly hasStart: boolean;
@@ -81,6 +101,10 @@ export interface PublicationPresentation {
81
101
  readonly version: 1;
82
102
  readonly presentation: Presentation | null;
83
103
  }
104
+ export interface FlowCreationOptions {
105
+ readonly tagIds?: readonly string[];
106
+ readonly presentation?: Readonly<Record<string, JsonValue>>;
107
+ }
84
108
  export interface Presentation {
85
109
  readonly revision: number;
86
110
  readonly updatedAt: string;
@@ -740,7 +764,7 @@ export declare class ControlClient {
740
764
  private readonly channel;
741
765
  constructor(requestControl: ControlRequest, channel?: 'workbench' | 'cli' | 'api');
742
766
  loadOpenApiDocument(url: string, signal?: AbortSignal): Promise<JsonValue>;
743
- listFlows(options?: {
767
+ listFlows(options?: FlowQuery & {
744
768
  readonly cursor?: string;
745
769
  readonly includeTotal?: boolean;
746
770
  readonly limit?: number;
@@ -808,11 +832,24 @@ export declare class ControlClient {
808
832
  readonly name?: string;
809
833
  readonly teamId?: string;
810
834
  readonly idempotencyKey?: string;
835
+ readonly tagIds?: readonly string[];
811
836
  }): Promise<Flow>;
812
- createFlow(name: string, idempotencyKey?: string, teamId?: string): Promise<Flow>;
837
+ createFlow(name: string, idempotencyKey?: string, teamId?: string, tagIds?: readonly string[], initialPresentation?: Readonly<Record<string, JsonValue>>): Promise<Flow>;
813
838
  broadcastCanvas(flowId: string, command: CanvasCommand): Promise<CanvasBroadcast>;
814
839
  getFlow(flowId: string): Promise<Flow>;
815
840
  getErrorListeners(flowId: string, signal?: AbortSignal): Promise<readonly ErrorListener[]>;
841
+ listTags(signal?: AbortSignal): Promise<{
842
+ readonly tags: readonly TagListItem[];
843
+ readonly version: 1;
844
+ }>;
845
+ createTag(name: string): Promise<Tag>;
846
+ renameTag(tagId: string, name: string): Promise<Tag>;
847
+ deleteTag(tagId: string): Promise<void>;
848
+ setFlowTags(flowId: string, tagIds: readonly string[]): Promise<Flow>;
849
+ updateFlow(flowId: string, changes: FlowUpdate): Promise<Flow>;
850
+ getFlowState(flowId: string, scope: StateScope, values?: boolean): Promise<FlowStateView>;
851
+ clearFlowState(flowId: string, scope: StateScope, key?: string): Promise<void>;
852
+ clearFlowDedupe(flowId: string, scope: StateScope, space: string): Promise<void>;
816
853
  renameFlow(flowId: string, name: string): Promise<Flow>;
817
854
  deleteFlow(flowId: string): Promise<Flow>;
818
855
  listTriggerKeys(signal?: AbortSignal, locale?: string): Promise<readonly TriggerKeySummary[]>;