@oomol-lab/open-flow 0.1.0-beta.80 → 0.1.0-beta.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +35 -0
  2. package/dist/browser/{FlowCanvas-CrsiDHK8.js → FlowCanvas-Dew2fmoT.js} +55 -274
  3. package/dist/browser/{createResourceDialog-CS3u9ga9.js → createResourceDialog-bdOJa5Zk.js} +2 -1
  4. package/dist/browser/{exportPng-BOPfjeEi.js → exportPng-Cjdb6COo.js} +2 -2
  5. package/dist/browser/{flowChanges-pFjPHU5k.js → flowChanges-URBEd4DI.js} +2719 -78
  6. package/dist/browser/{flowWorkspace-CRlqc403.js → flowWorkspace-BlXx-yAn.js} +445 -2699
  7. package/dist/browser/{markdownContent-CAG_CQfH.js → markdownContent-D8G_oNOe.js} +18 -41
  8. package/dist/browser/{markdownContent-frwDfQQU.js → markdownContent-IS8xXDoc.js} +18 -40
  9. package/dist/browser/preview.css +88 -80
  10. package/dist/browser/preview.js +291 -188
  11. package/dist/browser/ui.css +8 -0
  12. package/dist/browser/{dist-CHwj9BhV.js → videoLink-NAWDmBtf.js} +35 -1
  13. package/dist/browser/workbench-contract.d.ts +6 -0
  14. package/dist/browser/workbench.css +259 -251
  15. package/dist/browser/workbench.d.ts +2 -0
  16. package/dist/browser/workbench.js +311 -143
  17. package/dist/browser/{ContentIcon-CMn0c-kl.js → wrapLayout-DZvW9dBs.js} +4397 -4152
  18. package/dist/command/index.js +43 -41
  19. package/dist/common/authoring.d.ts +1 -1
  20. package/dist/common/control-api-conformance.js +306 -2
  21. package/dist/common/control-api.d.ts +20 -0
  22. package/dist/common/control-api.js +306 -4
  23. package/dist/common/control-requests.d.ts +3 -5
  24. package/dist/common/control-requests.js +24 -10
  25. package/dist/common/flow-authoring.js +19 -3
  26. package/dist/common/flow-encoding.d.ts +1 -0
  27. package/dist/common/flow-encoding.js +167 -1
  28. package/dist/common/flow-semantics.js +44 -7
  29. package/dist/common/flow-workflowBundle.d.ts +27 -0
  30. package/dist/common/flow-workflowFile.d.ts +2 -0
  31. package/dist/common/flow-workflowReferences.d.ts +4 -0
  32. package/dist/common/mcp.d.ts +2 -0
  33. package/dist/common/mcp.js +312 -4
  34. package/dist/render/browser/licenses.md +4047 -0
  35. package/dist/render/browser/runtime.css +14877 -0
  36. package/dist/render/browser/runtime.js +266765 -0
  37. package/dist/render/common/png.d.ts +24 -0
  38. package/dist/render/node/index.d.ts +11 -0
  39. package/dist/render/node/index.js +9491 -0
  40. package/dist/render/node/licenses.md +75 -0
  41. package/package.json +12 -2
  42. package/src/connector/common/actionContract.ts +26 -0
  43. package/src/control/common/api.ts +50 -0
  44. package/src/control/common/flowDecoders.ts +2 -0
  45. package/src/control/common/mcp.ts +4 -4
  46. package/src/control/common/requests.ts +12 -1
  47. package/src/flow/common/edgeChanges.ts +9 -6
  48. package/src/flow/common/encoding.ts +1 -0
  49. package/src/flow/common/semantics.ts +11 -8
  50. package/src/flow/common/workflowBundle.ts +117 -0
  51. package/src/flow/common/workflowFile.ts +4 -0
  52. package/src/flow/common/workflowReferences.ts +20 -0
@@ -9856,6 +9856,8 @@ var envelope = strictObject({
9856
9856
  kind: literal("open-flow-workflow"),
9857
9857
  version: literal(1),
9858
9858
  name: string().optional(),
9859
+ icon: string().optional(),
9860
+ description: string().optional(),
9859
9861
  content: unknown(),
9860
9862
  presentation: record$1(string(), json$1()).optional()
9861
9863
  });
@@ -9936,6 +9938,170 @@ function workflowNameFromFile(name) {
9936
9938
  return name.replace(/(?:\.openflow)?\.json$/i, "");
9937
9939
  }
9938
9940
  //#endregion
9941
+ //#region src/flow/common/workflowReferences.ts
9942
+ /** Rewrite only declared workflow identities, preserving business values and saved ports. */
9943
+ function mapNodeWorkflowTargets(node, map) {
9944
+ if (node.kind != "task") return node;
9945
+ const task = node.task;
9946
+ if ("moduleId" in task) return task.capabilities?.some((item) => item.kind == "workflow") ? {
9947
+ ...node,
9948
+ task: {
9949
+ ...task,
9950
+ capabilities: task.capabilities.map((item) => item.kind == "workflow" ? Object.assign({}, item, map(item)) : item)
9951
+ }
9952
+ } : node;
9953
+ const executor = task.executor;
9954
+ if (executor.kind == "workflow") return {
9955
+ ...node,
9956
+ task: {
9957
+ ...task,
9958
+ executor: {
9959
+ ...executor,
9960
+ ...map(executor)
9961
+ }
9962
+ }
9963
+ };
9964
+ if (executor.kind == "agent") return {
9965
+ ...node,
9966
+ task: {
9967
+ ...task,
9968
+ executor: {
9969
+ ...executor,
9970
+ tools: executor.tools.map((tool) => tool.kind == "workflow" ? Object.assign({}, tool, map(tool)) : tool)
9971
+ }
9972
+ }
9973
+ };
9974
+ return node;
9975
+ }
9976
+ /** Workflow declarations share discovery across authoring, admission and resource indexing. */
9977
+ function nodeWorkflowReferences(node) {
9978
+ if (node.kind != "task") return [];
9979
+ if ("moduleId" in node.task) return (node.task.capabilities ?? []).flatMap((item, index) => item.kind == "workflow" ? [{
9980
+ target: item,
9981
+ path: `task/capabilities/${index}`,
9982
+ tool: item.name
9983
+ }] : []);
9984
+ if (node.task.executor.kind == "workflow") return [{
9985
+ target: {
9986
+ ...node.task.executor,
9987
+ inputs: node.task.inputs.filter((port) => "handle" in port),
9988
+ outputs: node.task.outputs.filter((port) => "handle" in port)
9989
+ },
9990
+ path: "task/executor"
9991
+ }];
9992
+ if (node.task.executor.kind == "agent") return node.task.executor.tools.flatMap((item, index) => item.kind == "workflow" ? [{
9993
+ target: item,
9994
+ path: `task/executor/tools/${index}`,
9995
+ tool: item.name
9996
+ }] : []);
9997
+ return [];
9998
+ }
9999
+ //#endregion
10000
+ //#region src/flow/common/workflowBundle.ts
10001
+ var entries$1 = array(strictObject({
10002
+ flowId: string().min(1),
10003
+ file: unknown()
10004
+ })).min(1);
10005
+ var bundleSchema = strictObject({
10006
+ kind: literal("open-flow-workflow-bundle"),
10007
+ version: literal(1),
10008
+ entryFlowId: string().min(1),
10009
+ workflows: entries$1
10010
+ });
10011
+ var previewSchema = strictObject({
10012
+ version: literal(1),
10013
+ entryFlowId: string().min(1),
10014
+ workflows: entries$1,
10015
+ unavailableFlowIds: array(string().min(1))
10016
+ });
10017
+ function decodeEntries(value, entryFlowId, unavailableFlowIds = []) {
10018
+ const workflows = value.map(({ flowId, file }) => ({
10019
+ flowId,
10020
+ file: decodeWorkflowFile(file)
10021
+ }));
10022
+ const ids = new Set(workflows.map(({ flowId }) => flowId));
10023
+ if (ids.size != workflows.length || !ids.has(entryFlowId)) throw new TypeError("Workflow identities must be unique and include the entry workflow.");
10024
+ const unavailable = new Set(unavailableFlowIds);
10025
+ if (unavailable.size != unavailableFlowIds.length || unavailableFlowIds.some((id) => ids.has(id))) throw new TypeError("Invalid unavailable workflow identities.");
10026
+ for (const { file } of workflows) for (const node of Object.values(file.content.document.graph.nodes)) for (const { target } of nodeWorkflowReferences(node)) if (target.flowId && !ids.has(target.flowId) && !unavailable.has(target.flowId)) throw new TypeError("A referenced workflow is missing from the bundle.");
10027
+ return workflows;
10028
+ }
10029
+ function decodeWorkflowBundle(value) {
10030
+ checkJsonDepth(value, -4);
10031
+ const bundle = bundleSchema.parse(value);
10032
+ return {
10033
+ ...bundle,
10034
+ workflows: decodeEntries(bundle.workflows, bundle.entryFlowId)
10035
+ };
10036
+ }
10037
+ function decodeWorkflowExportPreview(value) {
10038
+ checkJsonDepth(value, -4);
10039
+ const preview = previewSchema.parse(value);
10040
+ return {
10041
+ ...preview,
10042
+ workflows: decodeEntries(preview.workflows, preview.entryFlowId, preview.unavailableFlowIds)
10043
+ };
10044
+ }
10045
+ function cleanWorkflowBundle(value) {
10046
+ const bundle = decodeWorkflowBundle(value);
10047
+ return {
10048
+ ...bundle,
10049
+ workflows: bundle.workflows.map(({ flowId, file }) => ({
10050
+ flowId,
10051
+ file: cleanWorkflowFile(file).file
10052
+ }))
10053
+ };
10054
+ }
10055
+ function workflowBundleFromPreview(preview) {
10056
+ if (preview.unavailableFlowIds.length) throw new TypeError("Some referenced workflows are unavailable.");
10057
+ return cleanWorkflowBundle({
10058
+ kind: "open-flow-workflow-bundle",
10059
+ version: 1,
10060
+ entryFlowId: preview.entryFlowId,
10061
+ workflows: preview.workflows
10062
+ });
10063
+ }
10064
+ function encodeWorkflowBundle(bundle) {
10065
+ return `${JSON.stringify(cleanWorkflowBundle(bundle), null, 2)}\n`;
10066
+ }
10067
+ function parseWorkflowImportFile(text) {
10068
+ const value = JSON.parse(text);
10069
+ return value != null && typeof value == "object" && "kind" in value && value.kind == "open-flow-workflow-bundle" ? decodeWorkflowBundle(value) : decodeWorkflowFile(value);
10070
+ }
10071
+ /** A bundle creates new drafts, so old published interface provenance must be refreshed. */
10072
+ function remapWorkflowBundle(bundle, flowIds) {
10073
+ const cleaned = cleanWorkflowBundle(bundle);
10074
+ function identity(flowId) {
10075
+ const mapped = flowIds.get(flowId);
10076
+ if (mapped == null || mapped.length == 0) throw new TypeError("Missing imported workflow identity.");
10077
+ return mapped;
10078
+ }
10079
+ const workflows = cleaned.workflows.map(({ flowId, file }) => ({
10080
+ flowId: identity(flowId),
10081
+ file: {
10082
+ ...file,
10083
+ content: {
10084
+ ...file.content,
10085
+ document: {
10086
+ ...file.content.document,
10087
+ graph: {
10088
+ ...file.content.document.graph,
10089
+ nodes: Object.fromEntries(Object.entries(file.content.document.graph.nodes).map(([id, node]) => [id, mapNodeWorkflowTargets(node, (target) => ({
10090
+ flowId: target.flowId ? identity(target.flowId) : "",
10091
+ revisionId: ""
10092
+ }))]))
10093
+ }
10094
+ }
10095
+ }
10096
+ }
10097
+ }));
10098
+ return decodeWorkflowBundle({
10099
+ ...cleaned,
10100
+ entryFlowId: identity(cleaned.entryFlowId),
10101
+ workflows
10102
+ });
10103
+ }
10104
+ //#endregion
9939
10105
  //#region src/flow/common/encoding.ts
9940
10106
  var encoder = new TextEncoder();
9941
10107
  function canonicalText(value) {
@@ -10315,4 +10481,4 @@ function repairRevision(bytes) {
10315
10481
  return repairRevisionEnvelope(revisionValue(bytes));
10316
10482
  }
10317
10483
  //#endregion
10318
- export { canonicalDocument, canonicalGraph, canonicalInputs, canonicalJsonBytes, canonicalModule, canonicalPorts, canonicalRevisionGraph, canonicalTask, cleanWorkflowFile, decodeFlowDocument, decodeRevision, decodeRevisionContent, decodeWorkflowFile, digestBytes, encodeRevision, encodeWorkflowFile, maxJsonDepth, parseWorkflowFile, repairRevision, revisionRepairKind, triggerRuntimeJson, upgradeRevisionContent, upgradeWorkflowInterfaceDocument, workflowFileName, workflowNameFromFile };
10484
+ export { canonicalDocument, canonicalGraph, canonicalInputs, canonicalJsonBytes, canonicalModule, canonicalPorts, canonicalRevisionGraph, canonicalTask, cleanWorkflowBundle, cleanWorkflowFile, decodeFlowDocument, decodeRevision, decodeRevisionContent, decodeWorkflowBundle, decodeWorkflowExportPreview, decodeWorkflowFile, digestBytes, encodeRevision, encodeWorkflowBundle, encodeWorkflowFile, maxJsonDepth, parseWorkflowFile, parseWorkflowImportFile, remapWorkflowBundle, repairRevision, revisionRepairKind, triggerRuntimeJson, upgradeRevisionContent, upgradeWorkflowInterfaceDocument, workflowBundleFromPreview, workflowFileName, workflowNameFromFile };
@@ -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;
@@ -12321,10 +12336,30 @@ strictObject({
12321
12336
  kind: literal("open-flow-workflow"),
12322
12337
  version: literal(1),
12323
12338
  name: string().optional(),
12339
+ icon: string().optional(),
12340
+ description: string().optional(),
12324
12341
  content: unknown(),
12325
12342
  presentation: record$1(string(), json$1()).optional()
12326
12343
  });
12327
12344
  //#endregion
12345
+ //#region src/flow/common/workflowBundle.ts
12346
+ var entries$2 = array(strictObject({
12347
+ flowId: string().min(1),
12348
+ file: unknown()
12349
+ })).min(1);
12350
+ strictObject({
12351
+ kind: literal("open-flow-workflow-bundle"),
12352
+ version: literal(1),
12353
+ entryFlowId: string().min(1),
12354
+ workflows: entries$2
12355
+ });
12356
+ strictObject({
12357
+ version: literal(1),
12358
+ entryFlowId: string().min(1),
12359
+ workflows: entries$2,
12360
+ unavailableFlowIds: array(string().min(1))
12361
+ });
12362
+ //#endregion
12328
12363
  //#region src/flow/common/encoding.ts
12329
12364
  var encoder = new TextEncoder();
12330
12365
  function canonicalText(value) {
@@ -25089,15 +25124,17 @@ async function validateFlow(revision, engine) {
25089
25124
  message,
25090
25125
  path: `/document/graph/nodes/${nodeId}/task/executor`
25091
25126
  });
25092
- if (task.executor.kind == "connector" && task.executor.action == "leina.send_notification") {
25093
- const mapping = node.inputs.leinaId;
25094
- const value = inputValue(mapping, nodeInputPorts(node).leinaId?.value);
25095
- if ((mapping?.kind != "sources" || mapping.sources.length == 0) && (typeof value != "string" || value.trim().length == 0)) checked.diagnostics.push({
25096
- code: "leina.robot-required",
25127
+ if (task.executor.kind == "connector") for (const constraint of connectorActionContracts[task.executor.action]?.inputConstraints ?? []) {
25128
+ const mapping = node.inputs[constraint.handle];
25129
+ if (mapping?.kind == "sources" && mapping.sources.length > 0) continue;
25130
+ const value = inputValue(mapping, nodeInputPorts(node)[constraint.handle]?.value);
25131
+ if (value !== void 0 && matchesSchema(value, constraint.jsonSchema)) continue;
25132
+ checked.diagnostics.push({
25133
+ code: constraint.code,
25097
25134
  column: 0,
25098
25135
  line: 1,
25099
- message: "Select a Leina robot or bind its identifier to an input source.",
25100
- path: `/document/graph/nodes/${nodeId}/inputs/leinaId`
25136
+ message: constraint.message,
25137
+ path: `/document/graph/nodes/${nodeId}/inputs/${constraint.handle}`
25101
25138
  });
25102
25139
  }
25103
25140
  if (task.executor.kind == "connector" && task.executor.action.length == 0) checked.diagnostics.push({
@@ -0,0 +1,27 @@
1
+ import type { WorkflowFile } from './flow-workflowFile.js';
2
+ export interface WorkflowBundleEntry {
3
+ readonly flowId: string;
4
+ readonly file: WorkflowFile;
5
+ }
6
+ export interface WorkflowBundle {
7
+ readonly kind: 'open-flow-workflow-bundle';
8
+ readonly version: 1;
9
+ readonly entryFlowId: string;
10
+ readonly workflows: readonly WorkflowBundleEntry[];
11
+ }
12
+ /** A saved export snapshot; unavailable targets carry no account metadata. */
13
+ export interface WorkflowExportPreview {
14
+ readonly version: 1;
15
+ readonly entryFlowId: string;
16
+ readonly workflows: readonly WorkflowBundleEntry[];
17
+ readonly unavailableFlowIds: readonly string[];
18
+ }
19
+ export declare function decodeWorkflowBundle(value: unknown): WorkflowBundle;
20
+ export declare function decodeWorkflowExportPreview(value: unknown): WorkflowExportPreview;
21
+ export declare function cleanWorkflowBundle(value: unknown): WorkflowBundle;
22
+ export declare function workflowBundleFromPreview(preview: WorkflowExportPreview): WorkflowBundle;
23
+ export declare function encodeWorkflowBundle(bundle: WorkflowBundle): string;
24
+ export type WorkflowImportFile = WorkflowFile | WorkflowBundle;
25
+ export declare function parseWorkflowImportFile(text: string): WorkflowImportFile;
26
+ /** A bundle creates new drafts, so old published interface provenance must be refreshed. */
27
+ export declare function remapWorkflowBundle(bundle: WorkflowBundle, flowIds: ReadonlyMap<string, string>): WorkflowBundle;
@@ -3,6 +3,8 @@ export interface WorkflowFile {
3
3
  readonly kind: 'open-flow-workflow';
4
4
  readonly version: 1;
5
5
  readonly name?: string;
6
+ readonly icon?: string;
7
+ readonly description?: string;
6
8
  readonly content: RevisionContent;
7
9
  readonly presentation?: Readonly<Record<string, JsonValue>>;
8
10
  }
@@ -1,8 +1,12 @@
1
1
  import type { GraphNode } from './flow-change.js';
2
2
  import type { WorkflowCapability } from './flow-model.js';
3
+ type WorkflowTarget = Pick<WorkflowCapability, 'flowId' | 'revisionId'>;
4
+ /** Rewrite only declared workflow identities, preserving business values and saved ports. */
5
+ export declare function mapNodeWorkflowTargets(node: GraphNode, map: (target: WorkflowTarget) => WorkflowTarget): GraphNode;
3
6
  /** Workflow declarations share discovery across authoring, admission and resource indexing. */
4
7
  export declare function nodeWorkflowReferences(node: GraphNode): readonly {
5
8
  readonly target: Omit<WorkflowCapability, 'kind' | 'name'>;
6
9
  readonly path: string;
7
10
  readonly tool?: string;
8
11
  }[];
12
+ export {};
@@ -349,6 +349,7 @@ export declare const mcpTools: {
349
349
  validate(value: unknown): {
350
350
  value: {
351
351
  flowId: string;
352
+ includeDependencies?: boolean | undefined;
352
353
  };
353
354
  } | {
354
355
  issues: {
@@ -380,6 +381,7 @@ export declare const mcpTools: {
380
381
  file: JsonValue;
381
382
  name?: string | undefined;
382
383
  teamId?: string | undefined;
384
+ tagIds?: string[] | undefined;
383
385
  idempotencyKey: string;
384
386
  };
385
387
  } | {