@oomol-lab/open-flow 0.1.0-beta.74 → 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.
- package/README.md +3 -1
- package/dist/browser/{ContentIcon-CUQHjQIw.js → ContentIcon-Cm1hbVzW.js} +4 -3
- package/dist/browser/{FlowCanvas-Dtf8_cQp.js → FlowCanvas-NzKtla_c.js} +62 -62
- package/dist/browser/{createResourceDialog-DI9pL-Yr.js → createResourceDialog-BgdedQqu.js} +3 -3
- package/dist/browser/{dialog-BYJGvItc.js → dialog-aSElFFw2.js} +322 -26
- package/dist/browser/{exportSvg-BOoy7-Db.js → exportSvg-Dcz4HTo_.js} +2 -2
- package/dist/browser/{flowChanges-RL-H4CjD.js → flowChanges-NZyS7HSp.js} +490 -438
- package/dist/browser/{flowWorkspace-BkDsETj0.js → flowWorkspace-Bl0SDehy.js} +499 -61
- package/dist/browser/preview.css +696 -825
- package/dist/browser/preview.js +1399 -717
- package/dist/browser/theme.css +114 -262
- package/dist/browser/{tooltip-wZJRB9oP.js → tooltip-3XMK9jkr.js} +1 -1
- package/dist/browser/{typeScriptSession-CSRwWmZm.js → typeScriptSession-C9sBGOKZ.js} +1 -1
- package/dist/browser/ui.css +354 -460
- package/dist/browser/ui.js +1 -1
- package/dist/browser/workbench.css +696 -825
- package/dist/browser/workbench.js +13 -7
- package/dist/browser/{workbenchSelect-BcWPWGzw.js → workbenchSelect-DBGP7Y4Z.js} +2 -2
- package/dist/command/index.js +41 -43
- package/dist/common/authoring.d.ts +5 -5
- package/dist/common/authoringExamples.d.ts +3 -2
- package/dist/common/authoringSchema.d.ts +70 -4
- package/dist/common/connector-proxy.d.ts +1 -1
- package/dist/common/control-api-conformance.js +250 -138
- package/dist/common/control-api.d.ts +3 -2
- package/dist/common/control-api.js +246 -134
- package/dist/common/control-requests.d.ts +3 -3
- package/dist/common/control-requests.js +353 -79
- package/dist/common/cron-trigger.d.ts +2 -1
- package/dist/common/decision.d.ts +4 -4
- package/dist/common/decision.js +5 -2
- package/dist/common/engine-contract.d.ts +6 -1
- package/dist/common/event-source-definition.d.ts +1 -1
- package/dist/common/event-source-view.d.ts +22 -0
- package/dist/common/event-source.d.ts +1 -1
- package/dist/common/event-source.js +24 -65
- package/dist/common/event-sources.d.ts +0 -21
- package/dist/common/flow-authoring.js +90 -19
- package/dist/common/flow-change-schema.d.ts +9 -1
- package/dist/common/flow-change.d.ts +7 -201
- package/dist/common/flow-change.js +96 -23
- package/dist/common/flow-encoding.js +89 -21
- package/dist/common/flow-graph.d.ts +2 -1
- package/dist/common/flow-input-value.d.ts +1 -1
- package/dist/common/flow-model.d.ts +121 -0
- package/dist/common/flow-notifications.d.ts +1 -1
- package/dist/common/flow-retry.d.ts +3 -5
- package/dist/common/flow-semantics.js +816 -586
- package/dist/common/flow-workflowReferences.d.ts +8 -0
- package/dist/common/flowInspection.d.ts +1 -1
- package/dist/common/http-hosts.d.ts +6 -0
- package/dist/common/http-request.d.ts +164 -0
- package/dist/common/http-request.js +5272 -0
- package/dist/common/integration-trigger.d.ts +2 -1
- package/dist/common/mcp.d.ts +3 -3
- package/dist/common/mcp.js +248 -136
- package/dist/common/openapi.d.ts +4 -4
- package/dist/common/openapi.js +4 -1
- package/dist/common/poll-trigger.d.ts +2 -1
- package/dist/common/run-events.js +11 -9
- package/dist/common/runtime-contract.d.ts +23 -1
- package/dist/common/runtime-contract.js +607 -72
- package/dist/common/runtime-nodejs-compat.d.ts +44 -0
- package/dist/common/runtime-nodejs-compat.js +5870 -0
- package/dist/common/scheduler-checkpoint.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 +95 -25
- package/dist/common/trigger-catalog.d.ts +1 -7
- 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 -1
- package/dist/common/trigger-localization.d.ts +8 -2
- package/dist/common/trigger-model.d.ts +101 -0
- package/dist/common/webhook-response.d.ts +1 -3
- package/dist/common/webhook-trigger.d.ts +3 -1
- package/dist/common/webhook-trigger.js +12 -11
- package/dist/common/workflow.d.ts +3 -12
- package/dist/common/workflow.js +25 -23
- package/dist/index.d.ts +41 -14
- package/package.json +9 -1
- package/skills/open-flow/references/flow-authoring.md +1 -0
- package/skills/open-flow/references/flow-n8n-conversion.md +19 -15
- package/src/base/common/json.ts +1 -1
- package/src/connector/common/proxy.ts +1 -1
- package/src/control/common/api.ts +7 -5
- package/src/control/common/authoring.ts +14 -3
- package/src/control/common/authoringExamples.ts +8 -0
- package/src/control/common/authoringSchema.ts +38 -25
- package/src/control/common/authoringTools.ts +1 -1
- package/src/control/common/conformance.ts +1 -1
- package/src/control/common/connectorDecoders.ts +1 -1
- package/src/control/common/eventSources.ts +2 -29
- package/src/control/common/triggerCatalog.ts +1 -8
- package/src/decision/common/decision.ts +15 -7
- package/src/event-source/common/definition.ts +1 -1
- package/src/event-source/common/index.ts +1 -1
- package/src/event-source/common/view.ts +20 -0
- package/src/execution/common/checkpoint.ts +1 -1
- package/src/execution/common/events.ts +3 -0
- package/src/execution/common/node-execution.ts +5 -3
- package/src/execution/common/scheduler.ts +2 -1
- package/src/flow/common/change.ts +59 -192
- package/src/flow/common/changeSchema.ts +39 -5
- package/src/flow/common/connectionUsage.ts +1 -1
- package/src/flow/common/graph.ts +10 -4
- package/src/flow/common/inputValue.ts +1 -1
- package/src/flow/common/model.ts +130 -0
- package/src/flow/common/modules.ts +1 -1
- package/src/flow/common/portChanges.ts +1 -1
- package/src/flow/common/retry.ts +3 -5
- package/src/flow/common/semantics.ts +71 -7
- package/src/flow/common/webhookResponse.ts +4 -8
- package/src/flow/common/workflowReferences.ts +31 -0
- package/src/http/common/authBindings.ts +9 -0
- package/src/http/common/headers.ts +5 -0
- package/src/http/common/hosts.ts +13 -0
- package/src/http/common/httpRequest.ts +266 -0
- package/src/openapi/common/openapi.ts +9 -5
- package/src/{execution → runtime}/common/engineContract.ts +24 -15
- package/src/runtime/common/nodejsCompat.ts +275 -0
- package/src/runtime/common/nodejsGuest.generated.json +47 -0
- package/src/runtime/common/runtime.ts +1138 -0
- package/src/trigger/common/config.ts +1 -1
- package/src/trigger/common/configOptions.ts +1 -1
- package/src/trigger/common/contract.ts +2 -1
- package/src/trigger/common/cron.ts +2 -1
- package/src/trigger/common/integration.ts +2 -1
- package/src/trigger/common/model.ts +87 -0
- package/src/trigger/common/poll.ts +2 -1
- package/src/trigger/common/webhook.ts +7 -4
- package/src/trigger/providers/fieldDescriptions.ts +1 -1
- package/src/trigger/providers/localization.ts +9 -2
- package/src/trigger/providers/remote.ts +1 -1
- package/src/types/index.ts +44 -15
- package/src/workflow/common/workflow.ts +3 -44
- package/src/execution/common/runtime.ts +0 -563
- package/src/openapi/common/authBindings.ts +0 -12
- /package/src/{control → connector}/common/providerIconSprite.ts +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -20,18 +20,50 @@ export interface ArtifactRef {
|
|
|
20
20
|
readonly kind: 'artifact';
|
|
21
21
|
readonly id: string;
|
|
22
22
|
readonly name: string;
|
|
23
|
-
readonly mediaType
|
|
23
|
+
readonly mediaType?: string;
|
|
24
24
|
readonly size: number;
|
|
25
25
|
readonly digest: string;
|
|
26
26
|
}
|
|
27
27
|
export interface ArtifactPutOptions {
|
|
28
28
|
readonly name: string;
|
|
29
|
-
readonly mediaType?: string
|
|
29
|
+
readonly mediaType?: string;
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
/** Strings are stored as UTF-8. */
|
|
32
|
+
export type ArtifactData = string | Uint8Array;
|
|
33
|
+
/** Artifacts belong to the current Run; an ArtifactRef is JSON and can be passed to downstream nodes. */
|
|
32
34
|
export interface ArtifactCapability {
|
|
33
35
|
put(data: ArtifactData, options: ArtifactPutOptions): Promise<ArtifactRef>;
|
|
34
|
-
open(ref: ArtifactRef): Promise<
|
|
36
|
+
open(ref: ArtifactRef): Promise<Uint8Array>;
|
|
37
|
+
}
|
|
38
|
+
export interface TaskFetchInit {
|
|
39
|
+
/** GET, HEAD, POST, PUT, PATCH, DELETE or OPTIONS. */
|
|
40
|
+
readonly method?: string;
|
|
41
|
+
readonly headers?: Readonly<Record<string, string>> | Iterable<readonly [string, string]>;
|
|
42
|
+
/** At most 1 MiB; strings are sent as UTF-8 text/plain unless a content-type header is supplied. */
|
|
43
|
+
readonly body?: string | Uint8Array | ArrayBuffer;
|
|
44
|
+
readonly signal?: AbortSignal;
|
|
45
|
+
}
|
|
46
|
+
export interface TaskFetchHeaders extends Iterable<[string, string]> {
|
|
47
|
+
get(name: string): string | null;
|
|
48
|
+
has(name: string): boolean;
|
|
49
|
+
entries(): IterableIterator<[string, string]>;
|
|
50
|
+
keys(): IterableIterator<string>;
|
|
51
|
+
values(): IterableIterator<string>;
|
|
52
|
+
forEach(callback: (value: string, name: string) => void): void;
|
|
53
|
+
}
|
|
54
|
+
/** A read-only subset of the Fetch Response; the body is buffered, at most 1 MiB, and readable once. */
|
|
55
|
+
export interface TaskFetchResponse {
|
|
56
|
+
readonly status: number;
|
|
57
|
+
readonly statusText: string;
|
|
58
|
+
readonly ok: boolean;
|
|
59
|
+
readonly redirected: false;
|
|
60
|
+
readonly url: string;
|
|
61
|
+
readonly headers: TaskFetchHeaders;
|
|
62
|
+
readonly bodyUsed: boolean;
|
|
63
|
+
bytes(): Promise<Uint8Array>;
|
|
64
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
65
|
+
text(): Promise<string>;
|
|
66
|
+
json(): Promise<unknown>;
|
|
35
67
|
}
|
|
36
68
|
export interface MediaPreviewPayload {
|
|
37
69
|
readonly type: 'video' | 'audio' | 'markdown' | 'iframe' | 'html';
|
|
@@ -60,12 +92,6 @@ export interface CsvPreviewPayload {
|
|
|
60
92
|
}
|
|
61
93
|
export type PreviewPayload = MediaPreviewPayload | TextPreviewPayload | ImagePreviewPayload | TablePreviewPayload | CsvPreviewPayload;
|
|
62
94
|
export type PreviewType = PreviewPayload['type'];
|
|
63
|
-
export interface TaskLogger {
|
|
64
|
-
debug(message: string, data?: unknown): void;
|
|
65
|
-
info(message: string, data?: unknown): void;
|
|
66
|
-
warn(message: string, data?: unknown): void;
|
|
67
|
-
error(message: string, data?: unknown): void;
|
|
68
|
-
}
|
|
69
95
|
export interface TaskContext<Actions extends object = Record<string, never>, Workflows extends object = {
|
|
70
96
|
call: (name: never, input?: never) => Promise<never>;
|
|
71
97
|
}> {
|
|
@@ -77,12 +103,13 @@ export interface TaskContext<Actions extends object = Record<string, never>, Wor
|
|
|
77
103
|
readonly runId: string;
|
|
78
104
|
readonly blockId: string;
|
|
79
105
|
readonly artifact: ArtifactCapability;
|
|
80
|
-
readonly fetch: typeof fetch;
|
|
81
|
-
readonly logger: TaskLogger;
|
|
82
106
|
/** Reads the selected direct predecessors, sorted by node ID; empty for a graph root. */
|
|
83
107
|
getPrevious(): Promise<readonly PreviousNode[]>;
|
|
84
|
-
|
|
85
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Calls an HTTP(S) URL whose host the node declares in its `http` Capability. Redirects are returned, not followed,
|
|
110
|
+
* and no platform credentials are added. Network failures reject with a TypeError.
|
|
111
|
+
*/
|
|
112
|
+
fetch(input: string | URL, init?: TaskFetchInit): Promise<TaskFetchResponse>;
|
|
86
113
|
}
|
|
87
114
|
export type TaskResult<Outputs extends object> = keyof Outputs extends never ? Outputs | void : Outputs;
|
|
88
115
|
export interface Task<Inputs extends object = Record<string, unknown>, Outputs extends object = Record<string, unknown>, Actions extends object = Record<string, never>, Workflows extends object = TaskContext['workflows']> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oomol-lab/open-flow",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.76",
|
|
4
4
|
"description": "TypeScript contracts and Browser runtime for Open Flow.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"types": "./dist/common/decision.d.ts",
|
|
26
26
|
"import": "./dist/common/decision.js"
|
|
27
27
|
},
|
|
28
|
+
"./http-request": {
|
|
29
|
+
"types": "./dist/common/http-request.d.ts",
|
|
30
|
+
"import": "./dist/common/http-request.js"
|
|
31
|
+
},
|
|
28
32
|
"./openapi": {
|
|
29
33
|
"types": "./dist/common/openapi.d.ts",
|
|
30
34
|
"import": "./dist/common/openapi.js"
|
|
@@ -109,6 +113,10 @@
|
|
|
109
113
|
"types": "./dist/common/runtime-contract.d.ts",
|
|
110
114
|
"import": "./dist/common/runtime-contract.js"
|
|
111
115
|
},
|
|
116
|
+
"./runtime-nodejs-compat": {
|
|
117
|
+
"types": "./dist/common/runtime-nodejs-compat.d.ts",
|
|
118
|
+
"import": "./dist/common/runtime-nodejs-compat.js"
|
|
119
|
+
},
|
|
112
120
|
"./scheduler": {
|
|
113
121
|
"types": "./dist/common/scheduler.d.ts",
|
|
114
122
|
"import": "./dist/common/scheduler.js"
|
|
@@ -298,6 +298,7 @@ For Connector Tasks, independent Code Actions, Agent tools and notifications, an
|
|
|
298
298
|
| Manual, HTTP or scheduled entry | `start`, `webhook`, `cron`: workflow `inputDefs`, HTTP body fields, or schedule. |
|
|
299
299
|
| Workflow failure handler | `error`: published upstream Flows' automatic Run failures; not a node-level catch or a handler for manual Run failures. |
|
|
300
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
|
+
| Single HTTP request | `http-request`: method, parameter modes, authentication, body and response configuration; URL and request values use public inputs. |
|
|
301
302
|
| Fixed HTTP operation | `openapi`: an OpenAPI source, path and method; resolved authentication choices and ports appear in node details. |
|
|
302
303
|
| Reusable constants | `value`: named JSON values and optional output constraints. |
|
|
303
304
|
| 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"}`. |
|
|
@@ -13,17 +13,17 @@ publishing and enabling remain separate actions within the user's authorization.
|
|
|
13
13
|
|
|
14
14
|
## Choose a representation
|
|
15
15
|
|
|
16
|
-
| Source behavior | Open Flow building blocks
|
|
17
|
-
| --------------------------------------------- |
|
|
18
|
-
| Scheduled, webhook or provider event | Cron, Webhook, Poll or Integration Trigger
|
|
19
|
-
| Provider read or write | Connector
|
|
20
|
-
| Field shaping, filtering, aggregation or join | Code with named input/output fields
|
|
21
|
-
| IF or Switch | Condition and named execution branches
|
|
22
|
-
| Prompt plus model and output parser | LLM with template, inputs and `resultSchema`
|
|
23
|
-
| Agent with tools or memory | Agent where its current contract fits
|
|
24
|
-
| HTTP request |
|
|
25
|
-
| Human response or durable pause | Wait or Approval
|
|
26
|
-
| Workflow failure handling | Error Trigger where its scope fits
|
|
16
|
+
| Source behavior | Open Flow building blocks | What determines a good fit |
|
|
17
|
+
| --------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
18
|
+
| Scheduled, webhook or provider event | Cron, Webhook, Poll or Integration Trigger | Schedule/timezone, event payload, delivery and response behavior. |
|
|
19
|
+
| Provider read or write | Connector | Exact operation, input/output shape, account and number of calls. |
|
|
20
|
+
| Field shaping, filtering, aggregation or join | Code with named input/output fields | Explicit collection representation, ordering, keys and empty-input behavior. |
|
|
21
|
+
| IF or Switch | Condition and named execution branches | Predicate, first/all matches, fallback route and data sent onward. |
|
|
22
|
+
| Prompt plus model and output parser | LLM with template, inputs and `resultSchema` | Supported model, result shape and any parser repair behavior. |
|
|
23
|
+
| Agent with tools or memory | Agent where its current contract fits | Tool permissions, state lifetime and how context is supplied. |
|
|
24
|
+
| HTTP request | `http-request`, or `openapi` for a documented operation | Method, parameters, auth, response format and error behavior. |
|
|
25
|
+
| Human response or durable pause | Wait or Approval | Who resumes it, payload, timing, notification and external response lifecycle. |
|
|
26
|
+
| Workflow failure handling | Error Trigger where its scope fits | Which failures trigger it and what failure data it receives. |
|
|
27
27
|
|
|
28
28
|
Use `schema TYPE` and provider discovery for the actual deployment. A node's
|
|
29
29
|
name alone does not establish equivalence. Provider operations can differ even
|
|
@@ -120,10 +120,14 @@ inside URLs, headers, expressions or Code; keep those out of Drafts and reports.
|
|
|
120
120
|
Use supported credential bindings for the selected operation. A missing account
|
|
121
121
|
can leave a Draft incomplete without implying that the action itself is absent.
|
|
122
122
|
|
|
123
|
-
For HTTP Request conversion, `schema
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
For HTTP Request conversion, `schema http-request` describes a single request's
|
|
124
|
+
method, parameter modes, body, authentication and response handling. Bind `url`,
|
|
125
|
+
request parameters and body through public inputs. Authentication inputs require
|
|
126
|
+
variables or upstream outputs. Query arrays become repeated parameters; response
|
|
127
|
+
arrays remain one value. The first version does not follow redirects or support
|
|
128
|
+
pagination, files, OAuth or direct Agent tools. Check these requirements before
|
|
129
|
+
calling the conversion equivalent. Use `schema openapi` when an actual operation
|
|
130
|
+
contract is available; do not invent an API specification to make a request.
|
|
127
131
|
|
|
128
132
|
A provider event may expose an ID where the source expected a full record. A
|
|
129
133
|
Connector read can supply the missing data if it preserves the desired behavior.
|
package/src/base/common/json.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SourceOperation, SourceReferenceOperation } from '../../event-source/common/definition.ts'
|
|
2
|
-
import type { JsonValue } from '../../
|
|
2
|
+
import type { JsonValue } from '../../types/index.ts'
|
|
3
3
|
export type TriggerOperationRequest =
|
|
4
4
|
| { readonly operation: 'sourceReference'; readonly request: SourceReferenceOperation }
|
|
5
5
|
| { readonly operation: 'source'; readonly request: SourceOperation }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CanvasCommand } from '../../canvas/common/commands.ts'
|
|
2
2
|
|
|
3
|
-
import { currentEngineContract } from '../../
|
|
3
|
+
import { currentEngineContract } from '../../runtime/common/engineContract.ts'
|
|
4
4
|
import { workflowContractSchema, workflowReferencesSchema } from '../../workflow/common/workflow.ts'
|
|
5
5
|
export type { CanvasCommand, CanvasCommandSubscriber } from '../../canvas/common/commands.ts'
|
|
6
6
|
import type { LiveDetails } from './liveDetails.ts'
|
|
@@ -9,12 +9,12 @@ import { decodeLiveDetails } from './liveDetails.ts'
|
|
|
9
9
|
export { liveEntries } from './liveDetails.ts'
|
|
10
10
|
export { flowInputDefinitions } from './authoringFields.ts'
|
|
11
11
|
export type { LiveDetails, LiveEntry } from './liveDetails.ts'
|
|
12
|
+
import type { ProviderIconAppearance } from '../../connector/common/providerIconSprite.ts'
|
|
12
13
|
import type { AuthoringRead, AuthoringSearch, AuthoringRequest, AuthoringType } from './authoringSchema.ts'
|
|
13
|
-
import type { ProviderIconAppearance } from './providerIconSprite.ts'
|
|
14
14
|
|
|
15
15
|
import { authoringReadResponse, authoringSearchResponse, authoringEditResponse, authoringCheckResponse } from './authoringSchema.ts'
|
|
16
|
-
export { providerIconAppearance } from '
|
|
17
|
-
export type { ProviderIconAppearance, ProviderIconSprite, ProviderIconSpriteCatalog } from '
|
|
16
|
+
export { providerIconAppearance } from '../../connector/common/providerIconSprite.ts'
|
|
17
|
+
export type { ProviderIconAppearance, ProviderIconSprite, ProviderIconSpriteCatalog } from '../../connector/common/providerIconSprite.ts'
|
|
18
18
|
export { connectorAccess as decodeConnectorAccess, connectorAccessSnapshot as decodeConnectorAccessSnapshot } from './connectorDecoders.ts'
|
|
19
19
|
import type { ProviderAccessIdentity, ProviderAccessReference } from './providerAccess.ts'
|
|
20
20
|
export {
|
|
@@ -35,7 +35,8 @@ export { decodeEventSource, decodeEventSources, type CreateEventSource, type Upd
|
|
|
35
35
|
import type { TriggerCatalogCache } from './triggerCatalog.ts'
|
|
36
36
|
|
|
37
37
|
import { decodeTriggerCatalog } from './triggerCatalog.ts'
|
|
38
|
-
export { decodeTriggerCatalog, searchTriggerKeys, type TriggerCatalog, type TriggerCatalogCache
|
|
38
|
+
export { decodeTriggerCatalog, searchTriggerKeys, type TriggerCatalog, type TriggerCatalogCache } from './triggerCatalog.ts'
|
|
39
|
+
export type { TriggerDisplay } from '../../trigger/providers/localization.ts'
|
|
39
40
|
import type { TriggerConfigOption } from '../../trigger/common/configOptions.ts'
|
|
40
41
|
export type { TriggerConfigOption } from '../../trigger/common/configOptions.ts'
|
|
41
42
|
import type { ResultQuery } from './results.ts'
|
|
@@ -675,6 +676,7 @@ export function decodeRunEvent(value: unknown) {
|
|
|
675
676
|
nodeKind !== 'javascript' &&
|
|
676
677
|
nodeKind !== 'decision' &&
|
|
677
678
|
nodeKind !== 'openapi' &&
|
|
679
|
+
nodeKind !== 'http-request' &&
|
|
678
680
|
nodeKind !== 'llm' &&
|
|
679
681
|
nodeKind !== 'agent' &&
|
|
680
682
|
nodeKind !== 'value' &&
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
renameFlowOutputSources,
|
|
43
43
|
} from '../../flow/common/nodeChanges.ts'
|
|
44
44
|
import { retryConfigurationSchema } from '../../flow/common/retry.ts'
|
|
45
|
+
import { httpRequestTask, httpRequestConfigSchema, httpRequestInputs } from '../../http/common/httpRequest.ts'
|
|
45
46
|
import { withWorkflowTask, workflowTask, workflowSelectionTask, workflowCapability, workflowAgentTool } from '../../workflow/common/workflow.ts'
|
|
46
47
|
import { conditionConfigurationView, prepareConditionConfiguration } from './authoringCondition.ts'
|
|
47
48
|
import { authoringDiagnosticField } from './authoringDiagnosticFields.ts'
|
|
@@ -145,7 +146,10 @@ export function authoringNode(content: RevisionContent, ref: string) {
|
|
|
145
146
|
),
|
|
146
147
|
}
|
|
147
148
|
else if (task.executor.kind == 'workflow') config = { flowId: task.executor.flowId }
|
|
148
|
-
else if (task.executor.kind == '
|
|
149
|
+
else if (task.executor.kind == 'http-request') {
|
|
150
|
+
const { kind: _kind, ...settings } = task.executor
|
|
151
|
+
config = settings
|
|
152
|
+
} else if (task.executor.kind == 'openapi') {
|
|
149
153
|
config = { ...openApiConfigView(task.executor) }
|
|
150
154
|
}
|
|
151
155
|
} else if (node.kind == 'task' && 'moduleId' in node.task) {
|
|
@@ -442,7 +446,8 @@ export async function compileAuthoring(base: RevisionContent, request: Authoring
|
|
|
442
446
|
const timing = record(record(patch.config).autoContinue)
|
|
443
447
|
if (Object.hasOwn(timing, 'kind') && timing.kind != record(record(view.config).autoContinue).kind) record(update.config).autoContinue = timing
|
|
444
448
|
}
|
|
445
|
-
if (type == 'openapi' && Object.hasOwn(record(patch.config), 'authentication'))
|
|
449
|
+
if ((type == 'openapi' || type == 'http-request') && Object.hasOwn(record(patch.config), 'authentication'))
|
|
450
|
+
record(update.config).authentication = record(patch.config).authentication
|
|
446
451
|
for (const path of clear) clearPath(update, path)
|
|
447
452
|
if (typeof update.name != 'string') fail('node.name-required', 'Node name cannot be cleared.')
|
|
448
453
|
const config = authoringConfigurations[type].parse(update.config) as Record<string, unknown>
|
|
@@ -516,7 +521,10 @@ export async function compileAuthoring(base: RevisionContent, request: Authoring
|
|
|
516
521
|
task = { ...before, name: String(update.name), executor: { ...executor, ...config } } as ManagedTaskDefinition
|
|
517
522
|
} else task = await connectorTask(config, String(update.name))
|
|
518
523
|
} else if (type == 'decision') task = decisionTask(config.questions as Parameters<typeof decisionTask>[0], String(update.name))
|
|
519
|
-
else if (type == '
|
|
524
|
+
else if (type == 'http-request') {
|
|
525
|
+
task = httpRequestTask(httpRequestConfigSchema.parse(config), String(update.name), before)
|
|
526
|
+
next = { ...next, inputs: httpRequestInputs(node.inputs, before, task) } as GraphNode
|
|
527
|
+
} else if (type == 'openapi') {
|
|
520
528
|
task = await prepareOpenApiTask(config as AuthoringOpenApiConfig, before, (url) => host.openapi(url), String(update.name), {
|
|
521
529
|
authentication: explicit('authentication'),
|
|
522
530
|
serverUrl: explicit('serverUrl'),
|
|
@@ -766,6 +774,9 @@ export async function compileAuthoring(base: RevisionContent, request: Authoring
|
|
|
766
774
|
case 'connector':
|
|
767
775
|
changes = createManagedTask(identity, await connectorTask(config, name))
|
|
768
776
|
break
|
|
777
|
+
case 'http-request':
|
|
778
|
+
changes = createManagedTask(identity, httpRequestTask(httpRequestConfigSchema.parse(config), name))
|
|
779
|
+
break
|
|
769
780
|
case 'openapi':
|
|
770
781
|
changes = createManagedTask(
|
|
771
782
|
identity,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
createValue,
|
|
12
12
|
createWait,
|
|
13
13
|
} from '../../flow/common/nodeChanges.ts'
|
|
14
|
+
import { httpRequestTask } from '../../http/common/httpRequest.ts'
|
|
14
15
|
import { openApiTask, selectOperation } from '../../openapi/common/openapi.ts'
|
|
15
16
|
|
|
16
17
|
const descriptions = {
|
|
@@ -22,6 +23,7 @@ const descriptions = {
|
|
|
22
23
|
'poll': 'Gmail polling by key; replace CONNECTION_ID with an active Gmail connection.',
|
|
23
24
|
'integration': 'Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.',
|
|
24
25
|
'decision': 'AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running.',
|
|
26
|
+
'http-request': 'A single HTTP request. Bind url and request inputs; outputs are body, statusCode and headers.',
|
|
25
27
|
'openapi': 'A fixed JSON API operation. Replace the example document and URL before running.',
|
|
26
28
|
'connector':
|
|
27
29
|
'A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show. Set connectionId to an empty string to defer account configuration; execution will require an account.',
|
|
@@ -55,6 +57,12 @@ export function authoringExample(name: string): { version: 1; operations: readon
|
|
|
55
57
|
{ name: 'needs_support', type: 'noul', instructions: 'Does the customer need support?' },
|
|
56
58
|
])
|
|
57
59
|
break
|
|
60
|
+
case 'http-request':
|
|
61
|
+
operations = [
|
|
62
|
+
...createManagedTask({ nodeId: 'http' }, httpRequestTask()),
|
|
63
|
+
{ kind: 'graph.node.input.set', nodeId: 'http', handle: 'url', value: { kind: 'value', value: 'https://example.com' } },
|
|
64
|
+
]
|
|
65
|
+
break
|
|
58
66
|
case 'openapi': {
|
|
59
67
|
const document = {
|
|
60
68
|
openapi: '3.1.0',
|
|
@@ -6,9 +6,12 @@ import {
|
|
|
6
6
|
connectorAgentToolSchema,
|
|
7
7
|
workflowAgentToolSchema,
|
|
8
8
|
connectorCapabilitySchema,
|
|
9
|
+
httpCapabilitySchema,
|
|
9
10
|
authoringDefinitionSchemas as definitions,
|
|
10
11
|
} from '../../flow/common/changeSchema.ts'
|
|
11
12
|
import { retryConfigurationSchema, retryNodeTypes } from '../../flow/common/retry.ts'
|
|
13
|
+
import { httpRequestConfigSchema } from '../../http/common/httpRequest.ts'
|
|
14
|
+
import { currentEngineContract, findEngineContract } from '../../runtime/common/engineContract.ts'
|
|
12
15
|
import { authoringLlmConfiguration } from './authoringLlm.ts'
|
|
13
16
|
import { authoringOpenApiSchema } from './authoringOpenApi.ts'
|
|
14
17
|
|
|
@@ -31,6 +34,7 @@ export const authoringTypes = [
|
|
|
31
34
|
'llm',
|
|
32
35
|
'decision',
|
|
33
36
|
'openapi',
|
|
37
|
+
'http-request',
|
|
34
38
|
'condition',
|
|
35
39
|
'value',
|
|
36
40
|
'wait',
|
|
@@ -69,7 +73,9 @@ const agentTool = z.union([
|
|
|
69
73
|
workflowAgentToolSchema.omit({ id: true, inputs: true, outputs: true, revisionId: true }).extend({ inputs: toolSources }).strict(),
|
|
70
74
|
connectorAgentToolSchema.omit({ id: true, inputs: true }).extend({ inputs: toolSources }).strict(),
|
|
71
75
|
])
|
|
72
|
-
const authoringCapabilities = z.array(
|
|
76
|
+
const authoringCapabilities = z.array(
|
|
77
|
+
z.union([connectorCapabilitySchema, z.strictObject({ kind: z.literal('workflow'), name: id, flowId: id }), httpCapabilitySchema]),
|
|
78
|
+
)
|
|
73
79
|
const notification = z.strictObject({
|
|
74
80
|
...definitions.connector.shape,
|
|
75
81
|
messageHandle: id,
|
|
@@ -111,6 +117,7 @@ export const authoringConfigurations = {
|
|
|
111
117
|
'code': z.strictObject({ inputs: inputFields, outputs: outputFields, capabilities: authoringCapabilities.optional() }),
|
|
112
118
|
'connector': definitions.connector.omit({ outputMode: true }).strict(),
|
|
113
119
|
'openapi': authoringOpenApiSchema,
|
|
120
|
+
'http-request': httpRequestConfigSchema,
|
|
114
121
|
'agent': definitions.agent
|
|
115
122
|
.omit({ prompt: true, tools: true })
|
|
116
123
|
.extend({
|
|
@@ -256,6 +263,9 @@ const requestContracts = {
|
|
|
256
263
|
},
|
|
257
264
|
}
|
|
258
265
|
|
|
266
|
+
const codeBuiltins = [...findEngineContract(currentEngineContract)!.builtinModules!].filter((name) => !name.startsWith('node:'))
|
|
267
|
+
const codeGuidance = `Code is an ES module whose default export receives (inputs, context) and returns the business outputs. It may import the Node builtins ${codeBuiltins.join(', ')}, with or without the node: prefix; fs is a fresh in-memory filesystem containing /tmp per execution. require, dynamic import, packages and the http/net builtins are unavailable. To call HTTP APIs, declare their hosts in config.capabilities as {kind: "http", hosts: ["api.example.com", "*.example.org"]} and use context.fetch(url, {method, headers, body}); it returns status, ok, headers.get(), text(), json() and bytes(), does not follow redirects, adds no credentials, and limits bodies to 1 MiB. Prefer an HTTP Request node for a single call without transformation and Connector Actions for services with accounts. context provides inputs, signal, getPrevious(), fetch, actions, workflows, artifact, flowId, runId and blockId. Select workflows through config.capabilities: [{kind: "workflow", flowId, name}]. Call context.workflows.call(name, input) and await its business output. The platform derives input/output types. Refresh a selected workflow tool with node.refresh and tool: its name. Calls obey node and Run time limits.`
|
|
268
|
+
|
|
259
269
|
/** Transport-independent discovery of the same requests the service validates. */
|
|
260
270
|
export function authoringRequestContract(name: string) {
|
|
261
271
|
if (!Object.hasOwn(requestContracts, name)) return undefined
|
|
@@ -296,15 +306,17 @@ export function authoringSchema(kind?: AuthoringType) {
|
|
|
296
306
|
? 'Configure static parameters with node.add.inputs or input.set. Definitions come from the selected Trigger key; execution output and variable sources are unavailable.'
|
|
297
307
|
: kind == 'llm'
|
|
298
308
|
? 'Configure model settings, message templates and history as defaults. Input bindings with the same names override these defaults; named business inputs can be bound directly. Template strings interpolate {{name}}.'
|
|
299
|
-
: kind == '
|
|
300
|
-
? '
|
|
301
|
-
: kind == '
|
|
302
|
-
? 'Select
|
|
303
|
-
: kind == '
|
|
304
|
-
? '
|
|
305
|
-
: kind == '
|
|
306
|
-
? '
|
|
307
|
-
:
|
|
309
|
+
: kind == 'http-request'
|
|
310
|
+
? 'Configure method, query/headers modes and names, bodyFormat, authentication, responseFormat and statusPolicy. Bind url, query.<name>/header.<name> or whole query/headers objects, body and auth.token (Basic: auth.username/auth.password). Credentials accept variables or upstream outputs only. Outputs: body, statusCode, headers. Authentication is replaced as a complete choice.'
|
|
311
|
+
: kind == 'openapi'
|
|
312
|
+
? 'Select an operation; the tool resolves its ports and authentication. Read authenticationChoices from node details. authentication is replaced as a complete choice. Bind advertised credentials through inputs.'
|
|
313
|
+
: kind == 'workflow'
|
|
314
|
+
? 'Select another workflow with config.flowId. A workflow cannot call itself, including in a disconnected node. Owned unpublished or unavailable targets may be saved as incomplete drafts. Use node.refresh to load the current published interface.'
|
|
315
|
+
: kind == 'agent'
|
|
316
|
+
? 'Tools accept Connector Actions or {kind: "workflow", flowId, name, description, approval, inputs}. Workflow parameter sources use model, input or value. The platform derives the interface. Refresh a workflow tool with node.refresh and tool: its name.'
|
|
317
|
+
: kind == 'code'
|
|
318
|
+
? codeGuidance
|
|
319
|
+
: 'Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.',
|
|
308
320
|
example: {
|
|
309
321
|
op: 'node.add',
|
|
310
322
|
as: 'step',
|
|
@@ -312,15 +324,16 @@ export function authoringSchema(kind?: AuthoringType) {
|
|
|
312
324
|
name: 'Step',
|
|
313
325
|
...((
|
|
314
326
|
{
|
|
315
|
-
start: { config: { inputDefs: {} } },
|
|
316
|
-
outputs: { config: { outputDefs: {} } },
|
|
317
|
-
workflow: { config: { flowId: '<Flow ID>' } },
|
|
318
|
-
connector: { config: { action: '<Action ID>', connectionId: '<Connection ID>' } },
|
|
319
|
-
poll: { config: { key: '<Trigger key>', schedule: [{ type: 'every', unit: 'minute', value: 5 }] } },
|
|
320
|
-
integration: { config: { key: '<Trigger key>' } },
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
327
|
+
'start': { config: { inputDefs: {} } },
|
|
328
|
+
'outputs': { config: { outputDefs: {} } },
|
|
329
|
+
'workflow': { config: { flowId: '<Flow ID>' } },
|
|
330
|
+
'connector': { config: { action: '<Action ID>', connectionId: '<Connection ID>' } },
|
|
331
|
+
'poll': { config: { key: '<Trigger key>', schedule: [{ type: 'every', unit: 'minute', value: 5 }] } },
|
|
332
|
+
'integration': { config: { key: '<Trigger key>' } },
|
|
333
|
+
'http-request': { config: {}, inputs: { url: { kind: 'value', value: 'https://example.com' } } },
|
|
334
|
+
'openapi': { config: { sourceUrl: 'https://example.com/openapi.json', path: '/items', method: 'get' } },
|
|
335
|
+
'code': { code: 'export default ({value}) => ({result:value})', inputs: { value: { kind: 'value', value: 'Hello' } } },
|
|
336
|
+
'condition': {
|
|
324
337
|
config: {
|
|
325
338
|
match: 'first',
|
|
326
339
|
branches: [
|
|
@@ -335,15 +348,15 @@ export function authoringSchema(kind?: AuthoringType) {
|
|
|
335
348
|
],
|
|
336
349
|
},
|
|
337
350
|
},
|
|
338
|
-
value: { config: { values: { threshold: 100, region: 'EU' } } },
|
|
339
|
-
webhook: { config: { method: 'POST', body: { orderId: { schema: { type: 'string' }, nullable: false } } } },
|
|
340
|
-
wait: { prompt: 'Continue processing this order?', inputs: { order: { kind: 'value', value: { orderId: 'A-1' } } } },
|
|
341
|
-
approval: { prompt: 'Approve this order?', inputs: { order: { kind: 'value', value: { orderId: 'A-1' } } } },
|
|
342
|
-
llm: {
|
|
351
|
+
'value': { config: { values: { threshold: 100, region: 'EU' } } },
|
|
352
|
+
'webhook': { config: { method: 'POST', body: { orderId: { schema: { type: 'string' }, nullable: false } } } },
|
|
353
|
+
'wait': { prompt: 'Continue processing this order?', inputs: { order: { kind: 'value', value: { orderId: 'A-1' } } } },
|
|
354
|
+
'approval': { prompt: 'Approve this order?', inputs: { order: { kind: 'value', value: { orderId: 'A-1' } } } },
|
|
355
|
+
'llm': {
|
|
343
356
|
config: { model: { model: 'deepseek-v4-flash' }, template: [{ role: 'user', content: 'Summarize {{order}}.' }] },
|
|
344
357
|
inputs: { order: { kind: 'value', value: { orderId: 'A-1', total: 42 } } },
|
|
345
358
|
},
|
|
346
|
-
agent: {
|
|
359
|
+
'agent': {
|
|
347
360
|
config: {
|
|
348
361
|
model: 'deepseek-v4-flash',
|
|
349
362
|
},
|
|
@@ -17,7 +17,7 @@ export type AuthoringCapability = Exclude<TaskCapability, WorkflowCapability> |
|
|
|
17
17
|
export type WorkflowLookup = (flowId: string) => Promise<WorkflowContract | WorkflowCandidate>
|
|
18
18
|
|
|
19
19
|
interface ToolIdentity {
|
|
20
|
-
readonly kind?:
|
|
20
|
+
readonly kind?: string
|
|
21
21
|
readonly name?: string
|
|
22
22
|
readonly flowId?: string
|
|
23
23
|
}
|
|
@@ -4,8 +4,8 @@ import type { ConnectorConnection, CreateEventSource, ResultInfo, PollTriggerTes
|
|
|
4
4
|
import type { ProviderAccessIdentity } from './providerAccess.ts'
|
|
5
5
|
|
|
6
6
|
import { dequal } from 'dequal/lite'
|
|
7
|
-
import { currentEngineContract as engineContract } from '../../execution/common/engineContract.ts'
|
|
8
7
|
import { upgradeRevisionContent } from '../../flow/common/change.ts'
|
|
8
|
+
import { currentEngineContract as engineContract } from '../../runtime/common/engineContract.ts'
|
|
9
9
|
import { ControlClient, decodeRunEvent } from './api.ts'
|
|
10
10
|
import { allConnectorConnectionsQuery } from './connectorQueries.ts'
|
|
11
11
|
|
|
@@ -14,10 +14,10 @@ import type {
|
|
|
14
14
|
ProviderAccessBindingCandidate,
|
|
15
15
|
} from './api.ts'
|
|
16
16
|
|
|
17
|
+
import { providerIconAppearance } from '../../connector/common/providerIconSprite.ts'
|
|
17
18
|
import { exact, requiredFields, integer, invalidResponse, jsonValue, record, string } from './decoding.ts'
|
|
18
19
|
import { ApiError } from './errors.ts'
|
|
19
20
|
import { parseProviderAccessSource } from './providerAccess.ts'
|
|
20
|
-
import { providerIconAppearance } from './providerIconSprite.ts'
|
|
21
21
|
|
|
22
22
|
export function leinaBots(value: unknown): readonly LeinaBot[] {
|
|
23
23
|
const source = record(value)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
+
import { eventSourceViewSchema } from '../../event-source/common/view.ts'
|
|
2
3
|
|
|
3
4
|
const id = z.string().min(1).max(256)
|
|
4
5
|
const eventType = z.string().regex(/^[a-z][a-z0-9_.:]{0,127}$/)
|
|
@@ -10,45 +11,17 @@ const eventSourceSchema = z.object({
|
|
|
10
11
|
revision: z.int().positive(),
|
|
11
12
|
name,
|
|
12
13
|
provider: z.enum(['feishu', 'feishu_app_bot', 'slackbot', 'intercom', 'sentry', 'zoom', 'fireflies', 'jira']),
|
|
13
|
-
|
|
14
|
-
workspaceId: id.optional(),
|
|
15
|
-
installationId: id.optional(),
|
|
16
|
-
organizationId: id.optional(),
|
|
17
|
-
projectId: id.optional(),
|
|
18
|
-
projectKey: id.optional(),
|
|
19
|
-
subscriptionStatus: z.enum(['idle', 'pending', 'ready', 'error']).optional(),
|
|
20
|
-
lastError: z.string().optional(),
|
|
21
|
-
signingSecretConfigured: z.boolean().optional(),
|
|
14
|
+
...eventSourceViewSchema.shape,
|
|
22
15
|
connectionId: id,
|
|
23
16
|
teamId: id.nullable(),
|
|
24
17
|
enabled: z.boolean(),
|
|
25
18
|
eventTypes: z.array(eventType),
|
|
26
|
-
manageSubscriptions: z.boolean().nullable(),
|
|
27
|
-
verificationTokenConfigured: z.boolean().nullable(),
|
|
28
|
-
encryptKeyConfigured: z.boolean().nullable(),
|
|
29
19
|
endpointUrl: z.string().nullable(),
|
|
30
|
-
verifiedAt: z.string().nullable(),
|
|
31
20
|
lastReceivedAt: z.string().nullable(),
|
|
32
21
|
updatedAt: z.string(),
|
|
33
22
|
consumers: z.array(z.object({ flowId: id, flowName: z.string(), triggerNodeId: id })),
|
|
34
23
|
})
|
|
35
24
|
|
|
36
|
-
export const eventSourceViewSchema = eventSourceSchema.pick({
|
|
37
|
-
appId: true,
|
|
38
|
-
workspaceId: true,
|
|
39
|
-
installationId: true,
|
|
40
|
-
organizationId: true,
|
|
41
|
-
projectId: true,
|
|
42
|
-
projectKey: true,
|
|
43
|
-
subscriptionStatus: true,
|
|
44
|
-
lastError: true,
|
|
45
|
-
signingSecretConfigured: true,
|
|
46
|
-
manageSubscriptions: true,
|
|
47
|
-
verificationTokenConfigured: true,
|
|
48
|
-
encryptKeyConfigured: true,
|
|
49
|
-
verifiedAt: true,
|
|
50
|
-
})
|
|
51
|
-
|
|
52
25
|
export interface CreateFeishuEventSource {
|
|
53
26
|
readonly kind?: 'feishu'
|
|
54
27
|
readonly version: 1
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import type { TriggerKeySnapshot } from '../../flow/common/change.ts'
|
|
2
2
|
import type { UiLanguage } from '../../localization/common/languages.ts'
|
|
3
|
+
import type { TriggerDisplay } from '../../trigger/providers/localization.ts'
|
|
3
4
|
import type { TriggerKeySummary } from './api.ts'
|
|
4
5
|
|
|
5
6
|
import { isUiLanguage } from '../../localization/common/languages.ts'
|
|
6
7
|
import { exact, requiredFields, invalidResponse, record, string } from './decoding.ts'
|
|
7
8
|
import { triggerKey } from './triggerDecoders.ts'
|
|
8
9
|
|
|
9
|
-
export interface TriggerDisplay {
|
|
10
|
-
readonly configInputs: Readonly<Record<string, string>>
|
|
11
|
-
readonly configInputLabels: Readonly<Record<string, string>>
|
|
12
|
-
readonly displayName: string
|
|
13
|
-
readonly description: string
|
|
14
|
-
readonly outputs: Readonly<Record<string, string>>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
10
|
export interface TriggerCatalog {
|
|
18
11
|
readonly version: 3
|
|
19
12
|
readonly locale: UiLanguage
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InputPort, JsonValue,
|
|
1
|
+
import type { InputPort, JsonValue, ManagedTaskDefinitionOf, Port, TaskExecutor } from '../../flow/common/model.ts'
|
|
2
2
|
|
|
3
3
|
import { dequal } from 'dequal/lite'
|
|
4
4
|
import { matchesSchema } from '../../flow/common/schema.ts'
|
|
@@ -18,6 +18,10 @@ export interface DecisionIssue {
|
|
|
18
18
|
readonly message: string
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function isDecisionExecutor(executor: TaskExecutor): executor is DecisionExecutor {
|
|
22
|
+
return executor.kind === 'decision'
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
export const decisionModel = 'typesafe/jev'
|
|
22
26
|
export const decisionLimits = { choice: 255, score: 10 } as const
|
|
23
27
|
|
|
@@ -34,8 +38,8 @@ export function limitDecisionQuestions(questions: readonly DecisionQuestion[]):
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
/** Loading an oversized task also updates its previously generated output schemas. */
|
|
37
|
-
export function limitDecisionTask(task:
|
|
38
|
-
if (task.executor
|
|
41
|
+
export function limitDecisionTask<Task extends ManagedTaskDefinitionOf<TaskExecutor>>(task: Task): Task {
|
|
42
|
+
if (!isDecisionExecutor(task.executor)) return task
|
|
39
43
|
const original = task.executor.questions
|
|
40
44
|
const questions = limitDecisionQuestions(original)
|
|
41
45
|
if (questions === original) return task
|
|
@@ -45,7 +49,8 @@ export function limitDecisionTask(task: ManagedTaskDefinition): ManagedTaskDefin
|
|
|
45
49
|
if (index < 0 || original[index] === questions[index] || !dequal(port.jsonSchema, answerSchema(original[index]!))) return port
|
|
46
50
|
return { ...port, jsonSchema: decisionAnswerSchema(questions[index]!) }
|
|
47
51
|
})
|
|
48
|
-
|
|
52
|
+
// Only the decision executor and its derived outputs change, so the task keeps its own type.
|
|
53
|
+
return { ...task, executor: { ...task.executor, questions }, outputs } as Task
|
|
49
54
|
}
|
|
50
55
|
export const decisionStateSchema: JsonValue = { type: ['string', 'object', 'array'] }
|
|
51
56
|
const probability: JsonValue = { type: 'number', minimum: 0, maximum: 1 }
|
|
@@ -102,7 +107,10 @@ function answerSchema(question: DecisionQuestion): JsonValue {
|
|
|
102
107
|
return { type: 'object', properties, required: Object.keys(properties) }
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
export function decisionTask(
|
|
110
|
+
export function decisionTask(
|
|
111
|
+
questions: readonly DecisionQuestion[] = [defaultDecisionQuestion()],
|
|
112
|
+
name = 'AI Decision',
|
|
113
|
+
): ManagedTaskDefinitionOf<DecisionExecutor> {
|
|
106
114
|
questions = limitDecisionQuestions(questions)
|
|
107
115
|
const inputs: InputPort[] = [
|
|
108
116
|
{ handle: 'target', description: 'Text, object, or array to evaluate across all questions.', jsonSchema: decisionStateSchema, nullable: false },
|
|
@@ -111,9 +119,9 @@ export function decisionTask(questions: readonly DecisionQuestion[] = [defaultDe
|
|
|
111
119
|
return { name, executor: { kind: 'decision', questions }, inputs, outputs }
|
|
112
120
|
}
|
|
113
121
|
|
|
114
|
-
export function decisionTaskIssues(task:
|
|
122
|
+
export function decisionTaskIssues(task: ManagedTaskDefinitionOf<TaskExecutor>): readonly DecisionIssue[] {
|
|
115
123
|
task = limitDecisionTask(task)
|
|
116
|
-
if (task.executor
|
|
124
|
+
if (!isDecisionExecutor(task.executor)) return []
|
|
117
125
|
const expected = decisionTask(task.executor.questions, task.name)
|
|
118
126
|
return [
|
|
119
127
|
...decisionQuestionIssues(task.executor.questions),
|