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

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 (125) hide show
  1. package/README.md +2 -1
  2. package/dist/browser/{ContentIcon-FCpKiwjp.js → ContentIcon-Cm1hbVzW.js} +2 -2
  3. package/dist/browser/{FlowCanvas-dzRBnlUT.js → FlowCanvas-NzKtla_c.js} +62 -62
  4. package/dist/browser/{createResourceDialog-BeYDdUl-.js → createResourceDialog-BgdedQqu.js} +3 -3
  5. package/dist/browser/{dialog-ZtpsFbl4.js → dialog-aSElFFw2.js} +49 -24
  6. package/dist/browser/{exportSvg-DqXw1yf-.js → exportSvg-Dcz4HTo_.js} +2 -2
  7. package/dist/browser/{flowChanges-b_5UobFj.js → flowChanges-NZyS7HSp.js} +207 -396
  8. package/dist/browser/{flowWorkspace-ItojZbO4.js → flowWorkspace-Bl0SDehy.js} +90 -13
  9. package/dist/browser/preview.css +515 -649
  10. package/dist/browser/preview.js +454 -545
  11. package/dist/browser/theme.css +114 -262
  12. package/dist/browser/{tooltip-wZJRB9oP.js → tooltip-3XMK9jkr.js} +1 -1
  13. package/dist/browser/{typeScriptSession-CSRwWmZm.js → typeScriptSession-C9sBGOKZ.js} +1 -1
  14. package/dist/browser/ui.css +354 -460
  15. package/dist/browser/ui.js +1 -1
  16. package/dist/browser/workbench.css +515 -649
  17. package/dist/browser/workbench.js +7 -7
  18. package/dist/browser/{workbenchSelect-M441Lz0d.js → workbenchSelect-DBGP7Y4Z.js} +2 -2
  19. package/dist/command/index.js +33 -35
  20. package/dist/common/authoring.d.ts +3 -3
  21. package/dist/common/authoringSchema.d.ts +3 -0
  22. package/dist/common/connector-proxy.d.ts +1 -1
  23. package/dist/common/control-api-conformance.js +197 -136
  24. package/dist/common/control-api.d.ts +3 -2
  25. package/dist/common/control-api.js +192 -131
  26. package/dist/common/control-requests.js +126 -24
  27. package/dist/common/cron-trigger.d.ts +2 -1
  28. package/dist/common/decision.d.ts +4 -4
  29. package/dist/common/decision.js +5 -2
  30. package/dist/common/engine-contract.d.ts +5 -1
  31. package/dist/common/event-source-definition.d.ts +1 -1
  32. package/dist/common/event-source-view.d.ts +22 -0
  33. package/dist/common/event-source.d.ts +1 -1
  34. package/dist/common/event-source.js +24 -65
  35. package/dist/common/event-sources.d.ts +0 -21
  36. package/dist/common/flow-authoring.js +40 -18
  37. package/dist/common/flow-change-schema.d.ts +9 -1
  38. package/dist/common/flow-change.d.ts +7 -201
  39. package/dist/common/flow-change.js +46 -22
  40. package/dist/common/flow-encoding.js +40 -20
  41. package/dist/common/flow-input-value.d.ts +1 -1
  42. package/dist/common/flow-model.d.ts +121 -0
  43. package/dist/common/flow-notifications.d.ts +1 -1
  44. package/dist/common/flow-retry.d.ts +2 -4
  45. package/dist/common/flow-semantics.js +83 -86
  46. package/dist/common/flow-workflowReferences.d.ts +8 -0
  47. package/dist/common/flowInspection.d.ts +1 -1
  48. package/dist/common/http-hosts.d.ts +6 -0
  49. package/dist/common/http-request.d.ts +13 -5
  50. package/dist/common/http-request.js +23 -5
  51. package/dist/common/integration-trigger.d.ts +2 -1
  52. package/dist/common/mcp.js +195 -134
  53. package/dist/common/openapi.d.ts +4 -4
  54. package/dist/common/openapi.js +4 -1
  55. package/dist/common/poll-trigger.d.ts +2 -1
  56. package/dist/common/runtime-contract.d.ts +23 -1
  57. package/dist/common/runtime-contract.js +604 -72
  58. package/dist/common/runtime-nodejs-compat.d.ts +44 -0
  59. package/dist/common/runtime-nodejs-compat.js +5870 -0
  60. package/dist/common/scheduler-checkpoint.d.ts +1 -1
  61. package/dist/common/scheduler-node-execution.d.ts +1 -1
  62. package/dist/common/scheduler.d.ts +1 -1
  63. package/dist/common/scheduler.js +25 -4
  64. package/dist/common/trigger-catalog.d.ts +1 -7
  65. package/dist/common/trigger-config-options.d.ts +1 -1
  66. package/dist/common/trigger-config.d.ts +1 -1
  67. package/dist/common/trigger-contract.d.ts +2 -1
  68. package/dist/common/trigger-localization.d.ts +8 -2
  69. package/dist/common/trigger-model.d.ts +101 -0
  70. package/dist/common/webhook-response.d.ts +1 -1
  71. package/dist/common/webhook-trigger.d.ts +3 -1
  72. package/dist/common/workflow.d.ts +3 -12
  73. package/dist/common/workflow.js +25 -23
  74. package/dist/index.d.ts +41 -14
  75. package/package.json +5 -1
  76. package/src/base/common/json.ts +1 -1
  77. package/src/connector/common/proxy.ts +1 -1
  78. package/src/control/common/api.ts +6 -5
  79. package/src/control/common/authoringSchema.ts +9 -2
  80. package/src/control/common/authoringTools.ts +1 -1
  81. package/src/control/common/conformance.ts +1 -1
  82. package/src/control/common/connectorDecoders.ts +1 -1
  83. package/src/control/common/eventSources.ts +2 -29
  84. package/src/control/common/triggerCatalog.ts +1 -8
  85. package/src/decision/common/decision.ts +15 -7
  86. package/src/event-source/common/definition.ts +1 -1
  87. package/src/event-source/common/index.ts +1 -1
  88. package/src/event-source/common/view.ts +20 -0
  89. package/src/execution/common/checkpoint.ts +1 -1
  90. package/src/execution/common/node-execution.ts +1 -1
  91. package/src/execution/common/scheduler.ts +1 -1
  92. package/src/flow/common/change.ts +58 -192
  93. package/src/flow/common/changeSchema.ts +29 -4
  94. package/src/flow/common/connectionUsage.ts +1 -1
  95. package/src/flow/common/inputValue.ts +1 -1
  96. package/src/flow/common/model.ts +130 -0
  97. package/src/flow/common/modules.ts +1 -1
  98. package/src/flow/common/portChanges.ts +1 -1
  99. package/src/flow/common/retry.ts +2 -4
  100. package/src/flow/common/semantics.ts +11 -4
  101. package/src/flow/common/webhookResponse.ts +1 -1
  102. package/src/flow/common/workflowReferences.ts +31 -0
  103. package/src/http/common/authBindings.ts +6 -9
  104. package/src/http/common/hosts.ts +13 -0
  105. package/src/http/common/httpRequest.ts +30 -15
  106. package/src/openapi/common/openapi.ts +9 -5
  107. package/src/{execution → runtime}/common/engineContract.ts +20 -15
  108. package/src/runtime/common/nodejsCompat.ts +275 -0
  109. package/src/runtime/common/nodejsGuest.generated.json +47 -0
  110. package/src/runtime/common/runtime.ts +1138 -0
  111. package/src/trigger/common/config.ts +1 -1
  112. package/src/trigger/common/configOptions.ts +1 -1
  113. package/src/trigger/common/contract.ts +2 -1
  114. package/src/trigger/common/cron.ts +2 -1
  115. package/src/trigger/common/integration.ts +2 -1
  116. package/src/trigger/common/model.ts +87 -0
  117. package/src/trigger/common/poll.ts +2 -1
  118. package/src/trigger/common/webhook.ts +3 -1
  119. package/src/trigger/providers/fieldDescriptions.ts +1 -1
  120. package/src/trigger/providers/localization.ts +9 -2
  121. package/src/trigger/providers/remote.ts +1 -1
  122. package/src/types/index.ts +44 -15
  123. package/src/workflow/common/workflow.ts +3 -44
  124. package/src/execution/common/runtime.ts +0 -563
  125. /package/src/{control → connector}/common/providerIconSprite.ts +0 -0
@@ -1,12 +1,3 @@
1
- //#region src/http/common/authBindings.ts
2
- /** Never allow credentials to enter a Revision as literal node inputs. */
3
- function assertHttpAuthBindings(document) {
4
- for (const node of Object.values(document.graph.nodes)) {
5
- if (node.kind != "task" || !("executor" in node.task) || !["openapi", "http-request"].includes(node.task.executor.kind)) continue;
6
- for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("HTTP authentication accepts deployment variables and upstream outputs only.");
7
- }
8
- }
9
- //#endregion
10
1
  //#region ../../node_modules/.bun/dequal@2.0.3/node_modules/dequal/lite/index.mjs
11
2
  var has = Object.prototype.hasOwnProperty;
12
3
  function dequal(foo, bar) {
@@ -8462,6 +8453,9 @@ function createSchemaComparer() {
8462
8453
  createSchemaComparer();
8463
8454
  //#endregion
8464
8455
  //#region src/decision/common/decision.ts
8456
+ function isDecisionExecutor(executor) {
8457
+ return executor.kind === "decision";
8458
+ }
8465
8459
  var decisionLimits = {
8466
8460
  choice: 255,
8467
8461
  score: 10
@@ -8484,7 +8478,7 @@ function limitDecisionQuestions(questions) {
8484
8478
  }
8485
8479
  /** Loading an oversized task also updates its previously generated output schemas. */
8486
8480
  function limitDecisionTask(task) {
8487
- if (task.executor.kind !== "decision") return task;
8481
+ if (!isDecisionExecutor(task.executor)) return task;
8488
8482
  const original = task.executor.questions;
8489
8483
  const questions = limitDecisionQuestions(original);
8490
8484
  if (questions === original) return task;
@@ -8551,6 +8545,20 @@ function answerSchema(question) {
8551
8545
  };
8552
8546
  }
8553
8547
  //#endregion
8548
+ //#region src/http/common/authBindings.ts
8549
+ /** Never allow credentials to enter a Revision as literal inputs of an OpenAPI or HTTP request node. */
8550
+ function assertHttpAuthBindings(inputs) {
8551
+ for (const [handle, mapping] of Object.entries(inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("HTTP authentication accepts deployment variables and upstream outputs only.");
8552
+ }
8553
+ //#endregion
8554
+ //#region src/http/common/hosts.ts
8555
+ /** Hosts of a Code `http` Capability: lowercase DNS names or IPv4 addresses; `*.example.com` matches subdomains only. */
8556
+ var httpHostPattern = /^(?:\*\.)?(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
8557
+ /** Wildcards must name a registrable suffix, so `*.com` is rejected. */
8558
+ function isHttpHost(value) {
8559
+ return httpHostPattern.test(value) && (!value.startsWith("*.") || value.slice(2).includes("."));
8560
+ }
8561
+ //#endregion
8554
8562
  //#region src/http/common/httpRequest.ts
8555
8563
  var parameterSchema = strictObject({
8556
8564
  mode: _enum(["fields", "object"]).default("fields"),
@@ -8764,7 +8772,14 @@ var workflowCapabilitySchema = strictObject({
8764
8772
  inputs: array(port),
8765
8773
  outputs: array(port).nullable()
8766
8774
  });
8767
- var capability = union([connectorCapabilitySchema, workflowCapabilitySchema]);
8775
+ var capability = union([
8776
+ connectorCapabilitySchema,
8777
+ workflowCapabilitySchema,
8778
+ strictObject({
8779
+ kind: literal("http"),
8780
+ hosts: array(text.refine(isHttpHost, "Use a lowercase host name or IPv4 address, optionally prefixed by \"*.\" for subdomains.")).min(1).max(20).describe("Hosts Code may call with context.fetch. \"*.example.com\" matches subdomains only.")
8781
+ })
8782
+ ]);
8768
8783
  var inline = object({
8769
8784
  ...ports,
8770
8785
  name: text,
@@ -9128,7 +9143,8 @@ var revision = object({
9128
9143
  literal(8),
9129
9144
  literal(9),
9130
9145
  literal(10),
9131
- literal(11)
9146
+ literal(11),
9147
+ literal(12)
9132
9148
  ]),
9133
9149
  document,
9134
9150
  modules: record$1(text, module)
@@ -9383,14 +9399,14 @@ function repairRevisionEnvelope(value) {
9383
9399
  checkJsonDepth(value);
9384
9400
  const envelopeSource = record(value);
9385
9401
  if (envelopeSource.kind != "open-flow-flow-revision" || envelopeSource.version != 1) throw new TypeError("The value is not an Open Flow Revision envelope.");
9386
- if (typeof envelopeSource.modelVersion == "number" && envelopeSource.modelVersion > 11) throw new TypeError("The Flow model is newer than this package.");
9402
+ if (typeof envelopeSource.modelVersion == "number" && envelopeSource.modelVersion > 12) throw new TypeError("The Flow model is newer than this package.");
9387
9403
  let sourceDocument = record(envelopeSource.modelVersion == 1 || envelopeSource.modelVersion == 2 ? upgradeLegacyDocument(envelopeSource.document) : envelopeSource.document);
9388
9404
  if (typeof envelopeSource.modelVersion == "number" && envelopeSource.modelVersion < 6) sourceDocument = upgradeTaskNodes(sourceDocument);
9389
9405
  sourceDocument = record(normalizeDocument(sourceDocument));
9390
9406
  const bindings = record(sourceDocument.bindings);
9391
9407
  const sourceGraph = repairGraph(sourceDocument.graph, bindings);
9392
9408
  return decodeRevisionContent({
9393
- modelVersion: 11,
9409
+ modelVersion: 12,
9394
9410
  document: {
9395
9411
  bindings: repairedEntries(sourceDocument.bindings, binding),
9396
9412
  graph: sourceGraph
@@ -9406,7 +9422,7 @@ function decodeRevisionContent(value) {
9406
9422
  checkJsonDepth(value);
9407
9423
  const content = revision.parse(value);
9408
9424
  checkModelVersion(content);
9409
- assertHttpAuthBindings(content.document);
9425
+ assertDocumentHttpAuthBindings(content.document);
9410
9426
  return content;
9411
9427
  }
9412
9428
  function decodeRevisionEnvelope(value) {
@@ -9418,7 +9434,7 @@ function decodeRevisionEnvelope(value) {
9418
9434
  } : value;
9419
9435
  const content = envelope$1.parse(candidate);
9420
9436
  checkModelVersion(content);
9421
- assertHttpAuthBindings(content.document);
9437
+ assertDocumentHttpAuthBindings(content.document);
9422
9438
  return {
9423
9439
  modelVersion: content.modelVersion,
9424
9440
  document: content.document,
@@ -9592,6 +9608,7 @@ array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, sha
9592
9608
  ...shape
9593
9609
  })])).values()])).min(1);
9594
9610
  function checkModelVersion(content) {
9611
+ 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.");
9595
9612
  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.");
9596
9613
  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.");
9597
9614
  if (content.modelVersion < 10 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "webhook" && (candidateNode.options?.responseBody != null || candidateNode.options?.responseStatusCodeOutput != null || candidateNode.options?.responseHeadersSource != null || candidateNode.options?.responseHeaderOutputs != null))) throw new TypeError("Dynamic Webhook responses require Flow model version 10.");
@@ -9607,6 +9624,9 @@ function checkModelVersion(content) {
9607
9624
  if (content.modelVersion < 6 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "executor" in candidateNode.task)) throw new TypeError("Node-owned managed Tasks require Flow model version 6.");
9608
9625
  if (content.modelVersion < 5 && Object.values(content.document.graph.nodes).some((itemNode) => itemNode.kind == "error")) throw new TypeError("Error workflows require Flow model version 5.");
9609
9626
  }
9627
+ function assertDocumentHttpAuthBindings(content) {
9628
+ for (const graphNode of Object.values(content.graph.nodes)) if (graphNode.kind == "task" && "executor" in graphNode.task && ["openapi", "http-request"].includes(graphNode.task.executor.kind)) assertHttpAuthBindings(graphNode.inputs);
9629
+ }
9610
9630
  //#endregion
9611
9631
  //#region src/flow/common/condition.ts
9612
9632
  function clearConditionBinding(operand) {
@@ -9649,10 +9669,10 @@ function upgradeRevisionContent(content) {
9649
9669
  function upgradeDecodedRevisionContent(content) {
9650
9670
  const graph = content.document.graph;
9651
9671
  const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
9652
- if (!hasManual && content.modelVersion == 11) return content;
9672
+ if (!hasManual && content.modelVersion == 12) return content;
9653
9673
  return {
9654
9674
  ...content,
9655
- modelVersion: 11,
9675
+ modelVersion: 12,
9656
9676
  document: {
9657
9677
  ...content.document,
9658
9678
  graph: hasManual ? {
@@ -9728,7 +9748,7 @@ function clearNodeConnections(graph, connectionId) {
9728
9748
  return [id, node];
9729
9749
  }
9730
9750
  const capabilities = node.task.capabilities?.map((capability) => {
9731
- if (capability.kind == "workflow") return capability;
9751
+ if (capability.kind == "workflow" || capability.kind == "http") return capability;
9732
9752
  if (!("mode" in capability)) {
9733
9753
  if ("action" in capability) {
9734
9754
  const { connectionId: selected, ...rest } = capability;
@@ -10224,7 +10244,7 @@ function revisionRepairKind(bytes) {
10224
10244
  return;
10225
10245
  }
10226
10246
  const source = value;
10227
- return typeof source.modelVersion == "number" && source.modelVersion < 11 ? "upgrade" : "repair";
10247
+ return typeof source.modelVersion == "number" && source.modelVersion < 12 ? "upgrade" : "repair";
10228
10248
  }
10229
10249
  function repairRevision(bytes) {
10230
10250
  return repairRevisionEnvelope(revisionValue(bytes));
@@ -1,4 +1,4 @@
1
- import type { FixedInputValue, InputValues, InputMapping, JsonValue } from './flow-change.js';
1
+ import type { FixedInputValue, InputValues, InputMapping, JsonValue } from './flow-model.js';
2
2
  /** An explicit clear suppresses the default; absent mappings still inherit it. */
3
3
  export declare function inputValue(mapping: InputMapping | undefined, fallback: JsonValue | undefined): JsonValue | undefined;
4
4
  /** Converts explicit user values at authoring boundaries, never persisted legacy data. */
@@ -0,0 +1,121 @@
1
+ import type { JsonValue, Port, PortDefinition } from '../index.js';
2
+ export type { JsonValue, Port, PortDefinition } from '../index.js';
3
+ /** Primitives shared by every node family. Node unions and graph operations belong to change.ts. */
4
+ export interface RetryConfiguration {
5
+ readonly maxRetries: number;
6
+ readonly intervalMs: number;
7
+ }
8
+ export interface InputPortDefinition extends PortDefinition {
9
+ readonly value?: JsonValue;
10
+ }
11
+ export interface InputPort extends InputPortDefinition {
12
+ readonly handle: string;
13
+ }
14
+ export interface Group {
15
+ readonly collapsed?: boolean;
16
+ readonly group: string;
17
+ }
18
+ export declare function portsByHandle<Value extends Port>(ports: readonly (Value | Group)[]): Readonly<Record<string, Value>>;
19
+ export interface NodeSource {
20
+ readonly system?: true;
21
+ readonly field?: string;
22
+ readonly kind: 'node';
23
+ readonly nodeId: string;
24
+ readonly output: string;
25
+ }
26
+ export interface BindingSource {
27
+ readonly bindingId: string;
28
+ readonly kind: 'binding';
29
+ }
30
+ export type FixedInputValue = {
31
+ readonly kind: 'unset';
32
+ } | {
33
+ readonly kind: 'value';
34
+ readonly value: JsonValue;
35
+ };
36
+ export type InputValues = Readonly<Record<string, FixedInputValue>>;
37
+ export type InputMapping = FixedInputValue | {
38
+ readonly kind: 'sources';
39
+ readonly sources: readonly (BindingSource | NodeSource)[];
40
+ };
41
+ export interface GraphNodeBase {
42
+ readonly description?: string;
43
+ readonly icon?: string;
44
+ readonly inputs: Readonly<Record<string, InputMapping>>;
45
+ readonly name?: string;
46
+ readonly maxExecutions?: number;
47
+ readonly timeoutMs?: number;
48
+ readonly retry?: RetryConfiguration;
49
+ readonly onError?: 'stop' | 'error';
50
+ }
51
+ export type Source = BindingSource | NodeSource;
52
+ export interface WorkflowCapability {
53
+ readonly kind: 'workflow';
54
+ readonly name: string;
55
+ readonly flowId: string;
56
+ readonly revisionId: string;
57
+ readonly inputs: readonly Port[];
58
+ readonly outputs: readonly Port[] | null;
59
+ }
60
+ /** Hosts that Code may call through `context.fetch`; requires Flow model 12 and Engine v9. */
61
+ export interface HttpCapability {
62
+ readonly kind: 'http';
63
+ readonly hosts: readonly string[];
64
+ }
65
+ export type TaskCapability = ConnectorCapability | WorkflowCapability | HttpCapability;
66
+ export interface ConnectorAccessCapability {
67
+ readonly actionHints?: readonly string[];
68
+ readonly connectionHints?: readonly {
69
+ readonly action: string;
70
+ readonly connectionId: string;
71
+ readonly alias?: string;
72
+ }[];
73
+ readonly kind: 'connector';
74
+ }
75
+ export interface ConnectorActionCapability {
76
+ readonly action: string;
77
+ readonly connections: readonly {
78
+ readonly connectionId: string;
79
+ readonly alias?: string;
80
+ }[];
81
+ readonly connectionId?: string;
82
+ readonly kind: 'connector';
83
+ }
84
+ export type ConnectorPermissionCapability = {
85
+ readonly kind: 'connector';
86
+ readonly mode: 'shared';
87
+ } | {
88
+ readonly kind: 'connector';
89
+ readonly mode: 'independent';
90
+ readonly actions: readonly {
91
+ readonly action: string;
92
+ readonly connectionId?: string;
93
+ }[];
94
+ };
95
+ export type ConnectorCapability = ConnectorAccessCapability | ConnectorActionCapability | ConnectorPermissionCapability;
96
+ export interface TaskDefinitionBase {
97
+ readonly inputs: readonly (InputPort | Group)[];
98
+ readonly name: string;
99
+ readonly outputs: readonly (Port | Group)[];
100
+ }
101
+ export interface InlineTaskDefinition extends TaskDefinitionBase {
102
+ readonly capabilities?: readonly TaskCapability[];
103
+ readonly moduleId: string;
104
+ }
105
+ /** The executor shape every managed Task shares; each node family narrows it with its own executor. */
106
+ export interface TaskExecutor {
107
+ readonly kind: string;
108
+ }
109
+ export interface ManagedTaskDefinitionOf<Executor extends TaskExecutor> extends TaskDefinitionBase {
110
+ readonly executor: Executor;
111
+ }
112
+ export interface WorkflowExecutor {
113
+ readonly kind: 'workflow';
114
+ readonly flowId: string;
115
+ readonly revisionId: string;
116
+ }
117
+ export interface CodeModule {
118
+ readonly imports: readonly string[];
119
+ readonly name: string;
120
+ readonly source: string;
121
+ }
@@ -1,4 +1,4 @@
1
- import type { CanvasCommand } from '../common/canvas-commands.js';
1
+ import type { CanvasCommand } from './canvas-commands.js';
2
2
  export type FlowCatalogEvent = {
3
3
  readonly kind: 'flows.changed';
4
4
  readonly version: 1;
@@ -1,9 +1,7 @@
1
1
  import type { GraphNode } from './flow-change.js';
2
+ import type { RetryConfiguration } from './flow-model.js';
2
3
  import { z } from 'zod';
3
- export interface RetryConfiguration {
4
- readonly maxRetries: number;
5
- readonly intervalMs: number;
6
- }
4
+ export type { RetryConfiguration } from './flow-model.js';
7
5
  export declare const retryNodeTypes: readonly ['code', 'connector', 'openapi', 'http-request', 'llm', 'decision'];
8
6
  export declare const nodeRetryLimits: {
9
7
  readonly maxRetries: 5;
@@ -3973,6 +3973,9 @@ function hasRetiredRef(value) {
3973
3973
  }
3974
3974
  //#endregion
3975
3975
  //#region src/decision/common/decision.ts
3976
+ function isDecisionExecutor(executor) {
3977
+ return executor.kind === "decision";
3978
+ }
3976
3979
  var decisionLimits = {
3977
3980
  choice: 255,
3978
3981
  score: 10
@@ -3995,7 +3998,7 @@ function limitDecisionQuestions(questions) {
3995
3998
  }
3996
3999
  /** Loading an oversized task also updates its previously generated output schemas. */
3997
4000
  function limitDecisionTask(task) {
3998
- if (task.executor.kind !== "decision") return task;
4001
+ if (!isDecisionExecutor(task.executor)) return task;
3999
4002
  const original = task.executor.questions;
4000
4003
  const questions = limitDecisionQuestions(original);
4001
4004
  if (questions === original) return task;
@@ -4120,7 +4123,7 @@ function decisionTask(questions = [defaultDecisionQuestion()], name = "AI Decisi
4120
4123
  }
4121
4124
  function decisionTaskIssues(task) {
4122
4125
  task = limitDecisionTask(task);
4123
- if (task.executor.kind !== "decision") return [];
4126
+ if (!isDecisionExecutor(task.executor)) return [];
4124
4127
  const expected = decisionTask(task.executor.questions, task.name);
4125
4128
  return [...decisionQuestionIssues(task.executor.questions), ...!dequal(task.inputs, expected.inputs) || !dequal(task.outputs, expected.outputs) ? [{
4126
4129
  field: "ports",
@@ -9809,6 +9812,14 @@ function httpHeaderNameIssue(name, names) {
9809
9812
  if (names.some((candidate) => candidate.toLowerCase() === name.toLowerCase())) return "duplicate";
9810
9813
  }
9811
9814
  //#endregion
9815
+ //#region src/http/common/hosts.ts
9816
+ /** Hosts of a Code `http` Capability: lowercase DNS names or IPv4 addresses; `*.example.com` matches subdomains only. */
9817
+ var httpHostPattern = /^(?:\*\.)?(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
9818
+ /** Wildcards must name a registrable suffix, so `*.com` is rejected. */
9819
+ function isHttpHost(value) {
9820
+ return httpHostPattern.test(value) && (!value.startsWith("*.") || value.slice(2).includes("."));
9821
+ }
9822
+ //#endregion
9812
9823
  //#region src/http/common/httpRequest.ts
9813
9824
  var parameterSchema = strictObject({
9814
9825
  mode: _enum(["fields", "object"]).default("fields"),
@@ -10189,6 +10200,9 @@ function schema$1(doc, schemaValue) {
10189
10200
  ...Object.keys(defs).length ? { $defs: defs } : {}
10190
10201
  };
10191
10202
  }
10203
+ function isOpenApiExecutor(executor) {
10204
+ return executor.kind == "openapi";
10205
+ }
10192
10206
  function parameters(config) {
10193
10207
  const doc = parseOpenApi(config.document);
10194
10208
  const { item, op } = operation(doc, config.path, config.method);
@@ -10310,7 +10324,7 @@ function inlineSchema(value, index) {
10310
10324
  }
10311
10325
  /** The canvas validator and property panel share the same configuration contract. */
10312
10326
  function openApiFieldIssues(task) {
10313
- if (task.executor.kind != "openapi") return [];
10327
+ if (!isOpenApiExecutor(task.executor)) return [];
10314
10328
  const config = task.executor;
10315
10329
  let field = "sourceUrl";
10316
10330
  try {
@@ -10349,66 +10363,6 @@ function openApiIssues(task) {
10349
10363
  return openApiFieldIssues(task).map((issue) => issue.message);
10350
10364
  }
10351
10365
  //#endregion
10352
- //#region src/workflow/common/workflow.ts
10353
- var portSchema = object$1({
10354
- handle: string().min(1),
10355
- jsonSchema: json$1(),
10356
- nullable: boolean(),
10357
- description: string().optional()
10358
- });
10359
- strictObject({
10360
- inputs: array(portSchema).nullable(),
10361
- outputs: array(portSchema).nullable()
10362
- });
10363
- object$1({
10364
- version: literal(1),
10365
- flowId: string().min(1),
10366
- name: string(),
10367
- revisionId: string().min(1),
10368
- publicationId: string().min(1),
10369
- inputs: array(portSchema),
10370
- outputs: array(portSchema).nullable()
10371
- });
10372
- object$1({
10373
- version: literal(1),
10374
- direction: _enum(["incoming", "outgoing"]),
10375
- total: int().nonnegative(),
10376
- nextOffset: int().nonnegative().optional(),
10377
- references: array(object$1({
10378
- flowId: string(),
10379
- name: string().nullable(),
10380
- available: boolean(),
10381
- draft: boolean(),
10382
- live: object$1({
10383
- publicationId: string(),
10384
- enabled: boolean()
10385
- }).nullable()
10386
- }))
10387
- });
10388
- /** Workflow declarations share discovery across authoring, admission and resource indexing. */
10389
- function nodeWorkflowReferences(node) {
10390
- if (node.kind != "task") return [];
10391
- if ("moduleId" in node.task) return (node.task.capabilities ?? []).flatMap((item, index) => item.kind == "workflow" ? [{
10392
- target: item,
10393
- path: `task/capabilities/${index}`,
10394
- tool: item.name
10395
- }] : []);
10396
- if (node.task.executor.kind == "workflow") return [{
10397
- target: {
10398
- ...node.task.executor,
10399
- inputs: node.task.inputs.filter((port) => "handle" in port),
10400
- outputs: node.task.outputs.filter((port) => "handle" in port)
10401
- },
10402
- path: "task/executor"
10403
- }];
10404
- if (node.task.executor.kind == "agent") return node.task.executor.tools.flatMap((item, index) => item.kind == "workflow" ? [{
10405
- target: item,
10406
- path: `task/executor/tools/${index}`,
10407
- tool: item.name
10408
- }] : []);
10409
- return [];
10410
- }
10411
- //#endregion
10412
10366
  //#region src/flow/common/inputValue.ts
10413
10367
  /** An explicit clear suppresses the default; absent mappings still inherit it. */
10414
10368
  function inputValue(mapping, fallback) {
@@ -10664,7 +10618,14 @@ var workflowCapabilitySchema = strictObject({
10664
10618
  inputs: array(port),
10665
10619
  outputs: array(port).nullable()
10666
10620
  });
10667
- var capability = union([connectorCapabilitySchema, workflowCapabilitySchema]);
10621
+ var capability = union([
10622
+ connectorCapabilitySchema,
10623
+ workflowCapabilitySchema,
10624
+ strictObject({
10625
+ kind: literal("http"),
10626
+ hosts: array(text.refine(isHttpHost, "Use a lowercase host name or IPv4 address, optionally prefixed by \"*.\" for subdomains.")).min(1).max(20).describe("Hosts Code may call with context.fetch. \"*.example.com\" matches subdomains only.")
10627
+ })
10628
+ ]);
10668
10629
  var inline = object$1({
10669
10630
  ...ports,
10670
10631
  name: text,
@@ -11044,7 +11005,8 @@ object$1({
11044
11005
  literal(8),
11045
11006
  literal(9),
11046
11007
  literal(10),
11047
- literal(11)
11008
+ literal(11),
11009
+ literal(12)
11048
11010
  ]),
11049
11011
  document,
11050
11012
  modules: record$1(text, module)
@@ -11399,13 +11361,15 @@ function nodeSystemOutputPorts(node) {
11399
11361
  } } : {};
11400
11362
  }
11401
11363
  //#endregion
11364
+ //#region src/flow/common/model.ts
11365
+ function portsByHandle(ports) {
11366
+ return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
11367
+ }
11368
+ //#endregion
11402
11369
  //#region src/flow/common/change.ts
11403
11370
  function validVariableName(value) {
11404
11371
  return value.length <= 256 && /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) && value.slice(0, 3).toUpperCase() != "OO_";
11405
11372
  }
11406
- function portsByHandle(ports) {
11407
- return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
11408
- }
11409
11373
  var workflowToolNamePattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
11410
11374
  function workflowToolNameIssue(name, otherNames = []) {
11411
11375
  if (!workflowToolNamePattern.test(name)) return "invalid";
@@ -11421,6 +11385,8 @@ function decodeTaskCapabilities(value) {
11421
11385
  if (workflowToolNameIssue(item.name, names)) throw new TypeError("Workflow tool names must be unique provider-compatible names.");
11422
11386
  names.add(item.name);
11423
11387
  }
11388
+ const http = parsed.filter((item) => item.kind == "http");
11389
+ if (http.length > 1 || http.some((item) => new Set(item.hosts).size != item.hosts.length)) throw new TypeError("Code declares HTTP hosts once, without duplicates.");
11424
11390
  let connectorIndex = 0;
11425
11391
  return parsed.map((item) => item.kind == "connector" ? connectors[connectorIndex++] : item);
11426
11392
  }
@@ -11549,6 +11515,31 @@ function isTriggerNode(node) {
11549
11515
  ].includes(node.kind);
11550
11516
  }
11551
11517
  //#endregion
11518
+ //#region src/flow/common/workflowReferences.ts
11519
+ /** Workflow declarations share discovery across authoring, admission and resource indexing. */
11520
+ function nodeWorkflowReferences(node) {
11521
+ if (node.kind != "task") return [];
11522
+ if ("moduleId" in node.task) return (node.task.capabilities ?? []).flatMap((item, index) => item.kind == "workflow" ? [{
11523
+ target: item,
11524
+ path: `task/capabilities/${index}`,
11525
+ tool: item.name
11526
+ }] : []);
11527
+ if (node.task.executor.kind == "workflow") return [{
11528
+ target: {
11529
+ ...node.task.executor,
11530
+ inputs: node.task.inputs.filter((port) => "handle" in port),
11531
+ outputs: node.task.outputs.filter((port) => "handle" in port)
11532
+ },
11533
+ path: "task/executor"
11534
+ }];
11535
+ if (node.task.executor.kind == "agent") return node.task.executor.tools.flatMap((item, index) => item.kind == "workflow" ? [{
11536
+ target: item,
11537
+ path: `task/executor/tools/${index}`,
11538
+ tool: item.name
11539
+ }] : []);
11540
+ return [];
11541
+ }
11542
+ //#endregion
11552
11543
  //#region src/flow/common/promptTemplate.ts
11553
11544
  var promptReferencePattern = /\{\{\s*([^{}\s]+)\s*\}\}/g;
11554
11545
  function renderPrompt(template, input) {
@@ -11643,7 +11634,7 @@ function clearNodeConnections(graph, connectionId) {
11643
11634
  return [id, node];
11644
11635
  }
11645
11636
  const capabilities = node.task.capabilities?.map((capability) => {
11646
- if (capability.kind == "workflow") return capability;
11637
+ if (capability.kind == "workflow" || capability.kind == "http") return capability;
11647
11638
  if (!("mode" in capability)) {
11648
11639
  if ("action" in capability) {
11649
11640
  const { connectionId: selected, ...rest } = capability;
@@ -11888,22 +11879,25 @@ function normalizeTriggerOutputs(trigger, outputs) {
11888
11879
  return matchesTriggerOutputs(trigger, normalized) ? normalized : void 0;
11889
11880
  }
11890
11881
  //#endregion
11891
- //#region src/execution/common/engineContract.ts
11892
- var currentEngineContract = "open-flow-engine/v8";
11882
+ //#region src/runtime/common/engineContract.ts
11883
+ /** v9 is a single contract: the Node compatibility builtins, `context.fetch`, and no `context.egress`. */
11884
+ var currentEngineContract = "open-flow-engine/v9";
11885
+ /** The published v8 Node compatibility contract, retained for existing Publications and Runs. */
11893
11886
  var nodejsEngineContract = "open-flow-engine/v8/nodejs-compat-v1";
11894
- var currentContract = {
11887
+ var platformSource = (contract) => `export const engineContract = ${JSON.stringify(contract)}
11888
+ export function identity(value) { return value }
11889
+ `;
11890
+ var v8Contract = {
11895
11891
  workflowTools: true,
11896
11892
  httpRequests: true,
11897
11893
  waitAutoContinue: true,
11898
11894
  webhookResponses: true,
11899
11895
  platformExports: /* @__PURE__ */ new Set(["engineContract", "identity"]),
11900
11896
  platformModule: "open-flow:platform",
11901
- platformSource: `export const engineContract = ${JSON.stringify(currentEngineContract)}
11902
- export function identity(value) { return value }
11903
- `
11897
+ platformSource: platformSource("open-flow-engine/v8")
11904
11898
  };
11905
11899
  var nodejsContract = {
11906
- ...currentContract,
11900
+ ...v8Contract,
11907
11901
  builtinModules: new Set([
11908
11902
  "assert",
11909
11903
  "assert/strict",
@@ -11930,28 +11924,30 @@ var nodejsContract = {
11930
11924
  "util",
11931
11925
  "zlib"
11932
11926
  ].flatMap((name) => [name, `node:${name}`])),
11933
- platformSource: `export const engineContract = ${JSON.stringify(nodejsEngineContract)}
11934
- export function identity(value) { return value }
11935
- `
11927
+ platformSource: platformSource(nodejsEngineContract)
11928
+ };
11929
+ var currentContract = {
11930
+ ...nodejsContract,
11931
+ codeFetch: true,
11932
+ platformSource: platformSource(currentEngineContract)
11936
11933
  };
11937
11934
  function findEngineContract(contract) {
11938
- if (contract == "open-flow-engine/v8") return currentContract;
11935
+ if (contract == "open-flow-engine/v9") return currentContract;
11936
+ if (contract == "open-flow-engine/v8") return v8Contract;
11939
11937
  if (contract == "open-flow-engine/v8/nodejs-compat-v1") return nodejsContract;
11940
11938
  if (contract == "open-flow-engine/v7" || contract == "open-flow-engine/v7/nodejs-compat-v1") return {
11941
- ...contract.endsWith("/nodejs-compat-v1") ? nodejsContract : currentContract,
11939
+ ...contract.endsWith("/nodejs-compat-v1") ? nodejsContract : v8Contract,
11942
11940
  workflowTools: false,
11943
11941
  httpRequests: false,
11944
- platformSource: `export const engineContract = ${JSON.stringify(contract)}\nexport function identity(value) { return value }\n`
11942
+ platformSource: platformSource(contract)
11945
11943
  };
11946
11944
  if (contract == "open-flow-engine/v6" || contract == "open-flow-engine/v6/nodejs-compat-v1") return {
11947
- ...contract == "open-flow-engine/v6" ? currentContract : nodejsContract,
11945
+ ...contract == "open-flow-engine/v6" ? v8Contract : nodejsContract,
11948
11946
  workflowTools: false,
11949
11947
  httpRequests: false,
11950
11948
  waitAutoContinue: false,
11951
11949
  webhookResponses: false,
11952
- platformSource: `export const engineContract = ${JSON.stringify(contract)}
11953
- export function identity(value) { return value }
11954
- `
11950
+ platformSource: platformSource(contract)
11955
11951
  };
11956
11952
  }
11957
11953
  //#endregion
@@ -25073,6 +25069,7 @@ async function prepareFlow(revision, engineContract, triggerId) {
25073
25069
  const engine = findEngineContract(engineContract);
25074
25070
  if (engine == null) return { kind: "engine-unsupported" };
25075
25071
  if (!engine.httpRequests && Object.values(revision.document.graph.nodes).some((node) => node.kind == "task" && "executor" in node.task && node.task.executor.kind == "http-request")) return { kind: "engine-unsupported" };
25072
+ if (!engine.codeFetch && Object.values(revision.document.graph.nodes).some((node) => node.kind == "task" && "moduleId" in node.task && node.task.capabilities?.some((item) => item.kind == "http"))) return { kind: "engine-unsupported" };
25076
25073
  if (!engine.workflowTools && Object.values(revision.document.graph.nodes).some((node) => nodeWorkflowReferences(node).some((ref) => ref.tool != null))) return { kind: "engine-unsupported" };
25077
25074
  if (triggerId != null) {
25078
25075
  const trigger = revision.document.graph.nodes[triggerId];
@@ -0,0 +1,8 @@
1
+ import type { GraphNode } from './flow-change.js';
2
+ import type { WorkflowCapability } from './flow-model.js';
3
+ /** Workflow declarations share discovery across authoring, admission and resource indexing. */
4
+ export declare function nodeWorkflowReferences(node: GraphNode): readonly {
5
+ readonly target: Omit<WorkflowCapability, 'kind' | 'name'>;
6
+ readonly path: string;
7
+ readonly tool?: string;
8
+ }[];
@@ -43,7 +43,7 @@ export declare function flowInspection(inspected: Awaited<ReturnType<typeof insp
43
43
  nodes: {
44
44
  [k: string]: Record<string, unknown>;
45
45
  };
46
- edges: readonly import('./flow-change.js').GraphEdge[];
46
+ edges: readonly import("./flow-change.js").GraphEdge[];
47
47
  };
48
48
  bindings: Readonly<Record<string, {
49
49
  readonly kind: 'variable';
@@ -0,0 +1,6 @@
1
+ /** Hosts of a Code `http` Capability: lowercase DNS names or IPv4 addresses; `*.example.com` matches subdomains only. */
2
+ export declare const httpHostPattern: RegExp;
3
+ export declare const maxHttpHosts = 20;
4
+ /** Wildcards must name a registrable suffix, so `*.com` is rejected. */
5
+ export declare function isHttpHost(value: string): boolean;
6
+ export declare function httpHostAllowed(hosts: readonly string[], hostname: string): boolean;