@oomol-lab/open-flow 0.1.0-beta.80 → 0.1.0-beta.81
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/dist/browser/{flowChanges-pFjPHU5k.js → flowChanges-CFj5pL4Y.js} +137 -8
- package/dist/browser/{flowWorkspace-CRlqc403.js → flowWorkspace-BeQaeJ3e.js} +6 -122
- package/dist/browser/preview.js +141 -128
- package/dist/browser/workbench.js +24 -8
- package/dist/command/index.js +3 -3
- package/dist/common/control-requests.js +19 -3
- package/dist/common/flow-authoring.js +19 -3
- package/dist/common/flow-semantics.js +24 -7
- package/package.json +1 -1
- package/src/connector/common/actionContract.ts +26 -0
- package/src/flow/common/edgeChanges.ts +9 -6
- package/src/flow/common/semantics.ts +11 -8
|
@@ -15393,6 +15393,21 @@ function applyFlowChanges(content, operations) {
|
|
|
15393
15393
|
});
|
|
15394
15394
|
}
|
|
15395
15395
|
//#endregion
|
|
15396
|
+
//#region src/connector/common/actionContract.ts
|
|
15397
|
+
/** These rules also apply to existing Revision snapshots without a catalog lookup. */
|
|
15398
|
+
var connectorActionContracts = { "leina.send_notification": {
|
|
15399
|
+
inputConstraints: [{
|
|
15400
|
+
handle: "leinaId",
|
|
15401
|
+
jsonSchema: {
|
|
15402
|
+
type: "string",
|
|
15403
|
+
pattern: "\\S"
|
|
15404
|
+
},
|
|
15405
|
+
code: "leina.robot-required",
|
|
15406
|
+
message: "Select a Leina robot or bind its identifier to an input source."
|
|
15407
|
+
}],
|
|
15408
|
+
pendingMessageInput: "message"
|
|
15409
|
+
} };
|
|
15410
|
+
//#endregion
|
|
15396
15411
|
//#region src/flow/common/edgeChanges.ts
|
|
15397
15412
|
function connect(content, edge) {
|
|
15398
15413
|
const selected = content.document.graph;
|
|
@@ -15403,11 +15418,12 @@ function connect(content, edge) {
|
|
|
15403
15418
|
}];
|
|
15404
15419
|
const source = selected.nodes[edge.source];
|
|
15405
15420
|
const target = selected.nodes[edge.target];
|
|
15406
|
-
|
|
15421
|
+
const messageInput = target?.kind == "task" && "executor" in target.task && target.task.executor.kind == "connector" ? connectorActionContracts[target.task.executor.action]?.pendingMessageInput : void 0;
|
|
15422
|
+
if (edge.sourceHandle == "pending" && (source?.kind == "approval" || source?.kind == "wait") && target?.kind == "task" && messageInput != null && (target.inputs[messageInput] == null || target.inputs[messageInput]?.kind == "unset")) changes.push({
|
|
15407
15423
|
kind: "graph.node.input.set",
|
|
15408
15424
|
nodeId: edge.target,
|
|
15409
|
-
handle:
|
|
15410
|
-
before: target.inputs
|
|
15425
|
+
handle: messageInput,
|
|
15426
|
+
before: target.inputs[messageInput],
|
|
15411
15427
|
value: {
|
|
15412
15428
|
kind: "sources",
|
|
15413
15429
|
sources: [{
|
|
@@ -57,6 +57,21 @@ function dequal(foo, bar) {
|
|
|
57
57
|
return foo !== foo && bar !== bar;
|
|
58
58
|
}
|
|
59
59
|
//#endregion
|
|
60
|
+
//#region src/connector/common/actionContract.ts
|
|
61
|
+
/** These rules also apply to existing Revision snapshots without a catalog lookup. */
|
|
62
|
+
var connectorActionContracts = { "leina.send_notification": {
|
|
63
|
+
inputConstraints: [{
|
|
64
|
+
handle: "leinaId",
|
|
65
|
+
jsonSchema: {
|
|
66
|
+
type: "string",
|
|
67
|
+
pattern: "\\S"
|
|
68
|
+
},
|
|
69
|
+
code: "leina.robot-required",
|
|
70
|
+
message: "Select a Leina robot or bind its identifier to an input source."
|
|
71
|
+
}],
|
|
72
|
+
pendingMessageInput: "message"
|
|
73
|
+
} };
|
|
74
|
+
//#endregion
|
|
60
75
|
//#region src/flow/common/edgeChanges.ts
|
|
61
76
|
function connect(content, edge) {
|
|
62
77
|
const selected = content.document.graph;
|
|
@@ -67,11 +82,12 @@ function connect(content, edge) {
|
|
|
67
82
|
}];
|
|
68
83
|
const source = selected.nodes[edge.source];
|
|
69
84
|
const target = selected.nodes[edge.target];
|
|
70
|
-
|
|
85
|
+
const messageInput = target?.kind == "task" && "executor" in target.task && target.task.executor.kind == "connector" ? connectorActionContracts[target.task.executor.action]?.pendingMessageInput : void 0;
|
|
86
|
+
if (edge.sourceHandle == "pending" && (source?.kind == "approval" || source?.kind == "wait") && target?.kind == "task" && messageInput != null && (target.inputs[messageInput] == null || target.inputs[messageInput]?.kind == "unset")) changes.push({
|
|
71
87
|
kind: "graph.node.input.set",
|
|
72
88
|
nodeId: edge.target,
|
|
73
|
-
handle:
|
|
74
|
-
before: target.inputs
|
|
89
|
+
handle: messageInput,
|
|
90
|
+
before: target.inputs[messageInput],
|
|
75
91
|
value: {
|
|
76
92
|
kind: "sources",
|
|
77
93
|
sources: [{
|
|
@@ -22,6 +22,21 @@ function dequal(foo, bar) {
|
|
|
22
22
|
return foo !== foo && bar !== bar;
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
|
+
//#region src/connector/common/actionContract.ts
|
|
26
|
+
/** These rules also apply to existing Revision snapshots without a catalog lookup. */
|
|
27
|
+
var connectorActionContracts = { "leina.send_notification": {
|
|
28
|
+
inputConstraints: [{
|
|
29
|
+
handle: "leinaId",
|
|
30
|
+
jsonSchema: {
|
|
31
|
+
type: "string",
|
|
32
|
+
pattern: "\\S"
|
|
33
|
+
},
|
|
34
|
+
code: "leina.robot-required",
|
|
35
|
+
message: "Select a Leina robot or bind its identifier to an input source."
|
|
36
|
+
}],
|
|
37
|
+
pendingMessageInput: "message"
|
|
38
|
+
} };
|
|
39
|
+
//#endregion
|
|
25
40
|
//#region ../../node_modules/.bun/@cfworker+json-schema@4.1.1/node_modules/@cfworker/json-schema/dist/esm/deep-compare-strict.js
|
|
26
41
|
function deepCompareStrict(a, b) {
|
|
27
42
|
const typeofa = typeof a;
|
|
@@ -25089,15 +25104,17 @@ async function validateFlow(revision, engine) {
|
|
|
25089
25104
|
message,
|
|
25090
25105
|
path: `/document/graph/nodes/${nodeId}/task/executor`
|
|
25091
25106
|
});
|
|
25092
|
-
if (task.executor.kind == "connector"
|
|
25093
|
-
const mapping = node.inputs.
|
|
25094
|
-
|
|
25095
|
-
|
|
25096
|
-
|
|
25107
|
+
if (task.executor.kind == "connector") for (const constraint of connectorActionContracts[task.executor.action]?.inputConstraints ?? []) {
|
|
25108
|
+
const mapping = node.inputs[constraint.handle];
|
|
25109
|
+
if (mapping?.kind == "sources" && mapping.sources.length > 0) continue;
|
|
25110
|
+
const value = inputValue(mapping, nodeInputPorts(node)[constraint.handle]?.value);
|
|
25111
|
+
if (value !== void 0 && matchesSchema(value, constraint.jsonSchema)) continue;
|
|
25112
|
+
checked.diagnostics.push({
|
|
25113
|
+
code: constraint.code,
|
|
25097
25114
|
column: 0,
|
|
25098
25115
|
line: 1,
|
|
25099
|
-
message:
|
|
25100
|
-
path: `/document/graph/nodes/${nodeId}/inputs
|
|
25116
|
+
message: constraint.message,
|
|
25117
|
+
path: `/document/graph/nodes/${nodeId}/inputs/${constraint.handle}`
|
|
25101
25118
|
});
|
|
25102
25119
|
}
|
|
25103
25120
|
if (task.executor.kind == "connector" && task.executor.action.length == 0) checked.diagnostics.push({
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { JsonValue } from '../../types/index.ts'
|
|
2
|
+
|
|
3
|
+
interface ConnectorActionContract {
|
|
4
|
+
readonly inputConstraints?: readonly {
|
|
5
|
+
readonly handle: string
|
|
6
|
+
readonly jsonSchema: JsonValue
|
|
7
|
+
readonly code: string
|
|
8
|
+
readonly message: string
|
|
9
|
+
}[]
|
|
10
|
+
readonly pendingMessageInput?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** These rules also apply to existing Revision snapshots without a catalog lookup. */
|
|
14
|
+
export const connectorActionContracts: Readonly<Record<string, ConnectorActionContract | undefined>> = {
|
|
15
|
+
'leina.send_notification': {
|
|
16
|
+
inputConstraints: [
|
|
17
|
+
{
|
|
18
|
+
handle: 'leinaId',
|
|
19
|
+
jsonSchema: { type: 'string', pattern: '\\S' },
|
|
20
|
+
code: 'leina.robot-required',
|
|
21
|
+
message: 'Select a Leina robot or bind its identifier to an input source.',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
pendingMessageInput: 'message',
|
|
25
|
+
},
|
|
26
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ChangeOperation, GraphEdge, RevisionContent } from './change.ts'
|
|
2
2
|
|
|
3
3
|
import { dequal } from 'dequal/lite'
|
|
4
|
+
import { connectorActionContracts } from '../../connector/common/actionContract.ts'
|
|
4
5
|
|
|
5
6
|
export function connect(content: RevisionContent, edge: GraphEdge): readonly ChangeOperation[] {
|
|
6
7
|
const selected = content.document.graph
|
|
@@ -8,20 +9,22 @@ export function connect(content: RevisionContent, edge: GraphEdge): readonly Cha
|
|
|
8
9
|
const changes: ChangeOperation[] = [{ edge, kind: 'graph.edge.connect' }]
|
|
9
10
|
const source = selected.nodes[edge.source]
|
|
10
11
|
const target = selected.nodes[edge.target]
|
|
12
|
+
const messageInput =
|
|
13
|
+
target?.kind == 'task' && 'executor' in target.task && target.task.executor.kind == 'connector'
|
|
14
|
+
? connectorActionContracts[target.task.executor.action]?.pendingMessageInput
|
|
15
|
+
: undefined
|
|
11
16
|
if (
|
|
12
17
|
edge.sourceHandle == 'pending' &&
|
|
13
18
|
(source?.kind == 'approval' || source?.kind == 'wait') &&
|
|
14
19
|
target?.kind == 'task' &&
|
|
15
|
-
|
|
16
|
-
target.
|
|
17
|
-
target.task.executor.action == 'leina.send_notification' &&
|
|
18
|
-
(target.inputs.message == null || target.inputs.message.kind == 'unset')
|
|
20
|
+
messageInput != null &&
|
|
21
|
+
(target.inputs[messageInput] == null || target.inputs[messageInput]?.kind == 'unset')
|
|
19
22
|
) {
|
|
20
23
|
changes.push({
|
|
21
24
|
kind: 'graph.node.input.set',
|
|
22
25
|
nodeId: edge.target,
|
|
23
|
-
handle:
|
|
24
|
-
before: target.inputs
|
|
26
|
+
handle: messageInput,
|
|
27
|
+
before: target.inputs[messageInput],
|
|
25
28
|
value: { kind: 'sources', sources: [{ kind: 'node', nodeId: edge.source, output: 'pending', field: 'message' }] },
|
|
26
29
|
})
|
|
27
30
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { dequal } from 'dequal/lite'
|
|
2
|
+
import { connectorActionContracts } from '../../connector/common/actionContract.ts'
|
|
2
3
|
import { decisionTaskIssues } from '../../decision/common/decision.ts'
|
|
3
4
|
import { httpRequestIssues, httpAuthHandles, httpRequestTask, httpRequestUrl } from '../../http/common/httpRequest.ts'
|
|
4
5
|
import { openApiIssues, authHandles } from '../../openapi/common/openapi.ts'
|
|
@@ -22,7 +23,7 @@ import { canonicalJsonBytes, canonicalModule, canonicalRevisionGraph, digestByte
|
|
|
22
23
|
import { nodeInputPorts, validateFlowGraph } from './graph.ts'
|
|
23
24
|
import { inputValue } from './inputValue.ts'
|
|
24
25
|
import { compareDiagnostics, validateModuleGraph } from './modules.ts'
|
|
25
|
-
import { hasRetiredRef } from './schema.ts'
|
|
26
|
+
import { hasRetiredRef, matchesSchema } from './schema.ts'
|
|
26
27
|
export { availableOutputs, graphOrder, nodeInputPorts } from './graph.ts'
|
|
27
28
|
export { validateModules } from './modules.ts'
|
|
28
29
|
export { matchesSchema, schemaValidationErrors, variableInputCompatible } from './schema.ts'
|
|
@@ -349,16 +350,18 @@ export async function validateFlow(revision: RevisionContent, engine: EngineCont
|
|
|
349
350
|
for (const message of agentConfigIssues(task)) {
|
|
350
351
|
checked.diagnostics.push({ code: 'agent.config-invalid', column: 0, line: 1, message, path: `/document/graph/nodes/${nodeId}/task/executor` })
|
|
351
352
|
}
|
|
352
|
-
if (task.executor.kind == 'connector'
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
353
|
+
if (task.executor.kind == 'connector') {
|
|
354
|
+
for (const constraint of connectorActionContracts[task.executor.action]?.inputConstraints ?? []) {
|
|
355
|
+
const mapping = node.inputs[constraint.handle]
|
|
356
|
+
if (mapping?.kind == 'sources' && mapping.sources.length > 0) continue
|
|
357
|
+
const value = inputValue(mapping, nodeInputPorts(node)[constraint.handle]?.value)
|
|
358
|
+
if (value !== undefined && matchesSchema(value, constraint.jsonSchema)) continue
|
|
356
359
|
checked.diagnostics.push({
|
|
357
|
-
code:
|
|
360
|
+
code: constraint.code,
|
|
358
361
|
column: 0,
|
|
359
362
|
line: 1,
|
|
360
|
-
message:
|
|
361
|
-
path: `/document/graph/nodes/${nodeId}/inputs
|
|
363
|
+
message: constraint.message,
|
|
364
|
+
path: `/document/graph/nodes/${nodeId}/inputs/${constraint.handle}`,
|
|
362
365
|
})
|
|
363
366
|
}
|
|
364
367
|
}
|