@oomol-lab/open-flow 0.1.0-beta.73 → 0.1.0-beta.74
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.
- package/LICENSE +36 -0
- package/NOTICE +7 -0
- package/README.md +40 -0
- package/dist/browser/{createResourceDialog-BWJkjiOO.js → createResourceDialog-DI9pL-Yr.js} +2 -2
- package/dist/browser/{dialog-CUy_fwx9.js → dialog-BYJGvItc.js} +54 -19
- package/dist/browser/{flowChanges-CgSnSqqP.js → flowChanges-RL-H4CjD.js} +306 -48
- package/dist/browser/{flowWorkspace-Bf7H-r0t.js → flowWorkspace-BkDsETj0.js} +20745 -20186
- package/dist/browser/preview.css +73 -3
- package/dist/browser/preview.js +21410 -20607
- package/dist/browser/{typeScriptSession-B0hC-C8y.js → typeScriptSession-CSRwWmZm.js} +1 -1
- package/dist/browser/ui.css +72 -2
- package/dist/browser/workbench.css +73 -3
- package/dist/browser/workbench.js +14 -76
- package/dist/browser/{workbenchSelect-C3e4J93X.js → workbenchSelect-BcWPWGzw.js} +1 -1
- package/dist/command/index.js +34 -34
- package/dist/common/authoring.d.ts +1 -1
- package/dist/common/authoringFields.d.ts +1 -1
- package/dist/common/authoringSchema.d.ts +28 -4
- package/dist/common/connector-proxy.d.ts +1 -1
- package/dist/common/control-api-conformance.d.ts +1 -1
- package/dist/common/control-api-conformance.js +61 -24
- package/dist/common/control-api.d.ts +4 -3
- package/dist/common/control-api.js +59 -22
- package/dist/common/control-requests.d.ts +2 -1
- package/dist/common/control-requests.js +204 -42
- package/dist/common/cron-trigger.d.ts +1 -1
- package/dist/common/decision.d.ts +1 -1
- package/dist/common/draftOperations.d.ts +1 -1
- package/dist/common/engine-contract.d.ts +3 -2
- package/dist/common/event-source-definition.d.ts +1 -1
- package/dist/common/flow-agent.d.ts +1 -1
- package/dist/{browser → common}/flow-authoring-node.d.ts +3 -3
- package/dist/{browser → common}/flow-authoring.js +75 -23
- package/dist/{browser → common}/flow-change-schema.d.ts +177 -6
- package/dist/{browser → common}/flow-change.d.ts +35 -15
- package/dist/{browser → common}/flow-change.js +77 -25
- package/dist/common/flow-connectionUsage.d.ts +1 -1
- package/dist/common/flow-encoding.d.ts +1 -1
- package/dist/common/flow-encoding.js +34 -16
- package/dist/common/flow-errorHandling.d.ts +1 -1
- package/dist/common/flow-graph.d.ts +1 -1
- package/dist/common/flow-modules.d.ts +1 -1
- package/dist/common/flow-promptTemplate.d.ts +1 -1
- package/dist/common/flow-retry.d.ts +1 -1
- package/dist/common/flow-semantics.d.ts +1 -1
- package/dist/common/flow-semantics.js +151 -32
- package/dist/common/flow-workflowFile.d.ts +1 -1
- package/dist/common/flowInspection.d.ts +3 -3
- package/dist/common/integration-trigger.d.ts +1 -1
- package/dist/common/licenses.md +118 -1
- package/dist/common/liveDetails.d.ts +1 -1
- package/dist/common/mcp.d.ts +2 -1
- package/dist/common/mcp.js +59 -22
- package/dist/common/openapi.d.ts +1 -1
- package/dist/common/poll-trigger.d.ts +1 -1
- package/dist/common/run-results.d.ts +8 -1
- package/dist/common/runtime-contract.d.ts +8 -2
- package/dist/common/runtime-contract.js +22 -5
- package/dist/common/scheduler-checkpoint.d.ts +1 -1
- package/dist/common/scheduler-dependencies.d.ts +1 -1
- package/dist/common/scheduler-node-execution.d.ts +1 -1
- package/dist/common/scheduler.d.ts +2 -2
- package/dist/common/scheduler.js +31 -12
- package/dist/common/trigger-catalog.d.ts +1 -1
- package/dist/common/trigger-config-options.d.ts +1 -1
- package/dist/common/trigger-config.d.ts +1 -1
- package/dist/common/trigger-contract.d.ts +2 -2
- package/dist/common/trigger-localization.d.ts +1 -1
- package/dist/common/webhook-response.d.ts +1 -1
- package/dist/common/webhook-trigger.d.ts +1 -1
- package/dist/common/workflow.d.ts +17 -1
- package/dist/common/workflow.js +68 -22
- package/dist/index.d.ts +6 -3
- package/package.json +7 -6
- package/src/base/common/json.ts +90 -0
- package/src/canvas/common/commands.ts +15 -0
- package/src/connector/common/actionSchema.ts +168 -0
- package/src/connector/common/proxy.ts +44 -0
- package/src/control/common/api.ts +1505 -0
- package/src/control/common/authoring.ts +912 -0
- package/src/control/common/authoringCondition.ts +110 -0
- package/src/control/common/authoringDiagnosticFields.ts +136 -0
- package/src/control/common/authoringExamples.ts +192 -0
- package/src/control/common/authoringFields.ts +53 -0
- package/src/control/common/authoringLlm.ts +70 -0
- package/src/control/common/authoringOpenApi.ts +129 -0
- package/src/control/common/authoringSchema.ts +404 -0
- package/src/control/common/authoringTools.ts +123 -0
- package/src/control/common/authoringTriggers.ts +26 -0
- package/src/control/common/checkDecoders.ts +65 -0
- package/src/control/common/conformance.ts +1989 -0
- package/src/control/common/connectorDecoders.ts +370 -0
- package/src/control/common/connectorQueries.ts +61 -0
- package/src/control/common/decoding.ts +60 -0
- package/src/control/common/draftOperations.ts +61 -0
- package/src/control/common/errors.ts +114 -0
- package/src/control/common/eventSourceSchemas.ts +13 -0
- package/src/control/common/eventSources.ts +186 -0
- package/src/control/common/flowDecoders.ts +153 -0
- package/src/control/common/flowInspection.ts +181 -0
- package/src/control/common/flowNotifications.ts +37 -0
- package/src/control/common/liveDetails.ts +124 -0
- package/src/control/common/mcp.ts +241 -0
- package/src/control/common/mcpConformance.ts +142 -0
- package/src/control/common/providerAccess.ts +28 -0
- package/src/control/common/providerIconSprite.ts +42 -0
- package/src/control/common/publicationDecoders.ts +98 -0
- package/src/control/common/random.ts +16 -0
- package/src/control/common/requests.ts +112 -0
- package/src/control/common/resultQuery.ts +8 -0
- package/src/control/common/results.ts +176 -0
- package/src/control/common/revisionDecoders.ts +52 -0
- package/src/control/common/runDecoders.ts +240 -0
- package/src/control/common/triggerCatalog.ts +89 -0
- package/src/control/common/triggerDecoders.ts +175 -0
- package/src/decision/common/decision.ts +168 -0
- package/src/event-source/common/catalog.generated.json +65 -0
- package/src/event-source/common/definition.ts +66 -0
- package/src/event-source/common/index.ts +99 -0
- package/src/execution/common/checkpoint.ts +311 -0
- package/src/execution/common/dependencies.ts +440 -0
- package/src/execution/common/engineContract.ts +80 -0
- package/src/execution/common/events.ts +328 -0
- package/src/execution/common/node-execution.ts +467 -0
- package/src/execution/common/runLifecycle.ts +250 -0
- package/src/execution/common/runtime.ts +563 -0
- package/src/execution/common/scheduler.ts +696 -0
- package/src/execution/common/wait.ts +36 -0
- package/src/flow/common/agent.ts +305 -0
- package/src/flow/common/authoring.ts +30 -0
- package/src/flow/common/change.ts +1036 -0
- package/src/flow/common/changeSchema.ts +783 -0
- package/src/flow/common/codePermissions.ts +2 -0
- package/src/flow/common/condition.ts +265 -0
- package/src/flow/common/connectionUsage.ts +131 -0
- package/src/flow/common/edgeChanges.ts +35 -0
- package/src/flow/common/encoding.ts +437 -0
- package/src/flow/common/errorHandling.ts +34 -0
- package/src/flow/common/graph.ts +892 -0
- package/src/flow/common/inputValue.ts +16 -0
- package/src/flow/common/json.ts +8 -0
- package/src/flow/common/moduleChanges.ts +31 -0
- package/src/flow/common/modules.ts +292 -0
- package/src/flow/common/nodeChanges.ts +762 -0
- package/src/flow/common/portChanges.ts +36 -0
- package/src/flow/common/promptTemplate.ts +15 -0
- package/src/flow/common/retry.ts +20 -0
- package/src/flow/common/schema.ts +162 -0
- package/src/flow/common/schemaCompare.ts +176 -0
- package/src/flow/common/schemaComparer.ts +178 -0
- package/src/flow/common/schemaKeywords.ts +53 -0
- package/src/flow/common/semantics.ts +474 -0
- package/src/flow/common/sourceField.ts +35 -0
- package/src/flow/common/triggerScheduleSchema.ts +8 -0
- package/src/flow/common/wait.ts +30 -0
- package/src/flow/common/webhookMethod.ts +7 -0
- package/src/flow/common/webhookResponse.ts +75 -0
- package/src/flow/common/workflowFile.ts +97 -0
- package/src/json-schema-subset/checker/array.ts +142 -0
- package/src/json-schema-subset/checker/cache.ts +57 -0
- package/src/json-schema-subset/checker/checker.ts +230 -0
- package/src/json-schema-subset/checker/enumAndConst.ts +113 -0
- package/src/json-schema-subset/checker/equals.ts +93 -0
- package/src/json-schema-subset/checker/numeric/checker.ts +50 -0
- package/src/json-schema-subset/checker/numeric/float.ts +121 -0
- package/src/json-schema-subset/checker/numeric/index.ts +1 -0
- package/src/json-schema-subset/checker/numeric/integer.ts +119 -0
- package/src/json-schema-subset/checker/numeric/integerNormalizer.ts +72 -0
- package/src/json-schema-subset/checker/object.ts +354 -0
- package/src/json-schema-subset/checker/range.ts +91 -0
- package/src/json-schema-subset/checker/string.ts +60 -0
- package/src/json-schema-subset/checker/tools/index.ts +3 -0
- package/src/json-schema-subset/checker/tools/mark.ts +82 -0
- package/src/json-schema-subset/checker/tools/quantum.ts +106 -0
- package/src/json-schema-subset/checker/tools/range.ts +210 -0
- package/src/json-schema-subset/checker/validator.ts +23 -0
- package/src/json-schema-subset/compiler/array.ts +163 -0
- package/src/json-schema-subset/compiler/combination.ts +109 -0
- package/src/json-schema-subset/compiler/common.ts +99 -0
- package/src/json-schema-subset/compiler/compiler.ts +188 -0
- package/src/json-schema-subset/compiler/enumAndConst.ts +75 -0
- package/src/json-schema-subset/compiler/index.ts +11 -0
- package/src/json-schema-subset/compiler/object.ts +411 -0
- package/src/json-schema-subset/compiler/primitive.ts +144 -0
- package/src/json-schema-subset/compiler/utils.ts +24 -0
- package/src/json-schema-subset/compiler/wrapper.ts +192 -0
- package/src/json-schema-subset/error.ts +55 -0
- package/src/json-schema-subset/expression/calculator.ts +442 -0
- package/src/json-schema-subset/expression/combination.ts +49 -0
- package/src/json-schema-subset/expression/expression.ts +191 -0
- package/src/json-schema-subset/expression/index.ts +25 -0
- package/src/json-schema-subset/expression/result.ts +88 -0
- package/src/json-schema-subset/expression/types.ts +36 -0
- package/src/json-schema-subset/extends/extendsContext.ts +89 -0
- package/src/json-schema-subset/extends/index.ts +2 -0
- package/src/json-schema-subset/extends/types.ts +12 -0
- package/src/json-schema-subset/global.ts +60 -0
- package/src/json-schema-subset/index.ts +8 -0
- package/src/json-schema-subset/preprocessing.ts +74 -0
- package/src/json-schema-subset/types.ts +8 -0
- package/src/json-schema-subset/utils.ts +95 -0
- package/src/localization/common/languages.ts +118 -0
- package/src/localization/common/timeZone.ts +25 -0
- package/src/openapi/common/authBindings.ts +12 -0
- package/src/openapi/common/openapi.ts +459 -0
- package/src/trigger/common/config.ts +56 -0
- package/src/trigger/common/configOptions.ts +15 -0
- package/src/trigger/common/configSchema.ts +8 -0
- package/src/trigger/common/contract.ts +132 -0
- package/src/trigger/common/cron.ts +151 -0
- package/src/trigger/common/integration.ts +498 -0
- package/src/trigger/common/poll.ts +187 -0
- package/src/trigger/common/webhook.ts +412 -0
- package/src/trigger/providers/airtable/locales/fr.json +18 -0
- package/src/trigger/providers/airtable/locales/ja.json +18 -0
- package/src/trigger/providers/airtable/locales/ko.json +18 -0
- package/src/trigger/providers/airtable/locales/ru.json +18 -0
- package/src/trigger/providers/airtable/locales/zh-CN.json +18 -0
- package/src/trigger/providers/airtable/locales/zh-TW.json +18 -0
- package/src/trigger/providers/asana/locales/fr.json +15 -0
- package/src/trigger/providers/asana/locales/ja.json +15 -0
- package/src/trigger/providers/asana/locales/ko.json +15 -0
- package/src/trigger/providers/asana/locales/ru.json +15 -0
- package/src/trigger/providers/asana/locales/zh-CN.json +15 -0
- package/src/trigger/providers/asana/locales/zh-TW.json +15 -0
- package/src/trigger/providers/calendly/locales/fr.json +16 -0
- package/src/trigger/providers/calendly/locales/ja.json +16 -0
- package/src/trigger/providers/calendly/locales/ko.json +16 -0
- package/src/trigger/providers/calendly/locales/ru.json +16 -0
- package/src/trigger/providers/calendly/locales/zh-CN.json +16 -0
- package/src/trigger/providers/calendly/locales/zh-TW.json +16 -0
- package/src/trigger/providers/catalog.generated.json +4996 -0
- package/src/trigger/providers/clickup/locales/fr.json +16 -0
- package/src/trigger/providers/clickup/locales/ja.json +16 -0
- package/src/trigger/providers/clickup/locales/ko.json +16 -0
- package/src/trigger/providers/clickup/locales/ru.json +16 -0
- package/src/trigger/providers/clickup/locales/zh-CN.json +16 -0
- package/src/trigger/providers/clickup/locales/zh-TW.json +16 -0
- package/src/trigger/providers/definitions.ts +19 -0
- package/src/trigger/providers/feishu/locales/fr.json +20 -0
- package/src/trigger/providers/feishu/locales/ja.json +20 -0
- package/src/trigger/providers/feishu/locales/ko.json +20 -0
- package/src/trigger/providers/feishu/locales/ru.json +20 -0
- package/src/trigger/providers/feishu/locales/zh-CN.json +20 -0
- package/src/trigger/providers/feishu/locales/zh-TW.json +20 -0
- package/src/trigger/providers/fieldDescriptions.ts +392 -0
- package/src/trigger/providers/fieldLabels.ts +256 -0
- package/src/trigger/providers/fireflies/locales/fr.json +17 -0
- package/src/trigger/providers/fireflies/locales/ja.json +17 -0
- package/src/trigger/providers/fireflies/locales/ko.json +17 -0
- package/src/trigger/providers/fireflies/locales/ru.json +17 -0
- package/src/trigger/providers/fireflies/locales/zh-CN.json +17 -0
- package/src/trigger/providers/fireflies/locales/zh-TW.json +17 -0
- package/src/trigger/providers/github/locales/fr.json +30 -0
- package/src/trigger/providers/github/locales/ja.json +30 -0
- package/src/trigger/providers/github/locales/ko.json +30 -0
- package/src/trigger/providers/github/locales/ru.json +30 -0
- package/src/trigger/providers/github/locales/zh-CN.json +30 -0
- package/src/trigger/providers/github/locales/zh-TW.json +30 -0
- package/src/trigger/providers/gitlab/locales/fr.json +18 -0
- package/src/trigger/providers/gitlab/locales/ja.json +18 -0
- package/src/trigger/providers/gitlab/locales/ko.json +18 -0
- package/src/trigger/providers/gitlab/locales/ru.json +18 -0
- package/src/trigger/providers/gitlab/locales/zh-CN.json +18 -0
- package/src/trigger/providers/gitlab/locales/zh-TW.json +18 -0
- package/src/trigger/providers/gmail/locales/fr.json +18 -0
- package/src/trigger/providers/gmail/locales/ja.json +18 -0
- package/src/trigger/providers/gmail/locales/ko.json +18 -0
- package/src/trigger/providers/gmail/locales/ru.json +18 -0
- package/src/trigger/providers/gmail/locales/zh-CN.json +18 -0
- package/src/trigger/providers/gmail/locales/zh-TW.json +18 -0
- package/src/trigger/providers/google-calendar/locales/fr.json +15 -0
- package/src/trigger/providers/google-calendar/locales/ja.json +15 -0
- package/src/trigger/providers/google-calendar/locales/ko.json +15 -0
- package/src/trigger/providers/google-calendar/locales/ru.json +15 -0
- package/src/trigger/providers/google-calendar/locales/zh-CN.json +15 -0
- package/src/trigger/providers/google-calendar/locales/zh-TW.json +15 -0
- package/src/trigger/providers/google-drive/locales/fr.json +48 -0
- package/src/trigger/providers/google-drive/locales/ja.json +48 -0
- package/src/trigger/providers/google-drive/locales/ko.json +48 -0
- package/src/trigger/providers/google-drive/locales/ru.json +48 -0
- package/src/trigger/providers/google-drive/locales/zh-CN.json +48 -0
- package/src/trigger/providers/google-drive/locales/zh-TW.json +48 -0
- package/src/trigger/providers/google-sheets/locales/fr.json +19 -0
- package/src/trigger/providers/google-sheets/locales/ja.json +19 -0
- package/src/trigger/providers/google-sheets/locales/ko.json +19 -0
- package/src/trigger/providers/google-sheets/locales/ru.json +19 -0
- package/src/trigger/providers/google-sheets/locales/zh-CN.json +19 -0
- package/src/trigger/providers/google-sheets/locales/zh-TW.json +19 -0
- package/src/trigger/providers/intercom/locales/fr.json +17 -0
- package/src/trigger/providers/intercom/locales/ja.json +17 -0
- package/src/trigger/providers/intercom/locales/ko.json +17 -0
- package/src/trigger/providers/intercom/locales/ru.json +17 -0
- package/src/trigger/providers/intercom/locales/zh-CN.json +17 -0
- package/src/trigger/providers/intercom/locales/zh-TW.json +17 -0
- package/src/trigger/providers/jira/locales/fr.json +17 -0
- package/src/trigger/providers/jira/locales/ja.json +17 -0
- package/src/trigger/providers/jira/locales/ko.json +17 -0
- package/src/trigger/providers/jira/locales/ru.json +17 -0
- package/src/trigger/providers/jira/locales/zh-CN.json +17 -0
- package/src/trigger/providers/jira/locales/zh-TW.json +17 -0
- package/src/trigger/providers/linear/locales/fr.json +13 -0
- package/src/trigger/providers/linear/locales/ja.json +13 -0
- package/src/trigger/providers/linear/locales/ko.json +13 -0
- package/src/trigger/providers/linear/locales/ru.json +13 -0
- package/src/trigger/providers/linear/locales/zh-CN.json +13 -0
- package/src/trigger/providers/linear/locales/zh-TW.json +13 -0
- package/src/trigger/providers/locales/fr.ts +71 -0
- package/src/trigger/providers/locales/ja.ts +71 -0
- package/src/trigger/providers/locales/ko.ts +71 -0
- package/src/trigger/providers/locales/ru.ts +71 -0
- package/src/trigger/providers/locales/zh-CN.ts +71 -0
- package/src/trigger/providers/locales/zh-TW.ts +71 -0
- package/src/trigger/providers/localization.ts +59 -0
- package/src/trigger/providers/notion/locales/fr.json +16 -0
- package/src/trigger/providers/notion/locales/ja.json +16 -0
- package/src/trigger/providers/notion/locales/ko.json +16 -0
- package/src/trigger/providers/notion/locales/ru.json +16 -0
- package/src/trigger/providers/notion/locales/zh-CN.json +16 -0
- package/src/trigger/providers/notion/locales/zh-TW.json +16 -0
- package/src/trigger/providers/one-drive/locales/fr.json +16 -0
- package/src/trigger/providers/one-drive/locales/ja.json +16 -0
- package/src/trigger/providers/one-drive/locales/ko.json +16 -0
- package/src/trigger/providers/one-drive/locales/ru.json +16 -0
- package/src/trigger/providers/one-drive/locales/zh-CN.json +16 -0
- package/src/trigger/providers/one-drive/locales/zh-TW.json +16 -0
- package/src/trigger/providers/outlook/locales/fr.json +18 -0
- package/src/trigger/providers/outlook/locales/ja.json +18 -0
- package/src/trigger/providers/outlook/locales/ko.json +18 -0
- package/src/trigger/providers/outlook/locales/ru.json +18 -0
- package/src/trigger/providers/outlook/locales/zh-CN.json +18 -0
- package/src/trigger/providers/outlook/locales/zh-TW.json +18 -0
- package/src/trigger/providers/pandadoc/locales/fr.json +12 -0
- package/src/trigger/providers/pandadoc/locales/ja.json +12 -0
- package/src/trigger/providers/pandadoc/locales/ko.json +12 -0
- package/src/trigger/providers/pandadoc/locales/ru.json +12 -0
- package/src/trigger/providers/pandadoc/locales/zh-CN.json +12 -0
- package/src/trigger/providers/pandadoc/locales/zh-TW.json +12 -0
- package/src/trigger/providers/pipedrive/locales/fr.json +15 -0
- package/src/trigger/providers/pipedrive/locales/ja.json +15 -0
- package/src/trigger/providers/pipedrive/locales/ko.json +15 -0
- package/src/trigger/providers/pipedrive/locales/ru.json +15 -0
- package/src/trigger/providers/pipedrive/locales/zh-CN.json +15 -0
- package/src/trigger/providers/pipedrive/locales/zh-TW.json +15 -0
- package/src/trigger/providers/remote.ts +163 -0
- package/src/trigger/providers/resend/locales/fr.json +16 -0
- package/src/trigger/providers/resend/locales/ja.json +16 -0
- package/src/trigger/providers/resend/locales/ko.json +16 -0
- package/src/trigger/providers/resend/locales/ru.json +16 -0
- package/src/trigger/providers/resend/locales/zh-CN.json +16 -0
- package/src/trigger/providers/resend/locales/zh-TW.json +16 -0
- package/src/trigger/providers/sentry/locales/fr.json +19 -0
- package/src/trigger/providers/sentry/locales/ja.json +19 -0
- package/src/trigger/providers/sentry/locales/ko.json +19 -0
- package/src/trigger/providers/sentry/locales/ru.json +19 -0
- package/src/trigger/providers/sentry/locales/zh-CN.json +19 -0
- package/src/trigger/providers/sentry/locales/zh-TW.json +19 -0
- package/src/trigger/providers/shopify/locales/fr.json +18 -0
- package/src/trigger/providers/shopify/locales/ja.json +18 -0
- package/src/trigger/providers/shopify/locales/ko.json +18 -0
- package/src/trigger/providers/shopify/locales/ru.json +18 -0
- package/src/trigger/providers/shopify/locales/zh-CN.json +18 -0
- package/src/trigger/providers/shopify/locales/zh-TW.json +18 -0
- package/src/trigger/providers/slack/locales/fr.json +18 -0
- package/src/trigger/providers/slack/locales/ja.json +18 -0
- package/src/trigger/providers/slack/locales/ko.json +18 -0
- package/src/trigger/providers/slack/locales/ru.json +18 -0
- package/src/trigger/providers/slack/locales/zh-CN.json +18 -0
- package/src/trigger/providers/slack/locales/zh-TW.json +18 -0
- package/src/trigger/providers/slackbot/locales/fr.json +23 -0
- package/src/trigger/providers/slackbot/locales/ja.json +23 -0
- package/src/trigger/providers/slackbot/locales/ko.json +23 -0
- package/src/trigger/providers/slackbot/locales/ru.json +23 -0
- package/src/trigger/providers/slackbot/locales/zh-CN.json +23 -0
- package/src/trigger/providers/slackbot/locales/zh-TW.json +23 -0
- package/src/trigger/providers/source-events.ts +25 -0
- package/src/trigger/providers/stripe/locales/fr.json +17 -0
- package/src/trigger/providers/stripe/locales/ja.json +17 -0
- package/src/trigger/providers/stripe/locales/ko.json +17 -0
- package/src/trigger/providers/stripe/locales/ru.json +17 -0
- package/src/trigger/providers/stripe/locales/zh-CN.json +17 -0
- package/src/trigger/providers/stripe/locales/zh-TW.json +17 -0
- package/src/trigger/providers/tally/locales/fr.json +12 -0
- package/src/trigger/providers/tally/locales/ja.json +12 -0
- package/src/trigger/providers/tally/locales/ko.json +12 -0
- package/src/trigger/providers/tally/locales/ru.json +12 -0
- package/src/trigger/providers/tally/locales/zh-CN.json +12 -0
- package/src/trigger/providers/tally/locales/zh-TW.json +12 -0
- package/src/trigger/providers/telegram/locales/fr.json +17 -0
- package/src/trigger/providers/telegram/locales/ja.json +17 -0
- package/src/trigger/providers/telegram/locales/ko.json +17 -0
- package/src/trigger/providers/telegram/locales/ru.json +17 -0
- package/src/trigger/providers/telegram/locales/zh-CN.json +17 -0
- package/src/trigger/providers/telegram/locales/zh-TW.json +17 -0
- package/src/trigger/providers/typeform/locales/fr.json +12 -0
- package/src/trigger/providers/typeform/locales/ja.json +12 -0
- package/src/trigger/providers/typeform/locales/ko.json +12 -0
- package/src/trigger/providers/typeform/locales/ru.json +12 -0
- package/src/trigger/providers/typeform/locales/zh-CN.json +12 -0
- package/src/trigger/providers/typeform/locales/zh-TW.json +12 -0
- package/src/trigger/providers/vercel/locales/fr.json +18 -0
- package/src/trigger/providers/vercel/locales/ja.json +18 -0
- package/src/trigger/providers/vercel/locales/ko.json +18 -0
- package/src/trigger/providers/vercel/locales/ru.json +18 -0
- package/src/trigger/providers/vercel/locales/zh-CN.json +18 -0
- package/src/trigger/providers/vercel/locales/zh-TW.json +18 -0
- package/src/trigger/providers/woocommerce/locales/fr.json +19 -0
- package/src/trigger/providers/woocommerce/locales/ja.json +19 -0
- package/src/trigger/providers/woocommerce/locales/ko.json +19 -0
- package/src/trigger/providers/woocommerce/locales/ru.json +19 -0
- package/src/trigger/providers/woocommerce/locales/zh-CN.json +19 -0
- package/src/trigger/providers/woocommerce/locales/zh-TW.json +19 -0
- package/src/trigger/providers/zendesk/locales/fr.json +15 -0
- package/src/trigger/providers/zendesk/locales/ja.json +15 -0
- package/src/trigger/providers/zendesk/locales/ko.json +15 -0
- package/src/trigger/providers/zendesk/locales/ru.json +15 -0
- package/src/trigger/providers/zendesk/locales/zh-CN.json +15 -0
- package/src/trigger/providers/zendesk/locales/zh-TW.json +15 -0
- package/src/trigger/providers/zoom/locales/fr.json +17 -0
- package/src/trigger/providers/zoom/locales/ja.json +17 -0
- package/src/trigger/providers/zoom/locales/ko.json +17 -0
- package/src/trigger/providers/zoom/locales/ru.json +17 -0
- package/src/trigger/providers/zoom/locales/zh-CN.json +17 -0
- package/src/trigger/providers/zoom/locales/zh-TW.json +17 -0
- package/src/types/index.ts +112 -0
- package/src/workflow/common/workflow.ts +273 -0
- package/dist/browser/lib-DrKav3HG.js +0 -11403
- /package/dist/{browser → common}/flow-authoring-edge.d.ts +0 -0
- /package/dist/{browser → common}/flow-authoring-module.d.ts +0 -0
- /package/dist/{browser → common}/flow-authoring.d.ts +0 -0
- /package/dist/{browser → common}/flow-input-value.d.ts +0 -0
- /package/dist/{browser → common}/webhook-method.d.ts +0 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { decisionTaskIssues } from '../../decision/common/decision.ts'
|
|
2
|
+
import { openApiIssues, authHandles } from '../../openapi/common/openapi.ts'
|
|
3
|
+
import { nodeWorkflowReferences } from '../../workflow/common/workflow.ts'
|
|
4
|
+
import { isTriggerNode } from './change.ts'
|
|
5
|
+
export { renderPrompt } from './promptTemplate.ts'
|
|
6
|
+
export { connectionUsage, removeConnectionUsage } from './connectionUsage.ts'
|
|
7
|
+
import { matchesTriggerOutputs, normalizeTriggerOutputs } from '../../trigger/common/contract.ts'
|
|
8
|
+
import { nodeInputMappings } from './condition.ts'
|
|
9
|
+
import { connectionUsage } from './connectionUsage.ts'
|
|
10
|
+
export { matchesTriggerOutputs, normalizeTriggerOutputs, triggerOutputDefinitions, triggerOutputPorts } from '../../trigger/common/contract.ts'
|
|
11
|
+
import type { EngineContract } from '../../execution/common/engineContract.ts'
|
|
12
|
+
import type { RuntimeProgram } from '../../execution/common/runtime.ts'
|
|
13
|
+
import type { ConnectorActionCapability, ConnectorCapability, Graph, InputMapping, JsonValue, Port, RevisionContent, SchemaMismatch } from './change.ts'
|
|
14
|
+
|
|
15
|
+
import { findEngineContract } from '../../execution/common/engineContract.ts'
|
|
16
|
+
import { agentConfigIssues } from './agent.ts'
|
|
17
|
+
import { decodeTaskCapabilities } from './change.ts'
|
|
18
|
+
import { canonicalJsonBytes, canonicalModule, canonicalRevisionGraph, digestBytes } from './encoding.ts'
|
|
19
|
+
import { nodeInputPorts, validateFlowGraph } from './graph.ts'
|
|
20
|
+
import { inputValue } from './inputValue.ts'
|
|
21
|
+
import { compareDiagnostics, validateModuleGraph } from './modules.ts'
|
|
22
|
+
import { hasRetiredRef } from './schema.ts'
|
|
23
|
+
export { availableOutputs, graphOrder, nodeInputPorts } from './graph.ts'
|
|
24
|
+
export { validateModules } from './modules.ts'
|
|
25
|
+
export { matchesSchema, schemaValidationErrors, variableInputCompatible } from './schema.ts'
|
|
26
|
+
export { agentInput, agentToolInput, agentToolSchema } from './agent.ts'
|
|
27
|
+
|
|
28
|
+
export interface SemanticClosure {
|
|
29
|
+
readonly dependencies: {
|
|
30
|
+
readonly bindings: ReadonlySet<string>
|
|
31
|
+
readonly nodes: ReadonlySet<string>
|
|
32
|
+
readonly modules: ReadonlySet<string>
|
|
33
|
+
}
|
|
34
|
+
readonly digest: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function entries<T>(value: Readonly<Record<string, T>>): readonly (readonly [string, T])[] {
|
|
38
|
+
return Object.keys(value)
|
|
39
|
+
.toSorted()
|
|
40
|
+
.map((key) => [key, value[key]!] as const)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function flowDependencies(content: RevisionContent, triggerId?: string): SemanticClosure['dependencies'] {
|
|
44
|
+
if (triggerId != null) return flowDependencies(runRevision(content, triggerId))
|
|
45
|
+
const bindings = new Set<string>()
|
|
46
|
+
const modules = new Set<string>()
|
|
47
|
+
|
|
48
|
+
function visitModule(id: string): void {
|
|
49
|
+
if (modules.has(id)) return
|
|
50
|
+
modules.add(id)
|
|
51
|
+
const module = content.modules[id]
|
|
52
|
+
if (module == null) return
|
|
53
|
+
for (const imported of module.imports.toSorted()) visitModule(imported)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function visitInputMappings(value: Readonly<Record<string, InputMapping>>): void {
|
|
57
|
+
for (const mapping of Object.values(value)) {
|
|
58
|
+
if (mapping.kind != 'sources') continue
|
|
59
|
+
for (const source of mapping.sources) {
|
|
60
|
+
if (source.kind != 'binding') continue
|
|
61
|
+
bindings.add(source.bindingId)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function visitGraph(value: Graph): void {
|
|
67
|
+
for (const [, node] of entries(value.nodes)) {
|
|
68
|
+
if (!isTriggerNode(node)) visitInputMappings(nodeInputMappings(node))
|
|
69
|
+
switch (node.kind) {
|
|
70
|
+
case 'condition':
|
|
71
|
+
break
|
|
72
|
+
case 'task':
|
|
73
|
+
if ('moduleId' in node.task) visitModule(node.task.moduleId)
|
|
74
|
+
break
|
|
75
|
+
case 'outputs':
|
|
76
|
+
case 'value':
|
|
77
|
+
break
|
|
78
|
+
case 'approval':
|
|
79
|
+
case 'wait':
|
|
80
|
+
break
|
|
81
|
+
case 'poll':
|
|
82
|
+
case 'integration':
|
|
83
|
+
case 'cron':
|
|
84
|
+
case 'error':
|
|
85
|
+
case 'manual':
|
|
86
|
+
case 'start':
|
|
87
|
+
case 'webhook':
|
|
88
|
+
break
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
visitGraph(content.document.graph)
|
|
94
|
+
|
|
95
|
+
return { bindings, modules, nodes: new Set(Object.keys(content.document.graph.nodes)) }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function flowClosure(content: RevisionContent): Promise<SemanticClosure> {
|
|
99
|
+
const dependencies = flowDependencies(content)
|
|
100
|
+
return { dependencies, digest: await digestBytes(closureBytes(content, dependencies)) }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Canonical semantic bytes, also used by transactional storage upgrades. */
|
|
104
|
+
export function encodeFlowClosure(content: RevisionContent, triggerId?: string): Uint8Array {
|
|
105
|
+
const scoped = triggerId == null ? content : runRevision(content, triggerId)
|
|
106
|
+
return closureBytes(scoped, flowDependencies(scoped))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function closureBytes(content: RevisionContent, dependencies: SemanticClosure['dependencies']): Uint8Array {
|
|
110
|
+
const { bindings, modules } = dependencies
|
|
111
|
+
return canonicalJsonBytes({
|
|
112
|
+
bindings: Object.fromEntries([...bindings].toSorted().map((id) => [id, content.document.bindings[id] ?? null])),
|
|
113
|
+
graph: canonicalRevisionGraph(content, content.document.graph),
|
|
114
|
+
kind: 'open-flow-semantic-closure',
|
|
115
|
+
...(content.modelVersion < 6 ? { subflows: {} } : {}),
|
|
116
|
+
modelVersion: content.modelVersion,
|
|
117
|
+
modules: Object.fromEntries([...modules].toSorted().map((id) => [id, content.modules[id] == null ? null : canonicalModule(content.modules[id])])),
|
|
118
|
+
...(content.modelVersion < 6 ? { tasks: {} } : {}),
|
|
119
|
+
version: 2,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function variableBindings(revision: RevisionContent, bindingIds: Iterable<string>): Readonly<Record<string, string>> {
|
|
124
|
+
return Object.fromEntries(
|
|
125
|
+
[...bindingIds].flatMap((bindingId) => {
|
|
126
|
+
const binding = revision.document.bindings[bindingId]
|
|
127
|
+
return binding?.kind == 'variable' ? [[bindingId, binding.target]] : []
|
|
128
|
+
}),
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface FlowResourceReferences {
|
|
133
|
+
readonly calledFlowIds?: readonly string[]
|
|
134
|
+
readonly variableNames: readonly string[]
|
|
135
|
+
readonly connections: readonly { readonly providerId: string; readonly connectionId: string }[]
|
|
136
|
+
readonly errorSourceFlowIds: readonly string[]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function flowResourceReferences(content: RevisionContent): FlowResourceReferences {
|
|
140
|
+
const connections = new Map<string, { readonly providerId: string; readonly connectionId: string }>()
|
|
141
|
+
for (const use of connectionUsage(content.document)) {
|
|
142
|
+
if (use.connectionId == null || use.connectionId === '') continue
|
|
143
|
+
connections.set(JSON.stringify([use.providerId, use.connectionId]), { providerId: use.providerId, connectionId: use.connectionId })
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
calledFlowIds: [
|
|
147
|
+
...new Set(
|
|
148
|
+
Object.values(content.document.graph.nodes).flatMap((node) =>
|
|
149
|
+
nodeWorkflowReferences(node)
|
|
150
|
+
.map(({ target }) => target.flowId)
|
|
151
|
+
.filter(Boolean),
|
|
152
|
+
),
|
|
153
|
+
),
|
|
154
|
+
].toSorted(),
|
|
155
|
+
variableNames: [...new Set(Object.values(variableBindings(content, flowDependencies(content).bindings)))].toSorted(),
|
|
156
|
+
connections: [...connections].toSorted(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0)).map(([, value]) => value),
|
|
157
|
+
errorSourceFlowIds: [
|
|
158
|
+
...new Set(Object.values(content.document.graph.nodes).flatMap((node) => (node.kind == 'error' ? (node.sourceFlowIds ?? []) : []))),
|
|
159
|
+
].toSorted(),
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface Diagnostic {
|
|
164
|
+
readonly code: string
|
|
165
|
+
readonly column: number
|
|
166
|
+
readonly fields?: readonly string[]
|
|
167
|
+
readonly line: number
|
|
168
|
+
readonly message: string
|
|
169
|
+
readonly mismatch?: SchemaMismatch
|
|
170
|
+
readonly path: string
|
|
171
|
+
readonly values?: Readonly<Record<string, string | number>>
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface FlowValidation {
|
|
175
|
+
readonly closure: SemanticClosure
|
|
176
|
+
readonly diagnostics: readonly Diagnostic[]
|
|
177
|
+
readonly valid: boolean
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type FlowInputsValidation = 'invalid' | 'valid'
|
|
181
|
+
|
|
182
|
+
export function validRunTrigger(revision: RevisionContent, value: unknown): boolean {
|
|
183
|
+
if (value == null || typeof value != 'object' || Array.isArray(value)) return false
|
|
184
|
+
const trigger = value as Readonly<Record<string, unknown>>
|
|
185
|
+
if (Object.keys(trigger).some((key) => key != 'nodeId' && key != 'outputs') || typeof trigger.nodeId != 'string' || !Object.hasOwn(trigger, 'outputs'))
|
|
186
|
+
return false
|
|
187
|
+
const node = revision.document.graph.nodes[trigger.nodeId]
|
|
188
|
+
return node != null && isTriggerNode(node) && matchesTriggerOutputs(node, trigger.outputs)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function normalizeRunTrigger(
|
|
192
|
+
revision: RevisionContent,
|
|
193
|
+
value: unknown,
|
|
194
|
+
): { readonly nodeId: string; readonly outputs: Readonly<Record<string, JsonValue>> } | undefined {
|
|
195
|
+
if (value == null || typeof value != 'object' || Array.isArray(value)) return
|
|
196
|
+
const trigger = value as Readonly<Record<string, unknown>>
|
|
197
|
+
if (Object.keys(trigger).some((key) => key != 'nodeId' && key != 'outputs') || typeof trigger.nodeId != 'string' || !Object.hasOwn(trigger, 'outputs')) return
|
|
198
|
+
const node = revision.document.graph.nodes[trigger.nodeId]
|
|
199
|
+
if (node == null || !isTriggerNode(node)) return
|
|
200
|
+
const outputs = normalizeTriggerOutputs(node, trigger.outputs)
|
|
201
|
+
return outputs == null ? undefined : { nodeId: trigger.nodeId, outputs }
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function validateFlowInputs(revision: RevisionContent, value: unknown): FlowInputsValidation {
|
|
205
|
+
if (value == null || typeof value != 'object' || Array.isArray(value)) return 'invalid'
|
|
206
|
+
const graph = revision.document.graph
|
|
207
|
+
for (const [nodeId, candidate] of Object.entries(value)) {
|
|
208
|
+
const node = graph.nodes[nodeId]
|
|
209
|
+
if (node == null || isTriggerNode(node) || node.kind == 'condition' || candidate == null || typeof candidate != 'object' || Array.isArray(candidate)) {
|
|
210
|
+
return 'invalid'
|
|
211
|
+
}
|
|
212
|
+
const inputs = nodeInputPorts(node)
|
|
213
|
+
for (const handle of Object.keys(candidate)) {
|
|
214
|
+
const port = inputs[handle]
|
|
215
|
+
if (port == null || hasRetiredRef(port.jsonSchema) || nodeInputMappings(node)[handle] != null || Object.hasOwn(port, 'value')) return 'invalid'
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return 'valid'
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export async function validateFlow(revision: RevisionContent, engine: EngineContract): Promise<FlowValidation> {
|
|
222
|
+
const closure = await flowClosure(revision)
|
|
223
|
+
const checked = validateModuleGraph(revision, [...closure.dependencies.modules], engine)
|
|
224
|
+
checked.diagnostics.push(...validateFlowGraph(revision))
|
|
225
|
+
const missingEntryModules = new Set<string>()
|
|
226
|
+
for (const [nodeId, node] of Object.entries(revision.document.graph.nodes)) {
|
|
227
|
+
if (node.kind != 'task' || !('moduleId' in node.task)) continue
|
|
228
|
+
if (revision.modules[node.task.moduleId] == null) {
|
|
229
|
+
checked.diagnostics.push({
|
|
230
|
+
code: 'task.module-missing',
|
|
231
|
+
column: 0,
|
|
232
|
+
line: 1,
|
|
233
|
+
message: `Inline Task "${nodeId}" references missing CodeModule "${node.task.moduleId}".`,
|
|
234
|
+
path: `/document/graph/nodes/${nodeId}/task/moduleId`,
|
|
235
|
+
values: { moduleId: node.task.moduleId, nodeId },
|
|
236
|
+
})
|
|
237
|
+
} else if (checked.analysis.get(node.task.moduleId)?.exports.has('default') == false && !missingEntryModules.has(node.task.moduleId)) {
|
|
238
|
+
missingEntryModules.add(node.task.moduleId)
|
|
239
|
+
checked.diagnostics.push({
|
|
240
|
+
code: 'task.missing-entry',
|
|
241
|
+
column: 0,
|
|
242
|
+
line: 1,
|
|
243
|
+
message: `CodeModule "${node.task.moduleId}" used by an Inline Task must export a default function.`,
|
|
244
|
+
path: `/modules/${node.task.moduleId}/source`,
|
|
245
|
+
values: { moduleId: node.task.moduleId },
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
decodeTaskCapabilities(node.task.capabilities === undefined ? [] : node.task.capabilities)
|
|
250
|
+
} catch {
|
|
251
|
+
checked.diagnostics.push({
|
|
252
|
+
code: 'task.capability-incomplete',
|
|
253
|
+
column: 0,
|
|
254
|
+
line: 1,
|
|
255
|
+
message: `Inline Task "${nodeId}" has an incomplete Connector Capability.`,
|
|
256
|
+
path: `/document/graph/nodes/${nodeId}/task/capabilities`,
|
|
257
|
+
values: { nodeId },
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
for (const [nodeId, node] of Object.entries(revision.document.graph.nodes)) {
|
|
262
|
+
if (node.kind != 'task' || !('executor' in node.task)) continue
|
|
263
|
+
const task = node.task
|
|
264
|
+
for (const issue of decisionTaskIssues(task))
|
|
265
|
+
checked.diagnostics.push({
|
|
266
|
+
code: 'decision.config-invalid',
|
|
267
|
+
column: 0,
|
|
268
|
+
line: 1,
|
|
269
|
+
message: issue.message,
|
|
270
|
+
path: `/document/graph/nodes/${nodeId}/task/executor`,
|
|
271
|
+
})
|
|
272
|
+
for (const message of openApiIssues(task))
|
|
273
|
+
checked.diagnostics.push({ code: 'openapi.config-invalid', column: 0, line: 1, message, path: `/document/graph/nodes/${nodeId}/task/executor` })
|
|
274
|
+
if (task.executor.kind == 'openapi') {
|
|
275
|
+
const handles = authHandles(task.executor.auth)
|
|
276
|
+
for (const handle of handles) {
|
|
277
|
+
const mapping = node.inputs[handle]
|
|
278
|
+
if (mapping?.kind != 'sources' || mapping.sources.length == 0)
|
|
279
|
+
checked.diagnostics.push({
|
|
280
|
+
code: 'openapi.auth-source',
|
|
281
|
+
column: 0,
|
|
282
|
+
line: 1,
|
|
283
|
+
message: 'Authentication requires a deployment variable or upstream output.',
|
|
284
|
+
path: `/document/graph/nodes/${nodeId}/inputs/${handle}`,
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
for (const message of agentConfigIssues(task)) {
|
|
289
|
+
checked.diagnostics.push({ code: 'agent.config-invalid', column: 0, line: 1, message, path: `/document/graph/nodes/${nodeId}/task/executor` })
|
|
290
|
+
}
|
|
291
|
+
if (task.executor.kind == 'connector' && task.executor.action == 'leina.send_notification') {
|
|
292
|
+
const mapping = node.inputs.leinaId
|
|
293
|
+
const value = inputValue(mapping, nodeInputPorts(node).leinaId?.value)
|
|
294
|
+
if ((mapping?.kind != 'sources' || mapping.sources.length == 0) && (typeof value != 'string' || value.trim().length == 0)) {
|
|
295
|
+
checked.diagnostics.push({
|
|
296
|
+
code: 'leina.robot-required',
|
|
297
|
+
column: 0,
|
|
298
|
+
line: 1,
|
|
299
|
+
message: 'Select a Leina robot or bind its identifier to an input source.',
|
|
300
|
+
path: `/document/graph/nodes/${nodeId}/inputs/leinaId`,
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (task.executor.kind == 'connector' && task.executor.action.length == 0) {
|
|
305
|
+
checked.diagnostics.push({
|
|
306
|
+
code: 'task.connector-incomplete',
|
|
307
|
+
column: 0,
|
|
308
|
+
line: 1,
|
|
309
|
+
message: `Connector Task "${nodeId}" requires an action.`,
|
|
310
|
+
path: `/document/graph/nodes/${nodeId}/task/executor`,
|
|
311
|
+
values: { nodeId },
|
|
312
|
+
})
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const diagnostics = checked.diagnostics.toSorted(compareDiagnostics)
|
|
316
|
+
return { closure, diagnostics, valid: diagnostics.length == 0 }
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface PreparedFlow {
|
|
320
|
+
readonly inputDefs: readonly Port[]
|
|
321
|
+
readonly outputDefs: readonly Port[]
|
|
322
|
+
readonly outputMappings: Readonly<Record<string, InputMapping>>
|
|
323
|
+
readonly closureDigest: string
|
|
324
|
+
readonly engineContract: string
|
|
325
|
+
readonly graph: Graph
|
|
326
|
+
readonly modules: RevisionContent['modules']
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export type PrepareFlowResult =
|
|
330
|
+
| { readonly kind: 'engine-unsupported' }
|
|
331
|
+
| { readonly kind: 'flow-invalid'; readonly validation: FlowValidation }
|
|
332
|
+
| { readonly flow: PreparedFlow; readonly kind: 'prepared'; readonly validation: FlowValidation }
|
|
333
|
+
|
|
334
|
+
function runRevision(revision: RevisionContent, triggerId: string): RevisionContent {
|
|
335
|
+
const graph = revision.document.graph
|
|
336
|
+
const reachable = new Set([triggerId])
|
|
337
|
+
for (const nodeId of reachable) {
|
|
338
|
+
for (const edge of graph.edges) if (edge.source == nodeId) reachable.add(edge.target)
|
|
339
|
+
}
|
|
340
|
+
function inputs(nodeId: string, mappings: Readonly<Record<string, InputMapping>>): Readonly<Record<string, InputMapping>> {
|
|
341
|
+
const ancestors = new Set<string>()
|
|
342
|
+
for (const edge of graph.edges) if (edge.target == nodeId) ancestors.add(edge.source)
|
|
343
|
+
for (const ancestor of ancestors) {
|
|
344
|
+
for (const edge of graph.edges) if (edge.target == ancestor) ancestors.add(edge.source)
|
|
345
|
+
}
|
|
346
|
+
return Object.fromEntries(
|
|
347
|
+
Object.entries(mappings).map(([handle, mapping]) => [
|
|
348
|
+
handle,
|
|
349
|
+
mapping.kind != 'sources'
|
|
350
|
+
? mapping
|
|
351
|
+
: {
|
|
352
|
+
...mapping,
|
|
353
|
+
sources: mapping.sources.filter(
|
|
354
|
+
(source) => source.kind != 'node' || graph.nodes[source.nodeId] == null || reachable.has(source.nodeId) || !ancestors.has(source.nodeId),
|
|
355
|
+
),
|
|
356
|
+
},
|
|
357
|
+
]),
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
const nodes: Record<string, Graph['nodes'][string]> = {}
|
|
361
|
+
for (const nodeId of reachable) {
|
|
362
|
+
const node = graph.nodes[nodeId]
|
|
363
|
+
if (node == null) continue
|
|
364
|
+
nodes[nodeId] =
|
|
365
|
+
node.kind == 'outputs'
|
|
366
|
+
? { ...node, outputMappings: inputs(nodeId, node.outputMappings) }
|
|
367
|
+
: isTriggerNode(node)
|
|
368
|
+
? node
|
|
369
|
+
: {
|
|
370
|
+
...node,
|
|
371
|
+
inputs: inputs(nodeId, node.inputs),
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const content = {
|
|
375
|
+
...revision,
|
|
376
|
+
document: {
|
|
377
|
+
...revision.document,
|
|
378
|
+
graph: { nodes, edges: graph.edges.filter((edge) => reachable.has(edge.source)) },
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
const { bindings } = flowDependencies(content)
|
|
382
|
+
return {
|
|
383
|
+
...content,
|
|
384
|
+
document: { ...content.document, bindings: Object.fromEntries(Object.entries(content.document.bindings).filter(([id]) => bindings.has(id))) },
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export async function prepareFlow(revision: RevisionContent, engineContract: string, triggerId?: string): Promise<PrepareFlowResult> {
|
|
389
|
+
const engine = findEngineContract(engineContract)
|
|
390
|
+
if (engine == null) return { kind: 'engine-unsupported' }
|
|
391
|
+
if (!engine.workflowTools && Object.values(revision.document.graph.nodes).some((node) => nodeWorkflowReferences(node).some((ref) => ref.tool != null)))
|
|
392
|
+
return { kind: 'engine-unsupported' }
|
|
393
|
+
if (triggerId != null) {
|
|
394
|
+
const trigger = revision.document.graph.nodes[triggerId]
|
|
395
|
+
if (trigger == null || !isTriggerNode(trigger))
|
|
396
|
+
return {
|
|
397
|
+
kind: 'flow-invalid',
|
|
398
|
+
validation: {
|
|
399
|
+
closure: await flowClosure(revision),
|
|
400
|
+
diagnostics: [
|
|
401
|
+
{
|
|
402
|
+
code: 'graph.trigger-invalid',
|
|
403
|
+
column: 0,
|
|
404
|
+
line: 1,
|
|
405
|
+
message: 'Select an existing Trigger node.',
|
|
406
|
+
path: '/document/graph',
|
|
407
|
+
values: { nodeId: triggerId },
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
valid: false,
|
|
411
|
+
},
|
|
412
|
+
}
|
|
413
|
+
revision = runRevision(revision, triggerId)
|
|
414
|
+
}
|
|
415
|
+
if (
|
|
416
|
+
!engine.webhookResponses &&
|
|
417
|
+
Object.values(revision.document.graph.nodes).some(
|
|
418
|
+
(node) => node.kind === 'webhook-response' || (node.kind === 'webhook' && node.options?.responseBody?.kind === 'webhook-response'),
|
|
419
|
+
)
|
|
420
|
+
)
|
|
421
|
+
return { kind: 'engine-unsupported' }
|
|
422
|
+
if (!engine.waitAutoContinue && Object.values(revision.document.graph.nodes).some((node) => node.kind == 'wait' && node.autoContinue != null))
|
|
423
|
+
return { kind: 'engine-unsupported' }
|
|
424
|
+
const validation = await validateFlow(revision, engine)
|
|
425
|
+
if (!validation.valid) return { kind: 'flow-invalid', validation }
|
|
426
|
+
const { closure } = validation
|
|
427
|
+
const start = Object.values(revision.document.graph.nodes).find((node) => node.kind == 'start')
|
|
428
|
+
const outputs = Object.values(revision.document.graph.nodes).find((node) => node.kind == 'outputs')
|
|
429
|
+
return {
|
|
430
|
+
flow: {
|
|
431
|
+
closureDigest: closure.digest,
|
|
432
|
+
engineContract,
|
|
433
|
+
inputDefs: start?.inputDefs ?? [],
|
|
434
|
+
outputDefs: outputs?.outputDefs ?? [],
|
|
435
|
+
outputMappings: outputs?.outputMappings ?? {},
|
|
436
|
+
graph: revision.document.graph,
|
|
437
|
+
modules: Object.fromEntries([...closure.dependencies.modules].toSorted().map((id) => [id, revision.modules[id]!])),
|
|
438
|
+
},
|
|
439
|
+
kind: 'prepared',
|
|
440
|
+
validation,
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export function createRuntimeProgram(prepared: PreparedFlow, entryModuleId: string, engineDigest: string): RuntimeProgram | undefined {
|
|
445
|
+
if (!Object.hasOwn(prepared.modules, entryModuleId)) return
|
|
446
|
+
return {
|
|
447
|
+
engineContract: prepared.engineContract,
|
|
448
|
+
engineDigest,
|
|
449
|
+
entryModuleId,
|
|
450
|
+
modules: prepared.modules,
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export function agentActions(flow: Pick<PreparedFlow, 'graph'>): readonly ConnectorActionCapability[] {
|
|
455
|
+
return Object.values(flow.graph.nodes).flatMap((node) => {
|
|
456
|
+
if (node.kind != 'task' || !('executor' in node.task)) return []
|
|
457
|
+
const task = node.task
|
|
458
|
+
if (task.executor.kind != 'agent') return []
|
|
459
|
+
const notice = task.executor.notification
|
|
460
|
+
return [...task.executor.tools.filter((tool) => tool.kind != 'workflow'), ...(notice != null ? [notice] : [])]
|
|
461
|
+
.filter((tool) => tool.connectionId !== '')
|
|
462
|
+
.map((tool) => ({
|
|
463
|
+
kind: 'connector' as const,
|
|
464
|
+
action: tool.action,
|
|
465
|
+
connections: tool.connectionId == null ? [] : [{ connectionId: tool.connectionId }],
|
|
466
|
+
}))
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export function codeActions(flow: Pick<PreparedFlow, 'graph'>): readonly ConnectorCapability[] {
|
|
471
|
+
return Object.values(flow.graph.nodes).flatMap((node) =>
|
|
472
|
+
node.kind == 'task' && 'moduleId' in node.task ? (node.task.capabilities ?? []).filter((item) => item.kind == 'connector') : [],
|
|
473
|
+
)
|
|
474
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { NodeSource, PortDefinition } from './change.ts'
|
|
2
|
+
|
|
3
|
+
import { schemaObject } from './schema.ts'
|
|
4
|
+
|
|
5
|
+
/** Only explicitly declared, first-level object properties are selectable. */
|
|
6
|
+
export function sourceFields(output: PortDefinition): readonly { readonly field: string; readonly port: PortDefinition }[] {
|
|
7
|
+
const schema = schemaObject(output.jsonSchema)
|
|
8
|
+
if (schema == null) return []
|
|
9
|
+
const properties = schemaObject(schema.properties ?? false)
|
|
10
|
+
const types = Array.isArray(schema.type) ? schema.type : [schema.type]
|
|
11
|
+
if (properties == null || (schema.type !== undefined && !types.includes('object'))) return []
|
|
12
|
+
const required = Array.isArray(schema.required) ? schema.required : []
|
|
13
|
+
const missingParent = output.nullable || types.some((type) => type !== 'object')
|
|
14
|
+
return Object.entries(properties).map(([field, jsonSchema]) => {
|
|
15
|
+
const description = schemaObject(jsonSchema)?.description
|
|
16
|
+
return {
|
|
17
|
+
field,
|
|
18
|
+
port: {
|
|
19
|
+
...(typeof description == 'string' ? { description } : {}),
|
|
20
|
+
jsonSchema,
|
|
21
|
+
nullable: missingParent || !required.includes(field),
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function sourcePort(output: PortDefinition, field: string | undefined): PortDefinition | undefined {
|
|
28
|
+
return field === undefined ? output : sourceFields(output).find((candidate) => candidate.field === field)?.port
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Present a selected first-level field as a compact path from its output. */
|
|
32
|
+
export function sourceOutputLabel(source: Pick<NodeSource, 'output' | 'field' | 'system'>): string {
|
|
33
|
+
const output = source.system ? `$system / ${source.output}` : source.output
|
|
34
|
+
return source.field === undefined ? output : `${output} / ${source.field}`
|
|
35
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export const triggerScheduleSchema = z.array(
|
|
4
|
+
z.union([
|
|
5
|
+
z.object({ type: z.literal('cron'), expression: z.string(), timezone: z.string() }),
|
|
6
|
+
z.object({ type: z.literal('every'), unit: z.enum(['day', 'hour', 'minute', 'month', 'week']), value: z.number() }),
|
|
7
|
+
]),
|
|
8
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { WaitAutoContinue } from './change.ts'
|
|
2
|
+
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
import { isTimeZone } from '../../localization/common/timeZone.ts'
|
|
5
|
+
|
|
6
|
+
/** Drafts retain incomplete values; semantic validation gates publication and execution. */
|
|
7
|
+
export const waitAutoContinueDraftSchema = z.discriminatedUnion('kind', [
|
|
8
|
+
z.strictObject({ kind: z.literal('after'), durationMs: z.number().nullable() }),
|
|
9
|
+
z.strictObject({
|
|
10
|
+
kind: z.literal('at'),
|
|
11
|
+
at: z.string(),
|
|
12
|
+
timezone: z.string().optional(),
|
|
13
|
+
}),
|
|
14
|
+
])
|
|
15
|
+
|
|
16
|
+
/** Static business configuration; the deployment owns the allowed wait lifetime. */
|
|
17
|
+
export const waitAutoContinueSchema = z.discriminatedUnion('kind', [
|
|
18
|
+
waitAutoContinueDraftSchema.options[0].extend({ durationMs: z.number().int().positive().max(Number.MAX_SAFE_INTEGER) }),
|
|
19
|
+
waitAutoContinueDraftSchema.options[1].extend({
|
|
20
|
+
at: z.iso.datetime({ offset: true }),
|
|
21
|
+
timezone: z.string().refine(isTimeZone, 'Select a valid IANA timezone.').optional(),
|
|
22
|
+
}),
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
/** Resolve one registration's intent; the deployment separately enforces its lifetime. */
|
|
26
|
+
export function waitAutoContinueAt(config: WaitAutoContinue, waitingSince: number): number {
|
|
27
|
+
const timing = waitAutoContinueSchema.parse(config)
|
|
28
|
+
const at = timing.kind == 'after' ? waitingSince + timing.durationMs : Date.parse(timing.at)
|
|
29
|
+
return Math.max(waitingSince, at)
|
|
30
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { InputPort, JsonValue, Port, PortDefinition } from './change.ts'
|
|
2
|
+
|
|
3
|
+
export const webhookResponseTimeout = {
|
|
4
|
+
defaultMs: 30_000,
|
|
5
|
+
minMs: 1000,
|
|
6
|
+
maxMs: 60_000,
|
|
7
|
+
} as const
|
|
8
|
+
|
|
9
|
+
export const webhookStatusCodePort = { jsonSchema: { type: 'number' }, nullable: true } as const
|
|
10
|
+
|
|
11
|
+
export function webhookResponseAllowsBody(status: number): boolean {
|
|
12
|
+
return status !== 204 && status !== 205 && status !== 304
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const webhookHeaderValuePort = { jsonSchema: { type: ['string', 'number', 'boolean'] }, nullable: true } as const
|
|
16
|
+
export const webhookHeadersPort = {
|
|
17
|
+
jsonSchema: { type: 'object', additionalProperties: { type: ['string', 'number', 'boolean'] } },
|
|
18
|
+
nullable: true,
|
|
19
|
+
} as const
|
|
20
|
+
|
|
21
|
+
export function workflowOutputsPort(outputs: readonly Port[]): PortDefinition {
|
|
22
|
+
return {
|
|
23
|
+
jsonSchema: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: Object.fromEntries(outputs.map((port) => [port.handle, port.jsonSchema])),
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
required: outputs.map((port) => port.handle),
|
|
28
|
+
},
|
|
29
|
+
nullable: false,
|
|
30
|
+
} as const
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Header names are case-insensitive; never silently combine duplicate business fields. */
|
|
34
|
+
export function webhookHeaderNameIssue(name: string, names: readonly string[]): 'invalid' | 'duplicate' | undefined {
|
|
35
|
+
if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) return 'invalid'
|
|
36
|
+
if (names.some((candidate) => candidate.toLowerCase() === name.toLowerCase())) return 'duplicate'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Fixed inputs belong to the node, not author-supplied definitions. */
|
|
40
|
+
export const webhookResponseInputs: readonly InputPort[] = [
|
|
41
|
+
{ handle: 'body', jsonSchema: {}, nullable: true, value: '' },
|
|
42
|
+
{ handle: 'statusCode', jsonSchema: { type: 'number' }, nullable: false, value: 200 },
|
|
43
|
+
{ handle: 'headers', jsonSchema: webhookHeadersPort.jsonSchema, nullable: false, value: {} },
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
export interface WebhookResponseSnapshot {
|
|
47
|
+
readonly body: string
|
|
48
|
+
readonly contentType: string
|
|
49
|
+
readonly status: number
|
|
50
|
+
readonly headers: Readonly<Record<string, string>>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function validWebhookStatus(value: unknown): value is number {
|
|
54
|
+
return typeof value === 'number' && Number.isInteger(value) && value >= 200 && value <= 599 && webhookResponseAllowsBody(value)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Portable validation also runs in the isolated engine, which has no HTTP globals. */
|
|
58
|
+
export function webhookHeaderValues(source: unknown): Readonly<Record<string, string>> | undefined {
|
|
59
|
+
if (source == null || typeof source !== 'object' || Array.isArray(source)) return
|
|
60
|
+
const headers: Record<string, string> = {}
|
|
61
|
+
const names: string[] = []
|
|
62
|
+
for (const [name, value] of Object.entries(source)) {
|
|
63
|
+
if (webhookHeaderNameIssue(name, names) != null) return
|
|
64
|
+
if (typeof value !== 'string' && typeof value !== 'boolean' && !(typeof value === 'number' && Number.isFinite(value))) return
|
|
65
|
+
const text = String(value)
|
|
66
|
+
if ([...text].some((character) => character.charCodeAt(0) > 255 || /[\0\r\n]/.test(character))) return
|
|
67
|
+
names.push(name)
|
|
68
|
+
Object.defineProperty(headers, name, { value: text, enumerable: true, configurable: true })
|
|
69
|
+
}
|
|
70
|
+
return headers
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function encodeWebhookBody(value: JsonValue): Pick<WebhookResponseSnapshot, 'body' | 'contentType'> {
|
|
74
|
+
return typeof value === 'string' ? { body: value, contentType: 'text/plain;charset=UTF-8' } : { body: JSON.stringify(value), contentType: 'application/json' }
|
|
75
|
+
}
|