@d34dman/flowdrop 0.0.57 → 0.0.58

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 (54) hide show
  1. package/README.md +4 -4
  2. package/dist/adapters/WorkflowAdapter.d.ts +2 -1
  3. package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +4 -0
  4. package/dist/adapters/agentspec/AgentSpecAdapter.js +27 -22
  5. package/dist/adapters/agentspec/componentTypeDefaults.d.ts +73 -0
  6. package/dist/adapters/agentspec/componentTypeDefaults.js +238 -0
  7. package/dist/adapters/agentspec/{nodeTypeRegistry.d.ts → defaultNodeTypes.d.ts} +21 -30
  8. package/dist/adapters/agentspec/{nodeTypeRegistry.js → defaultNodeTypes.js} +31 -59
  9. package/dist/adapters/agentspec/index.d.ts +3 -1
  10. package/dist/adapters/agentspec/index.js +4 -2
  11. package/dist/components/App.svelte +57 -13
  12. package/dist/components/NodeSidebar.svelte +20 -8
  13. package/dist/components/NodeSidebar.svelte.d.ts +2 -1
  14. package/dist/components/WorkflowEditor.svelte +14 -13
  15. package/dist/components/form/FormMarkdownEditor.svelte +546 -422
  16. package/dist/components/form/FormMarkdownEditor.svelte.d.ts +2 -0
  17. package/dist/components/form/FormUISchemaRenderer.svelte +4 -8
  18. package/dist/components/form/types.d.ts +1 -1
  19. package/dist/components/nodes/WorkflowNode.svelte +1 -2
  20. package/dist/core/index.d.ts +13 -3
  21. package/dist/core/index.js +16 -3
  22. package/dist/form/code.js +6 -1
  23. package/dist/form/fieldRegistry.d.ts +79 -15
  24. package/dist/form/fieldRegistry.js +104 -49
  25. package/dist/form/full.d.ts +2 -2
  26. package/dist/form/full.js +2 -2
  27. package/dist/form/index.d.ts +3 -3
  28. package/dist/form/index.js +6 -2
  29. package/dist/form/markdown.d.ts +3 -3
  30. package/dist/form/markdown.js +8 -4
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js +2 -2
  33. package/dist/registry/BaseRegistry.d.ts +92 -0
  34. package/dist/registry/BaseRegistry.js +124 -0
  35. package/dist/registry/builtinFormats.d.ts +23 -0
  36. package/dist/registry/builtinFormats.js +70 -0
  37. package/dist/registry/builtinNodes.js +4 -0
  38. package/dist/registry/index.d.ts +2 -1
  39. package/dist/registry/index.js +2 -0
  40. package/dist/registry/nodeComponentRegistry.d.ts +26 -57
  41. package/dist/registry/nodeComponentRegistry.js +29 -82
  42. package/dist/registry/workflowFormatRegistry.d.ts +122 -0
  43. package/dist/registry/workflowFormatRegistry.js +96 -0
  44. package/dist/schema/index.d.ts +23 -0
  45. package/dist/schema/index.js +23 -0
  46. package/dist/stores/portCoordinateStore.js +1 -4
  47. package/dist/stores/workflowStore.d.ts +3 -0
  48. package/dist/stores/workflowStore.js +3 -0
  49. package/dist/svelte-app.d.ts +4 -0
  50. package/dist/svelte-app.js +9 -1
  51. package/dist/types/index.d.ts +18 -0
  52. package/dist/types/index.js +4 -0
  53. package/package.json +231 -225
  54. package/schemas/v1/workflow.schema.json +952 -0
@@ -8,10 +8,13 @@
8
8
  * - External libraries to contribute node types via plugins
9
9
  * - Runtime switching between different node visualizations
10
10
  */
11
+ import { BaseRegistry } from './BaseRegistry.js';
11
12
  /**
12
13
  * Central registry for node component types.
13
14
  * Allows built-in and third-party components to be registered and resolved.
14
15
  *
16
+ * Extends BaseRegistry for shared mechanics (subscribe, onClear, etc.).
17
+ *
15
18
  * @example
16
19
  * ```typescript
17
20
  * // Register a custom node
@@ -27,13 +30,11 @@
27
30
  * const component = nodeComponentRegistry.getComponent("myCustomNode");
28
31
  * ```
29
32
  */
30
- class NodeComponentRegistry {
31
- /** Map of type -> registration */
32
- components = new Map();
33
+ class NodeComponentRegistry extends BaseRegistry {
33
34
  /** Default type to use when requested type is not found */
34
35
  defaultType = 'workflowNode';
35
- /** Listeners for registry changes */
36
- listeners = new Set();
36
+ /** Initial default type, restored on clear() */
37
+ static INITIAL_DEFAULT_TYPE = 'workflowNode';
37
38
  /**
38
39
  * Register a node component type.
39
40
  *
@@ -51,12 +52,19 @@ class NodeComponentRegistry {
51
52
  * });
52
53
  * ```
53
54
  */
55
+ /**
56
+ * Clear all registrations and reset default type.
57
+ */
58
+ clear() {
59
+ super.clear();
60
+ this.defaultType = NodeComponentRegistry.INITIAL_DEFAULT_TYPE;
61
+ }
54
62
  register(registration, overwrite = false) {
55
- if (this.components.has(registration.type) && !overwrite) {
63
+ if (this.items.has(registration.type) && !overwrite) {
56
64
  throw new Error(`Node type "${registration.type}" is already registered. ` +
57
65
  `Use overwrite: true to replace it, or use a namespaced type like "mylib:${registration.type}".`);
58
66
  }
59
- this.components.set(registration.type, registration);
67
+ this.items.set(registration.type, registration);
60
68
  this.notifyListeners();
61
69
  }
62
70
  /**
@@ -71,28 +79,6 @@ class NodeComponentRegistry {
71
79
  this.register(registration, overwrite);
72
80
  }
73
81
  }
74
- /**
75
- * Unregister a node component type.
76
- *
77
- * @param type - The type identifier to remove
78
- * @returns true if the type was found and removed, false otherwise
79
- */
80
- unregister(type) {
81
- const result = this.components.delete(type);
82
- if (result) {
83
- this.notifyListeners();
84
- }
85
- return result;
86
- }
87
- /**
88
- * Get a registration by type.
89
- *
90
- * @param type - The type identifier to look up
91
- * @returns The registration if found, undefined otherwise
92
- */
93
- get(type) {
94
- return this.components.get(type);
95
- }
96
82
  /**
97
83
  * Get the component for a type, with fallback to default.
98
84
  *
@@ -100,17 +86,21 @@ class NodeComponentRegistry {
100
86
  * @returns The component if found, or the default component
101
87
  */
102
88
  getComponent(type) {
103
- const registration = this.components.get(type) ?? this.components.get(this.defaultType);
89
+ const registration = this.items.get(type) ?? this.items.get(this.defaultType);
104
90
  return registration?.component;
105
91
  }
106
92
  /**
107
- * Check if a type is registered.
93
+ * Get framework-agnostic metadata for a type, without the Svelte component.
108
94
  *
109
- * @param type - The type identifier to check
110
- * @returns true if the type is registered
95
+ * @param type - The type identifier to look up
96
+ * @returns The metadata if found, undefined otherwise
111
97
  */
112
- has(type) {
113
- return this.components.has(type);
98
+ getMetadata(type) {
99
+ const reg = this.items.get(type);
100
+ if (!reg)
101
+ return undefined;
102
+ const { component: _, ...metadata } = reg;
103
+ return metadata;
114
104
  }
115
105
  /**
116
106
  * Get all registered type identifiers.
@@ -118,15 +108,7 @@ class NodeComponentRegistry {
118
108
  * @returns Array of registered type strings
119
109
  */
120
110
  getTypes() {
121
- return Array.from(this.components.keys());
122
- }
123
- /**
124
- * Get all registrations.
125
- *
126
- * @returns Array of all registered node component metadata
127
- */
128
- getAll() {
129
- return Array.from(this.components.values());
111
+ return this.getKeys();
130
112
  }
131
113
  /**
132
114
  * Get registrations filtered by criteria.
@@ -182,7 +164,7 @@ class NodeComponentRegistry {
182
164
  * @throws Error if the type is not registered
183
165
  */
184
166
  setDefaultType(type) {
185
- if (!this.components.has(type)) {
167
+ if (!this.items.has(type)) {
186
168
  throw new Error(`Cannot set default to unregistered type: ${type}`);
187
169
  }
188
170
  this.defaultType = type;
@@ -195,25 +177,6 @@ class NodeComponentRegistry {
195
177
  getDefaultType() {
196
178
  return this.defaultType;
197
179
  }
198
- /**
199
- * Subscribe to registry changes.
200
- * Called whenever components are registered or unregistered.
201
- *
202
- * @param listener - Callback to invoke on changes
203
- * @returns Unsubscribe function
204
- */
205
- subscribe(listener) {
206
- this.listeners.add(listener);
207
- return () => this.listeners.delete(listener);
208
- }
209
- /**
210
- * Notify all listeners of a change.
211
- */
212
- notifyListeners() {
213
- for (const listener of this.listeners) {
214
- listener();
215
- }
216
- }
217
180
  /**
218
181
  * Get oneOf options for config forms.
219
182
  * Returns array suitable for JSON Schema oneOf with const/title.
@@ -241,7 +204,7 @@ class NodeComponentRegistry {
241
204
  * @returns The status position, or default "top-right"
242
205
  */
243
206
  getStatusPosition(type) {
244
- return this.components.get(type)?.statusPosition ?? 'top-right';
207
+ return this.items.get(type)?.statusPosition ?? 'top-right';
245
208
  }
246
209
  /**
247
210
  * Get the status size for a node type.
@@ -250,23 +213,7 @@ class NodeComponentRegistry {
250
213
  * @returns The status size, or default "md"
251
214
  */
252
215
  getStatusSize(type) {
253
- return this.components.get(type)?.statusSize ?? 'md';
254
- }
255
- /**
256
- * Clear all registrations.
257
- * Primarily useful for testing.
258
- */
259
- clear() {
260
- this.components.clear();
261
- this.notifyListeners();
262
- }
263
- /**
264
- * Get the count of registered components.
265
- *
266
- * @returns Number of registered node types
267
- */
268
- get size() {
269
- return this.components.size;
216
+ return this.items.get(type)?.statusSize ?? 'md';
270
217
  }
271
218
  }
272
219
  /** Singleton instance of the node component registry */
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Workflow Format Registry
3
+ *
4
+ * Central registry for workflow format adapters that allows built-in and
5
+ * third-party formats to be registered and resolved at runtime.
6
+ *
7
+ * This enables:
8
+ * - Custom workflow formats (e.g., n8n, LangGraph) to be registered by users
9
+ * - Format adapters to bundle their own node types
10
+ * - Bidirectional conversion between FlowDrop's StandardWorkflow and external formats
11
+ *
12
+ * Extends BaseRegistry for shared mechanics (subscribe, onClear, etc.).
13
+ */
14
+ import type { StandardWorkflow } from '../adapters/WorkflowAdapter.js';
15
+ import type { NodeMetadata, WorkflowFormat } from '../types/index.js';
16
+ import { BaseRegistry } from './BaseRegistry.js';
17
+ /**
18
+ * Validation result returned by format adapters.
19
+ */
20
+ export interface FormatValidationResult {
21
+ valid: boolean;
22
+ errors: string[];
23
+ warnings: string[];
24
+ }
25
+ /**
26
+ * Interface that all workflow format adapters must implement.
27
+ * Adapters handle bidirectional conversion between FlowDrop's StandardWorkflow
28
+ * and an external workflow format.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const myAdapter: WorkflowFormatAdapter = {
33
+ * id: 'n8n',
34
+ * name: 'n8n Workflow',
35
+ * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
36
+ * import: (data) => convertFromN8n(JSON.parse(data)),
37
+ * };
38
+ * ```
39
+ */
40
+ export interface WorkflowFormatAdapter {
41
+ /** Unique format identifier (e.g., 'agentspec', 'n8n') */
42
+ id: WorkflowFormat;
43
+ /** Display name for UI (e.g., 'Agent Spec (Oracle)') */
44
+ name: string;
45
+ /** Description */
46
+ description?: string;
47
+ /** Version */
48
+ version?: string;
49
+ /**
50
+ * Optional node types specific to this format.
51
+ * When provided, these nodes are merged into the sidebar
52
+ * and automatically tagged with this format.
53
+ */
54
+ nodes?: NodeMetadata[];
55
+ /** Convert a StandardWorkflow to this format's JSON string */
56
+ export(workflow: StandardWorkflow): string;
57
+ /** Parse this format's input and convert to StandardWorkflow */
58
+ import(data: string): StandardWorkflow;
59
+ /** Validate whether a workflow can be exported to this format */
60
+ validate?(workflow: StandardWorkflow): FormatValidationResult;
61
+ }
62
+ /**
63
+ * Central registry for workflow format adapters.
64
+ * Singleton — extends BaseRegistry for shared mechanics.
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * // Register a custom format
69
+ * workflowFormatRegistry.register({
70
+ * id: 'n8n',
71
+ * name: 'n8n Workflow',
72
+ * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
73
+ * import: (data) => convertFromN8n(JSON.parse(data)),
74
+ * });
75
+ *
76
+ * // Get an adapter
77
+ * const adapter = workflowFormatRegistry.get('n8n');
78
+ * ```
79
+ */
80
+ declare class WorkflowFormatRegistry extends BaseRegistry<string, WorkflowFormatAdapter> {
81
+ /**
82
+ * Register a workflow format adapter.
83
+ *
84
+ * @param adapter - The format adapter to register
85
+ * @param overwrite - If true, allows overwriting existing registrations
86
+ * @throws Error if format already registered and overwrite is false
87
+ */
88
+ register(adapter: WorkflowFormatAdapter, overwrite?: boolean): void;
89
+ /**
90
+ * Get all registered format identifiers.
91
+ *
92
+ * @returns Array of format id strings
93
+ */
94
+ getIds(): string[];
95
+ /**
96
+ * Get all node types provided by registered format adapters.
97
+ * Collects `adapter.nodes` from all adapters that provide them.
98
+ *
99
+ * @returns Array of NodeMetadata from all format adapters
100
+ */
101
+ getAllFormatNodes(): NodeMetadata[];
102
+ /**
103
+ * Get node types for a specific format.
104
+ *
105
+ * @param formatId - The format identifier
106
+ * @returns Array of NodeMetadata for the format, or empty array
107
+ */
108
+ getFormatNodes(formatId: WorkflowFormat): NodeMetadata[];
109
+ /**
110
+ * Get oneOf options for config forms.
111
+ * Returns array suitable for JSON Schema oneOf with const/title.
112
+ *
113
+ * @returns Array of oneOf items
114
+ */
115
+ getOneOfOptions(): Array<{
116
+ const: string;
117
+ title: string;
118
+ }>;
119
+ }
120
+ /** Singleton instance of the workflow format registry */
121
+ export declare const workflowFormatRegistry: WorkflowFormatRegistry;
122
+ export {};
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Workflow Format Registry
3
+ *
4
+ * Central registry for workflow format adapters that allows built-in and
5
+ * third-party formats to be registered and resolved at runtime.
6
+ *
7
+ * This enables:
8
+ * - Custom workflow formats (e.g., n8n, LangGraph) to be registered by users
9
+ * - Format adapters to bundle their own node types
10
+ * - Bidirectional conversion between FlowDrop's StandardWorkflow and external formats
11
+ *
12
+ * Extends BaseRegistry for shared mechanics (subscribe, onClear, etc.).
13
+ */
14
+ import { BaseRegistry } from './BaseRegistry.js';
15
+ /**
16
+ * Central registry for workflow format adapters.
17
+ * Singleton — extends BaseRegistry for shared mechanics.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Register a custom format
22
+ * workflowFormatRegistry.register({
23
+ * id: 'n8n',
24
+ * name: 'n8n Workflow',
25
+ * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
26
+ * import: (data) => convertFromN8n(JSON.parse(data)),
27
+ * });
28
+ *
29
+ * // Get an adapter
30
+ * const adapter = workflowFormatRegistry.get('n8n');
31
+ * ```
32
+ */
33
+ class WorkflowFormatRegistry extends BaseRegistry {
34
+ /**
35
+ * Register a workflow format adapter.
36
+ *
37
+ * @param adapter - The format adapter to register
38
+ * @param overwrite - If true, allows overwriting existing registrations
39
+ * @throws Error if format already registered and overwrite is false
40
+ */
41
+ register(adapter, overwrite = false) {
42
+ if (this.items.has(adapter.id) && !overwrite) {
43
+ throw new Error(`Workflow format "${adapter.id}" is already registered. ` +
44
+ `Use overwrite: true to replace it.`);
45
+ }
46
+ this.items.set(adapter.id, adapter);
47
+ this.notifyListeners();
48
+ }
49
+ /**
50
+ * Get all registered format identifiers.
51
+ *
52
+ * @returns Array of format id strings
53
+ */
54
+ getIds() {
55
+ return this.getKeys();
56
+ }
57
+ /**
58
+ * Get all node types provided by registered format adapters.
59
+ * Collects `adapter.nodes` from all adapters that provide them.
60
+ *
61
+ * @returns Array of NodeMetadata from all format adapters
62
+ */
63
+ getAllFormatNodes() {
64
+ const allNodes = [];
65
+ for (const adapter of this.items.values()) {
66
+ if (adapter.nodes && adapter.nodes.length > 0) {
67
+ allNodes.push(...adapter.nodes);
68
+ }
69
+ }
70
+ return allNodes;
71
+ }
72
+ /**
73
+ * Get node types for a specific format.
74
+ *
75
+ * @param formatId - The format identifier
76
+ * @returns Array of NodeMetadata for the format, or empty array
77
+ */
78
+ getFormatNodes(formatId) {
79
+ const adapter = this.items.get(formatId);
80
+ return adapter?.nodes ?? [];
81
+ }
82
+ /**
83
+ * Get oneOf options for config forms.
84
+ * Returns array suitable for JSON Schema oneOf with const/title.
85
+ *
86
+ * @returns Array of oneOf items
87
+ */
88
+ getOneOfOptions() {
89
+ return this.getAll().map((adapter) => ({
90
+ const: adapter.id,
91
+ title: adapter.name
92
+ }));
93
+ }
94
+ }
95
+ /** Singleton instance of the workflow format registry */
96
+ export const workflowFormatRegistry = new WorkflowFormatRegistry();
@@ -0,0 +1,23 @@
1
+ /**
2
+ * FlowDrop Workflow JSON Schema
3
+ *
4
+ * Provides the versioned JSON Schema for the FlowDrop workflow document format.
5
+ * The schema is generated from the OpenAPI YAML definitions in `api/components/schemas/`.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { workflowSchema, WORKFLOW_SCHEMA_VERSION } from '@d34dman/flowdrop/core';
10
+ *
11
+ * // Use with any JSON Schema validator (e.g., Ajv)
12
+ * import Ajv from 'ajv/dist/2020';
13
+ * const ajv = new Ajv();
14
+ * const validate = ajv.compile(workflowSchema);
15
+ * const valid = validate(myWorkflow);
16
+ * ```
17
+ *
18
+ * @module schema
19
+ */
20
+ import workflowSchema from '../../../schemas/v1/workflow.schema.json';
21
+ /** Current workflow schema format version */
22
+ export declare const WORKFLOW_SCHEMA_VERSION = "1.0.0";
23
+ export { workflowSchema };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * FlowDrop Workflow JSON Schema
3
+ *
4
+ * Provides the versioned JSON Schema for the FlowDrop workflow document format.
5
+ * The schema is generated from the OpenAPI YAML definitions in `api/components/schemas/`.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { workflowSchema, WORKFLOW_SCHEMA_VERSION } from '@d34dman/flowdrop/core';
10
+ *
11
+ * // Use with any JSON Schema validator (e.g., Ajv)
12
+ * import Ajv from 'ajv/dist/2020';
13
+ * const ajv = new Ajv();
14
+ * const validate = ajv.compile(workflowSchema);
15
+ * const valid = validate(myWorkflow);
16
+ * ```
17
+ *
18
+ * @module schema
19
+ */
20
+ import workflowSchema from '../../../schemas/v1/workflow.schema.json';
21
+ /** Current workflow schema format version */
22
+ export const WORKFLOW_SCHEMA_VERSION = '1.0.0';
23
+ export { workflowSchema };
@@ -65,10 +65,7 @@ function computeNodePortCoordinates(node, internalNode) {
65
65
  const posAbs = internalNode.internals.positionAbsolute;
66
66
  const dataTypeLookup = buildPortDataTypeLookup(node);
67
67
  const coordinates = [];
68
- const allHandles = [
69
- ...(handleBounds.source ?? []),
70
- ...(handleBounds.target ?? [])
71
- ];
68
+ const allHandles = [...(handleBounds.source ?? []), ...(handleBounds.target ?? [])];
72
69
  for (const handle of allHandles) {
73
70
  if (!handle.id)
74
71
  continue;
@@ -86,7 +86,10 @@ export declare const workflowMetadata: import("svelte/store").Readable<{
86
86
  tags?: string[];
87
87
  versionId?: string;
88
88
  updateNumber?: number;
89
+ format?: import("../types").WorkflowFormat;
89
90
  }>;
91
+ /** Derived store for the current workflow format */
92
+ export declare const workflowFormat: import("svelte/store").Readable<import("../types").WorkflowFormat>;
90
93
  /**
91
94
  * Actions for updating the workflow
92
95
  *
@@ -7,6 +7,7 @@
7
7
  * @module stores/workflowStore
8
8
  */
9
9
  import { writable, derived, get } from 'svelte/store';
10
+ import { DEFAULT_WORKFLOW_FORMAT } from '../types/index.js';
10
11
  import { historyService } from '../services/historyService.js';
11
12
  // =========================================================================
12
13
  // Core Workflow Store
@@ -220,6 +221,8 @@ export const workflowMetadata = derived(workflowStore, ($workflow) => $workflow?
220
221
  versionId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
221
222
  updateNumber: 0
222
223
  });
224
+ /** Derived store for the current workflow format */
225
+ export const workflowFormat = derived(workflowStore, ($workflow) => $workflow?.metadata?.format ?? DEFAULT_WORKFLOW_FORMAT);
223
226
  // =========================================================================
224
227
  // Helper Functions
225
228
  // =========================================================================
@@ -10,6 +10,8 @@ import type { Workflow, NodeMetadata, PortConfig, CategoryDefinition } from './t
10
10
  import type { EndpointConfig } from './config/endpoints.js';
11
11
  import type { AuthProvider } from './types/auth.js';
12
12
  import type { FlowDropEventHandlers, FlowDropFeatures } from './types/events.js';
13
+ import type { WorkflowFormatAdapter } from './registry/workflowFormatRegistry.js';
14
+ import './registry/builtinFormats.js';
13
15
  import type { PartialSettings } from './types/settings.js';
14
16
  declare global {
15
17
  interface Window {
@@ -73,6 +75,8 @@ export interface FlowDropMountOptions {
73
75
  settings?: PartialSettings;
74
76
  /** Custom storage key for localStorage drafts */
75
77
  draftStorageKey?: string;
78
+ /** Custom workflow format adapters to register */
79
+ formatAdapters?: WorkflowFormatAdapter[];
76
80
  }
77
81
  /**
78
82
  * Return type for mounted FlowDrop app
@@ -9,6 +9,8 @@
9
9
  import { mount, unmount } from 'svelte';
10
10
  import WorkflowEditor from './components/WorkflowEditor.svelte';
11
11
  import App from './components/App.svelte';
12
+ import { workflowFormatRegistry } from './registry/workflowFormatRegistry.js';
13
+ import './registry/builtinFormats.js';
12
14
  import { initializePortCompatibility } from './utils/connections.js';
13
15
  import { DEFAULT_PORT_CONFIG } from './config/defaultPortConfig.js';
14
16
  import { fetchPortConfig } from './services/portConfigApi.js';
@@ -43,7 +45,13 @@ import { initializeSettings } from './stores/settingsStore.js';
43
45
  * ```
44
46
  */
45
47
  export async function mountFlowDropApp(container, options = {}) {
46
- const { workflow, nodes, endpointConfig, portConfig, categories, height = '100vh', width = '100%', showNavbar = false, disableSidebar, lockWorkflow, readOnly, nodeStatuses, pipelineId, navbarTitle, navbarActions, showSettings, authProvider, eventHandlers, features: userFeatures, settings: initialSettings, draftStorageKey: customDraftKey } = options;
48
+ const { workflow, nodes, endpointConfig, portConfig, categories, height = '100vh', width = '100%', showNavbar = false, disableSidebar, lockWorkflow, readOnly, nodeStatuses, pipelineId, navbarTitle, navbarActions, showSettings, authProvider, eventHandlers, features: userFeatures, settings: initialSettings, draftStorageKey: customDraftKey, formatAdapters } = options;
49
+ // Register custom format adapters before mounting
50
+ if (formatAdapters) {
51
+ for (const adapter of formatAdapters) {
52
+ workflowFormatRegistry.register(adapter);
53
+ }
54
+ }
47
55
  // Merge features with defaults
48
56
  const features = mergeFeatures(userFeatures);
49
57
  // Apply initial settings overrides and initialize theme
@@ -24,6 +24,20 @@ export type BuiltinNodeCategory = 'triggers' | 'inputs' | 'outputs' | 'prompts'
24
24
  * ```
25
25
  */
26
26
  export type NodeCategory = BuiltinNodeCategory | (string & Record<never, never>);
27
+ /**
28
+ * Built-in workflow format identifiers that ship with FlowDrop.
29
+ */
30
+ export type BuiltinWorkflowFormat = 'flowdrop' | 'agentspec';
31
+ /**
32
+ * Workflow format identifier.
33
+ * Determines sidebar node filtering and export behavior.
34
+ * Includes built-in formats plus any custom string for third-party adapters.
35
+ */
36
+ export type WorkflowFormat = BuiltinWorkflowFormat | (string & Record<never, never>);
37
+ /**
38
+ * Default workflow format used when none is specified.
39
+ */
40
+ export declare const DEFAULT_WORKFLOW_FORMAT: WorkflowFormat;
27
41
  /**
28
42
  * Category definition with metadata for display and organization.
29
43
  * Fetched from the `/categories` API endpoint or provided as defaults.
@@ -550,6 +564,8 @@ export interface NodeMetadata {
550
564
  /** Default configuration values for this node type */
551
565
  config?: Record<string, unknown>;
552
566
  tags?: string[];
567
+ /** Workflow formats this node is compatible with. Omit = universal (all formats). */
568
+ formats?: WorkflowFormat[];
553
569
  /**
554
570
  * Admin/Edit configuration for nodes with dynamic or external configuration.
555
571
  * Used when the config schema cannot be determined at workflow load time
@@ -1106,6 +1122,8 @@ export interface Workflow {
1106
1122
  tags?: string[];
1107
1123
  versionId?: string;
1108
1124
  updateNumber?: number;
1125
+ /** Workflow format. Determines sidebar filtering and export behavior. */
1126
+ format?: WorkflowFormat;
1109
1127
  };
1110
1128
  }
1111
1129
  /**
@@ -2,6 +2,10 @@
2
2
  * Core types for the Workflow Library
3
3
  */
4
4
  import { ConnectionLineType } from '@xyflow/svelte';
5
+ /**
6
+ * Default workflow format used when none is specified.
7
+ */
8
+ export const DEFAULT_WORKFLOW_FORMAT = 'flowdrop';
5
9
  /**
6
10
  * Convert a DynamicPort to a NodePort
7
11
  * @param port - The dynamic port configuration