@oomol-lab/open-flow 0.1.0-beta.69 → 0.1.0-beta.70

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 (49) hide show
  1. package/dist/browser/{ContentIcon-CsECY5id.js → ContentIcon-CUQHjQIw.js} +16 -8
  2. package/dist/browser/{FlowCanvas-C5X22xQ7.js → FlowCanvas-CqtUDPGj.js} +11 -26
  3. package/dist/browser/{createResourceDialog-Di5BBrQv.js → createResourceDialog-BAHYW9yu.js} +3 -3
  4. package/dist/browser/{dialog-Bjo-r9B0.js → dialog-DcGOzUP2.js} +162 -12
  5. package/dist/browser/{exportSvg-Cj6Spxx-.js → exportSvg-Dv5Qgrq7.js} +2 -2
  6. package/dist/browser/flow-authoring.js +95 -12
  7. package/dist/browser/flow-change-schema.d.ts +24 -1
  8. package/dist/browser/flow-change.d.ts +33 -4
  9. package/dist/browser/flow-change.js +96 -13
  10. package/dist/browser/{flowChanges-Dp-rcEJ6.js → flowChanges-CYyehKer.js} +2593 -2254
  11. package/dist/browser/{flowWorkspace-CB1QACku.js → flowWorkspace-qYUZPJHR.js} +1114 -392
  12. package/dist/browser/preview.css +225 -221
  13. package/dist/browser/preview.js +3781 -2655
  14. package/dist/browser/{tooltip-CJjYs_2I.js → tooltip-wZJRB9oP.js} +28 -1
  15. package/dist/browser/ui.css +8 -20
  16. package/dist/browser/workbench.css +225 -221
  17. package/dist/browser/workbench.js +31 -10
  18. package/dist/browser/{workbenchSelect-C3hxUcYm.js → workbenchSelect-D8_vP2p5.js} +2 -2
  19. package/dist/command/index.js +45 -45
  20. package/dist/common/authoring.d.ts +3 -3
  21. package/dist/common/authoringExamples.d.ts +3 -2
  22. package/dist/common/authoringSchema.d.ts +37 -374
  23. package/dist/common/control-api-conformance.js +151 -55
  24. package/dist/common/control-api.d.ts +12 -78
  25. package/dist/common/control-api.js +162 -39
  26. package/dist/common/control-requests.d.ts +3 -3
  27. package/dist/common/control-requests.js +221 -35
  28. package/dist/common/decision.js +85 -7
  29. package/dist/common/engine-contract.d.ts +4 -2
  30. package/dist/common/flow-encoding.js +110 -14
  31. package/dist/common/flow-graph.d.ts +3 -0
  32. package/dist/common/flow-semantics.js +273 -14
  33. package/dist/common/integration-trigger.js +85 -7
  34. package/dist/common/liveDetails.d.ts +15 -0
  35. package/dist/common/mcp.d.ts +3 -3
  36. package/dist/common/mcp.js +134 -38
  37. package/dist/common/openapi.js +85 -7
  38. package/dist/common/poll-trigger.js +85 -7
  39. package/dist/common/run-events.d.ts +2 -0
  40. package/dist/common/run-events.js +59 -2
  41. package/dist/common/runtime-contract.js +14 -4
  42. package/dist/common/scheduler.d.ts +6 -2
  43. package/dist/common/scheduler.js +178 -11
  44. package/dist/common/webhook-response.d.ts +43 -0
  45. package/dist/common/webhook-trigger.d.ts +12 -0
  46. package/dist/common/webhook-trigger.js +236 -9
  47. package/dist/common/workflow.js +85 -7
  48. package/package.json +1 -1
  49. package/skills/open-flow/references/flow-authoring.md +15 -10
@@ -22,6 +22,133 @@ function dequal(foo, bar) {
22
22
  return foo !== foo && bar !== bar;
23
23
  }
24
24
  //#endregion
25
+ //#region src/base/common/json.ts
26
+ function hasJsonShape(root) {
27
+ if (root === null || typeof root == "boolean" || typeof root == "string") return true;
28
+ if (typeof root == "number") return Number.isFinite(root);
29
+ if (typeof root != "object") return false;
30
+ const ancestors = /* @__PURE__ */ new Set();
31
+ const pending = [];
32
+ let value = root;
33
+ traversal: while (true) {
34
+ let keys;
35
+ let arrayLength;
36
+ if (Array.isArray(value)) {
37
+ arrayLength = value.length;
38
+ keys = Reflect.ownKeys(value);
39
+ if (keys.length != arrayLength + 1) return false;
40
+ } else {
41
+ const prototype = Reflect.getPrototypeOf(value);
42
+ if (prototype != Object.prototype && prototype != null) return false;
43
+ keys = Reflect.ownKeys(value);
44
+ arrayLength = void 0;
45
+ }
46
+ ancestors.add(value);
47
+ let index = 0;
48
+ while (true) {
49
+ if (index >= keys.length) {
50
+ ancestors.delete(value);
51
+ const parent = pending.pop();
52
+ if (parent === void 0) return true;
53
+ value = parent.value;
54
+ keys = parent.keys;
55
+ arrayLength = parent.arrayLength;
56
+ index = parent.index;
57
+ continue;
58
+ }
59
+ const key = keys[index++];
60
+ if (arrayLength !== void 0) {
61
+ if (key == "length") continue;
62
+ if (typeof key != "string") return false;
63
+ const arrayIndex = Number(key);
64
+ if (!Number.isSafeInteger(arrayIndex) || arrayIndex < 0 || arrayIndex >= arrayLength || String(arrayIndex) != key) return false;
65
+ } else if (typeof key != "string") return false;
66
+ const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
67
+ if (descriptor?.enumerable != true || !Object.hasOwn(descriptor, "value")) return false;
68
+ const child = descriptor.value;
69
+ if (child === null || typeof child == "boolean" || typeof child == "string") continue;
70
+ if (typeof child == "number") {
71
+ if (!Number.isFinite(child)) return false;
72
+ continue;
73
+ }
74
+ if (typeof child != "object" || ancestors.has(child)) return false;
75
+ pending.push({
76
+ value,
77
+ keys,
78
+ arrayLength,
79
+ index
80
+ });
81
+ value = child;
82
+ continue traversal;
83
+ }
84
+ }
85
+ }
86
+ function isJsonObject(value) {
87
+ try {
88
+ return value != null && typeof value == "object" && !Array.isArray(value) && hasJsonShape(value);
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ //#endregion
94
+ //#region src/flow/common/webhookResponse.ts
95
+ var webhookResponseTimeout = {
96
+ defaultMs: 3e4,
97
+ minMs: 1e3,
98
+ maxMs: 6e4
99
+ };
100
+ function webhookResponseAllowsBody(status) {
101
+ return status !== 204 && status !== 205 && status !== 304;
102
+ }
103
+ var webhookHeadersPort = {
104
+ jsonSchema: {
105
+ type: "object",
106
+ additionalProperties: { type: [
107
+ "string",
108
+ "number",
109
+ "boolean"
110
+ ] }
111
+ },
112
+ nullable: true
113
+ };
114
+ /** Header names are case-insensitive; never silently combine duplicate business fields. */
115
+ function webhookHeaderNameIssue(name, names) {
116
+ if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) return "invalid";
117
+ if (names.some((candidate) => candidate.toLowerCase() === name.toLowerCase())) return "duplicate";
118
+ }
119
+ webhookHeadersPort.jsonSchema;
120
+ function validWebhookStatus(value) {
121
+ return typeof value === "number" && Number.isInteger(value) && value >= 200 && value <= 599 && webhookResponseAllowsBody(value);
122
+ }
123
+ /** Portable validation also runs in the isolated engine, which has no HTTP globals. */
124
+ function webhookHeaderValues(source) {
125
+ if (source == null || typeof source !== "object" || Array.isArray(source)) return;
126
+ const headers = {};
127
+ const names = [];
128
+ for (const [name, value] of Object.entries(source)) {
129
+ if (webhookHeaderNameIssue(name, names) != null) return;
130
+ if (typeof value !== "string" && typeof value !== "boolean" && !(typeof value === "number" && Number.isFinite(value))) return;
131
+ const text = String(value);
132
+ if ([...text].some((character) => character.charCodeAt(0) > 255 || /[\0\r\n]/.test(character))) return;
133
+ names.push(name);
134
+ Object.defineProperty(headers, name, {
135
+ value: text,
136
+ enumerable: true,
137
+ configurable: true
138
+ });
139
+ }
140
+ return headers;
141
+ }
142
+ function encodeWebhookBody(value) {
143
+ return typeof value === "string" ? {
144
+ body: value,
145
+ contentType: "text/plain;charset=UTF-8"
146
+ } : {
147
+ body: JSON.stringify(value),
148
+ contentType: "application/json"
149
+ };
150
+ }
151
+ //#endregion
25
152
  //#region ../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/util.js
26
153
  function getEnumValues(entries) {
27
154
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
@@ -1043,7 +1170,7 @@ function timeSource(args) {
1043
1170
  function time(args) {
1044
1171
  return new RegExp(`^${timeSource(args)}$`);
1045
1172
  }
1046
- function datetime(args) {
1173
+ function datetime$1(args) {
1047
1174
  const opts = ["Z"];
1048
1175
  if (args.offset) opts.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);
1049
1176
  const qualified = `${timeSource({
@@ -1694,7 +1821,7 @@ var $ZodKSUID = /*@__PURE__*/ $constructor("$ZodKSUID", (inst, def) => {
1694
1821
  $ZodStringFormat.init(inst, def);
1695
1822
  });
1696
1823
  var $ZodISODateTime = /*@__PURE__*/ $constructor("$ZodISODateTime", (inst, def) => {
1697
- def.pattern ?? (def.pattern = datetime(def));
1824
+ def.pattern ?? (def.pattern = datetime$1(def));
1698
1825
  $ZodStringFormat.init(inst, def);
1699
1826
  });
1700
1827
  var $ZodISODate = /*@__PURE__*/ $constructor("$ZodISODate", (inst, def) => {
@@ -5691,6 +5818,11 @@ function preprocess(fn, schema) {
5691
5818
  });
5692
5819
  }
5693
5820
  //#endregion
5821
+ //#region ../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/iso.js
5822
+ function datetime(params) {
5823
+ return /* @__PURE__ */ _isoDateTime(ZodISODateTime, params);
5824
+ }
5825
+ //#endregion
5694
5826
  //#region src/decision/common/decision.ts
5695
5827
  var decisionLimits = {
5696
5828
  choice: 255,
@@ -5810,6 +5942,32 @@ var triggerScheduleSchema = array(union([object({
5810
5942
  value: number()
5811
5943
  })]));
5812
5944
  //#endregion
5945
+ //#region src/localization/common/timeZone.ts
5946
+ /** Validate a named timezone using the same runtime data used for date conversion. */
5947
+ function isTimeZone(value) {
5948
+ try {
5949
+ Intl.DateTimeFormat("en", { timeZone: value });
5950
+ return true;
5951
+ } catch {
5952
+ return false;
5953
+ }
5954
+ }
5955
+ //#endregion
5956
+ //#region src/flow/common/wait.ts
5957
+ /** Drafts retain incomplete values; semantic validation gates publication and execution. */
5958
+ var waitAutoContinueDraftSchema = discriminatedUnion("kind", [strictObject({
5959
+ kind: literal("after"),
5960
+ durationMs: number().nullable()
5961
+ }), strictObject({
5962
+ kind: literal("at"),
5963
+ at: string(),
5964
+ timezone: string().optional()
5965
+ })]);
5966
+ discriminatedUnion("kind", [waitAutoContinueDraftSchema.options[0].extend({ durationMs: number().int().positive().max(Number.MAX_SAFE_INTEGER) }), waitAutoContinueDraftSchema.options[1].extend({
5967
+ at: datetime({ offset: true }),
5968
+ timezone: string().refine(isTimeZone, "Select a valid IANA timezone.").optional()
5969
+ })]);
5970
+ //#endregion
5813
5971
  //#region src/flow/common/webhookMethod.ts
5814
5972
  var webhookMethods = [
5815
5973
  "GET",
@@ -6048,9 +6206,24 @@ var webhookOptions = object({
6048
6206
  allowedMethods: never().optional(),
6049
6207
  allowedOrigins: strings.optional(),
6050
6208
  noResponseBody: never().optional(),
6209
+ responseBody: discriminatedUnion("kind", [strictObject({
6210
+ kind: literal("workflow-outputs"),
6211
+ output: text.optional(),
6212
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
6213
+ }), strictObject({
6214
+ kind: literal("webhook-response"),
6215
+ nodeId: text.optional(),
6216
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
6217
+ })]).optional(),
6051
6218
  responseData: text.optional(),
6052
6219
  responseHeaders: record$1(text, text).optional(),
6053
- responseStatusCode: number().int().min(200).max(599).optional()
6220
+ responseHeadersSource: strictObject({
6221
+ kind: literal("workflow-outputs"),
6222
+ output: text.optional()
6223
+ }).optional(),
6224
+ responseHeaderOutputs: record$1(text, text).optional(),
6225
+ responseStatusCode: number().int().min(200).max(599).optional(),
6226
+ responseStatusCodeOutput: text.optional()
6054
6227
  });
6055
6228
  var webhook = {
6056
6229
  bodyFields: array(input),
@@ -6105,6 +6278,12 @@ var base = {
6105
6278
  onError: _enum(["stop", "error"]).optional()
6106
6279
  };
6107
6280
  var node = union([
6281
+ strictObject({
6282
+ ...base,
6283
+ kind: literal("webhook-response"),
6284
+ retry: never().optional(),
6285
+ onError: never().optional()
6286
+ }),
6108
6287
  strictObject({
6109
6288
  ...base,
6110
6289
  kind: literal("outputs"),
@@ -6137,7 +6316,8 @@ var node = union([
6137
6316
  strictObject({
6138
6317
  ...base,
6139
6318
  kind: literal("wait"),
6140
- ...wait
6319
+ ...wait,
6320
+ autoContinue: waitAutoContinueDraftSchema.optional()
6141
6321
  }).omit({ timeoutMs: true }),
6142
6322
  object({
6143
6323
  ...trigger,
@@ -6224,7 +6404,8 @@ object({
6224
6404
  literal(6),
6225
6405
  literal(7),
6226
6406
  literal(8),
6227
- literal(9)
6407
+ literal(9),
6408
+ literal(10)
6228
6409
  ]),
6229
6410
  document,
6230
6411
  modules: record$1(text, module)
@@ -6349,8 +6530,14 @@ var shapes = {
6349
6530
  },
6350
6531
  "graph.node.resolution.set": {
6351
6532
  ...at,
6352
- before: object(wait),
6353
- value: object(wait)
6533
+ before: strictObject({
6534
+ ...wait,
6535
+ autoContinue: waitAutoContinueDraftSchema.optional()
6536
+ }),
6537
+ value: strictObject({
6538
+ ...wait,
6539
+ autoContinue: waitAutoContinueDraftSchema.optional()
6540
+ })
6354
6541
  },
6355
6542
  "graph.node.webhook.set": {
6356
6543
  ...at,
@@ -9169,6 +9356,46 @@ createSchemaComparer();
9169
9356
  //#endregion
9170
9357
  //#region src/trigger/common/webhook.ts
9171
9358
  var maximumWebhookBodyBytes = 65536;
9359
+ /** Serialize only declared workflow business outputs, never node logs or execution metadata. */
9360
+ function webhookResponseBody(result, source) {
9361
+ const value = workflowOutputValue(result, source.output);
9362
+ if (value === void 0) return;
9363
+ return encodeWebhookBody(value);
9364
+ }
9365
+ function webhookResponseStatusCode(result, output) {
9366
+ const value = workflowOutputValue(result, output);
9367
+ if (validWebhookStatus(value)) return value;
9368
+ }
9369
+ /** Project business headers before the HTTP layer applies its deployment-owned header policy. */
9370
+ function webhookResponseHeaders(result, options) {
9371
+ const whole = options.responseHeadersSource;
9372
+ const source = whole == null ? options.responseHeaders ?? {} : workflowOutputValue(result, whole.output);
9373
+ if (!isJsonObject(source)) return;
9374
+ const values = /* @__PURE__ */ new Map();
9375
+ for (const [name, value] of Object.entries(source)) {
9376
+ if (webhookHeaderNameIssue(name, [...values.values()].map((entry) => entry.name)) != null) return;
9377
+ values.set(name.toLowerCase(), {
9378
+ name,
9379
+ value
9380
+ });
9381
+ }
9382
+ if (whole == null) {
9383
+ const names = [];
9384
+ for (const [name, output] of Object.entries(options.responseHeaderOutputs ?? {})) {
9385
+ if (webhookHeaderNameIssue(name, names) != null) return;
9386
+ names.push(name);
9387
+ values.set(name.toLowerCase(), {
9388
+ name,
9389
+ value: workflowOutputValue(result, output)
9390
+ });
9391
+ }
9392
+ }
9393
+ return webhookHeaderValues(Object.fromEntries([...values.values()].map(({ name, value }) => [name, value])));
9394
+ }
9395
+ function workflowOutputValue(result, output) {
9396
+ if (!isJsonObject(result) || result.kind != "node-results" || !isJsonObject(result.outputs)) return;
9397
+ return output == null ? result.outputs : Object.hasOwn(result.outputs, output) ? result.outputs[output] : void 0;
9398
+ }
9172
9399
  var endpointPattern = /^\/v1\/webhooks\/(endpoint_[0-9a-f]{32})$/;
9173
9400
  var encoder = new TextEncoder();
9174
9401
  function webhookEndpointId(url) {
@@ -9393,7 +9620,7 @@ var webhookConformanceCases = [
9393
9620
  headers: {
9394
9621
  "access-control-allow-credentials": null,
9395
9622
  "content-security-policy": "default-src 'none'; frame-ancestors 'none'; sandbox",
9396
- "content-type": "text/plain;charset=UTF-8",
9623
+ "content-type": "text/html",
9397
9624
  "location": null,
9398
9625
  "referrer-policy": "no-referrer",
9399
9626
  "set-cookie": null,
@@ -9570,4 +9797,4 @@ var webhookConformanceCases = [
9570
9797
  }
9571
9798
  ];
9572
9799
  //#endregion
9573
- export { maximumWebhookBodyBytes, webhookConformanceCases, webhookEndpointId, webhookOccurrenceId, webhookSupportsBody };
9800
+ export { maximumWebhookBodyBytes, webhookConformanceCases, webhookEndpointId, webhookOccurrenceId, webhookResponseAllowsBody, webhookResponseBody, webhookResponseHeaders, webhookResponseStatusCode, webhookResponseTimeout, webhookSupportsBody };
@@ -1043,7 +1043,7 @@ function timeSource(args) {
1043
1043
  function time$1(args) {
1044
1044
  return new RegExp(`^${timeSource(args)}$`);
1045
1045
  }
1046
- function datetime(args) {
1046
+ function datetime$1(args) {
1047
1047
  const opts = ["Z"];
1048
1048
  if (args.offset) opts.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);
1049
1049
  const qualified = `${timeSource({
@@ -1694,7 +1694,7 @@ var $ZodKSUID = /*@__PURE__*/ $constructor("$ZodKSUID", (inst, def) => {
1694
1694
  $ZodStringFormat.init(inst, def);
1695
1695
  });
1696
1696
  var $ZodISODateTime = /*@__PURE__*/ $constructor("$ZodISODateTime", (inst, def) => {
1697
- def.pattern ?? (def.pattern = datetime(def));
1697
+ def.pattern ?? (def.pattern = datetime$1(def));
1698
1698
  $ZodStringFormat.init(inst, def);
1699
1699
  });
1700
1700
  var $ZodISODate = /*@__PURE__*/ $constructor("$ZodISODate", (inst, def) => {
@@ -5691,6 +5691,11 @@ function preprocess(fn, schema) {
5691
5691
  });
5692
5692
  }
5693
5693
  //#endregion
5694
+ //#region ../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/iso.js
5695
+ function datetime(params) {
5696
+ return /* @__PURE__ */ _isoDateTime(ZodISODateTime, params);
5697
+ }
5698
+ //#endregion
5694
5699
  //#region ../../node_modules/.bun/@cfworker+json-schema@4.1.1/node_modules/@cfworker/json-schema/dist/esm/deep-compare-strict.js
5695
5700
  function deepCompareStrict(a, b) {
5696
5701
  const typeofa = typeof a;
@@ -6690,6 +6695,32 @@ var triggerScheduleSchema = array(union([object({
6690
6695
  value: number()
6691
6696
  })]));
6692
6697
  //#endregion
6698
+ //#region src/localization/common/timeZone.ts
6699
+ /** Validate a named timezone using the same runtime data used for date conversion. */
6700
+ function isTimeZone(value) {
6701
+ try {
6702
+ Intl.DateTimeFormat("en", { timeZone: value });
6703
+ return true;
6704
+ } catch {
6705
+ return false;
6706
+ }
6707
+ }
6708
+ //#endregion
6709
+ //#region src/flow/common/wait.ts
6710
+ /** Drafts retain incomplete values; semantic validation gates publication and execution. */
6711
+ var waitAutoContinueDraftSchema = discriminatedUnion("kind", [strictObject({
6712
+ kind: literal("after"),
6713
+ durationMs: number().nullable()
6714
+ }), strictObject({
6715
+ kind: literal("at"),
6716
+ at: string(),
6717
+ timezone: string().optional()
6718
+ })]);
6719
+ discriminatedUnion("kind", [waitAutoContinueDraftSchema.options[0].extend({ durationMs: number().int().positive().max(Number.MAX_SAFE_INTEGER) }), waitAutoContinueDraftSchema.options[1].extend({
6720
+ at: datetime({ offset: true }),
6721
+ timezone: string().refine(isTimeZone, "Select a valid IANA timezone.").optional()
6722
+ })]);
6723
+ //#endregion
6693
6724
  //#region src/flow/common/webhookMethod.ts
6694
6725
  var webhookMethods = [
6695
6726
  "GET",
@@ -6698,6 +6729,24 @@ var webhookMethods = [
6698
6729
  "PATCH",
6699
6730
  "DELETE"
6700
6731
  ];
6732
+ //#endregion
6733
+ //#region src/flow/common/webhookResponse.ts
6734
+ var webhookResponseTimeout = {
6735
+ defaultMs: 3e4,
6736
+ minMs: 1e3,
6737
+ maxMs: 6e4
6738
+ };
6739
+ ({
6740
+ jsonSchema: {
6741
+ type: "object",
6742
+ additionalProperties: { type: [
6743
+ "string",
6744
+ "number",
6745
+ "boolean"
6746
+ ] }
6747
+ },
6748
+ nullable: true
6749
+ }).jsonSchema;
6701
6750
  var text = string();
6702
6751
  var actionConnection = text.describe("Account selection: omit while unconfigured; use an account ID to select it; use \"\" to explicitly defer configuration. Deferred Actions fail if called; deferred Agent tools are excluded from the callable tool set. Not supported by Triggers.");
6703
6752
  var json = json$1();
@@ -6925,9 +6974,24 @@ var webhookOptions = object({
6925
6974
  allowedMethods: never().optional(),
6926
6975
  allowedOrigins: strings.optional(),
6927
6976
  noResponseBody: never().optional(),
6977
+ responseBody: discriminatedUnion("kind", [strictObject({
6978
+ kind: literal("workflow-outputs"),
6979
+ output: text.optional(),
6980
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
6981
+ }), strictObject({
6982
+ kind: literal("webhook-response"),
6983
+ nodeId: text.optional(),
6984
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
6985
+ })]).optional(),
6928
6986
  responseData: text.optional(),
6929
6987
  responseHeaders: record$1(text, text).optional(),
6930
- responseStatusCode: number().int().min(200).max(599).optional()
6988
+ responseHeadersSource: strictObject({
6989
+ kind: literal("workflow-outputs"),
6990
+ output: text.optional()
6991
+ }).optional(),
6992
+ responseHeaderOutputs: record$1(text, text).optional(),
6993
+ responseStatusCode: number().int().min(200).max(599).optional(),
6994
+ responseStatusCodeOutput: text.optional()
6931
6995
  });
6932
6996
  var webhook = {
6933
6997
  bodyFields: array(input),
@@ -6982,6 +7046,12 @@ var base = {
6982
7046
  onError: _enum(["stop", "error"]).optional()
6983
7047
  };
6984
7048
  var node = union([
7049
+ strictObject({
7050
+ ...base,
7051
+ kind: literal("webhook-response"),
7052
+ retry: never().optional(),
7053
+ onError: never().optional()
7054
+ }),
6985
7055
  strictObject({
6986
7056
  ...base,
6987
7057
  kind: literal("outputs"),
@@ -7014,7 +7084,8 @@ var node = union([
7014
7084
  strictObject({
7015
7085
  ...base,
7016
7086
  kind: literal("wait"),
7017
- ...wait
7087
+ ...wait,
7088
+ autoContinue: waitAutoContinueDraftSchema.optional()
7018
7089
  }).omit({ timeoutMs: true }),
7019
7090
  object({
7020
7091
  ...trigger,
@@ -7101,7 +7172,8 @@ object({
7101
7172
  literal(6),
7102
7173
  literal(7),
7103
7174
  literal(8),
7104
- literal(9)
7175
+ literal(9),
7176
+ literal(10)
7105
7177
  ]),
7106
7178
  document,
7107
7179
  modules: record$1(text, module)
@@ -7226,8 +7298,14 @@ var shapes = {
7226
7298
  },
7227
7299
  "graph.node.resolution.set": {
7228
7300
  ...at,
7229
- before: object(wait),
7230
- value: object(wait)
7301
+ before: strictObject({
7302
+ ...wait,
7303
+ autoContinue: waitAutoContinueDraftSchema.optional()
7304
+ }),
7305
+ value: strictObject({
7306
+ ...wait,
7307
+ autoContinue: waitAutoContinueDraftSchema.optional()
7308
+ })
7231
7309
  },
7232
7310
  "graph.node.webhook.set": {
7233
7311
  ...at,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oomol-lab/open-flow",
3
- "version": "0.1.0-beta.69",
3
+ "version": "0.1.0-beta.70",
4
4
  "description": "TypeScript contracts and Browser runtime for Open Flow.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -291,16 +291,16 @@ selection rules come from the selected node contract.
291
291
 
292
292
  For Connector Tasks, independent Code Actions, Agent tools and notifications, an omitted `connectionId` means unconfigured; `connectionId: ""` explicitly defers account configuration. Deferred selections pass account readiness checks but fail with `connector.connection-required` if invoked. Deferred Agent tools are excluded from the callable tool set. Provider Triggers still require a nonempty account ID. Public edits and portable exports preserve the empty string; clear the field to return to the unconfigured state.
293
293
 
294
- | Capability | Relevant schema and configuration |
295
- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
296
- | Provider read or write | `connector`: discovered `action`, optional `connectionId`, named input bindings. |
297
- | Provider event | `poll` or `integration`: discovered `key`, Connection and any static inputs; polling also has a schedule. |
298
- | Manual, HTTP or scheduled entry | `start`, `webhook`, `cron`: workflow `inputDefs`, HTTP body fields, or schedule. |
299
- | Workflow failure handler | `error`: published upstream Flows' automatic Run failures; not a node-level catch or a handler for manual Run failures. |
300
- | Call another workflow | `workflow`: select an owned published Flow ID; inputs and outputs derive from its saved contract. Use `node.refresh` to update it. |
301
- | Fixed HTTP operation | `openapi`: an OpenAPI source, path and method; resolved authentication choices and ports appear in node details. |
302
- | Reusable constants | `value`: named JSON values and optional output constraints. |
303
- | Durable interaction | `wait`, `approval`: prompt and named inputs; resume through the Run's Wait ID. |
294
+ | Capability | Relevant schema and configuration |
295
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
296
+ | Provider read or write | `connector`: discovered `action`, optional `connectionId`, named input bindings. |
297
+ | Provider event | `poll` or `integration`: discovered `key`, Connection and any static inputs; polling also has a schedule. |
298
+ | Manual, HTTP or scheduled entry | `start`, `webhook`, `cron`: workflow `inputDefs`, HTTP body fields, or schedule. |
299
+ | Workflow failure handler | `error`: published upstream Flows' automatic Run failures; not a node-level catch or a handler for manual Run failures. |
300
+ | Call another workflow | `workflow`: select an owned published Flow ID; inputs and outputs derive from its saved contract. Use `node.refresh` to update it. |
301
+ | Fixed HTTP operation | `openapi`: an OpenAPI source, path and method; resolved authentication choices and ports appear in node details. |
302
+ | Reusable constants | `value`: named JSON values and optional output constraints. |
303
+ | Durable interaction | `wait`, `approval`: prompt and named inputs; resume through the Run's Wait ID. Wait additionally supports optional `config.autoContinue` with `{kind:"after",durationMs:86400000}` or `{kind:"at",at:"2026-10-25T10:00:00+08:00"}`. |
304
304
 
305
305
  Connector and LLM services are configured on the Server. Missing capabilities
306
306
  should be described in terms of the required operation or event, without silently
@@ -340,6 +340,11 @@ Declare parameters on Start: `{"op":"node.add","as":"start","type":"start","name
340
340
  <!-- agentic:var flowCommand --> runs resolve RUN_ID WAIT_ID approve --json
341
341
  ```
342
342
 
343
+ Only Wait supports automatic continuation. Omit `config.autoContinue` for manual waiting or clear
344
+ `["config", "autoContinue"]` to disable it. Relative timing starts at each Wait registration;
345
+ absolute timestamps require an offset. Optional `timezone` stores the editor zone; `at` remains the absolute instant. Server rejects deadlines at or beyond its seven-day expiry
346
+ when registering the Wait. The first manual or automatic decision wins.
347
+
343
348
  A Wait or Approval suspends the existing Run. `run.waits` carries its Wait IDs;
344
349
  resolution uses `continue`, `approve` or `reject` as appropriate to that wait and
345
350
  the authorized decision. A client timeout also leaves the operation running.