@d34dman/flowdrop 0.0.56 → 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 (83) 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 +96 -0
  4. package/dist/adapters/agentspec/AgentSpecAdapter.js +663 -0
  5. package/dist/adapters/agentspec/agentAdapter.d.ts +59 -0
  6. package/dist/adapters/agentspec/agentAdapter.js +91 -0
  7. package/dist/adapters/agentspec/autoLayout.d.ts +34 -0
  8. package/dist/adapters/agentspec/autoLayout.js +127 -0
  9. package/dist/adapters/agentspec/componentTypeDefaults.d.ts +73 -0
  10. package/dist/adapters/agentspec/componentTypeDefaults.js +238 -0
  11. package/dist/adapters/agentspec/defaultNodeTypes.d.ts +53 -0
  12. package/dist/adapters/agentspec/defaultNodeTypes.js +561 -0
  13. package/dist/adapters/agentspec/index.d.ts +37 -0
  14. package/dist/adapters/agentspec/index.js +39 -0
  15. package/dist/adapters/agentspec/validator.d.ts +34 -0
  16. package/dist/adapters/agentspec/validator.js +169 -0
  17. package/dist/components/App.svelte +57 -13
  18. package/dist/components/ConfigForm.svelte +46 -12
  19. package/dist/components/ConfigForm.svelte.d.ts +8 -0
  20. package/dist/components/NodeSidebar.svelte +20 -8
  21. package/dist/components/NodeSidebar.svelte.d.ts +2 -1
  22. package/dist/components/SchemaForm.svelte +34 -12
  23. package/dist/components/SchemaForm.svelte.d.ts +8 -0
  24. package/dist/components/WorkflowEditor.svelte +14 -13
  25. package/dist/components/form/FormFieldset.svelte +142 -0
  26. package/dist/components/form/FormFieldset.svelte.d.ts +11 -0
  27. package/dist/components/form/FormMarkdownEditor.svelte +546 -422
  28. package/dist/components/form/FormMarkdownEditor.svelte.d.ts +2 -0
  29. package/dist/components/form/FormUISchemaRenderer.svelte +136 -0
  30. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +32 -0
  31. package/dist/components/form/index.d.ts +2 -0
  32. package/dist/components/form/index.js +3 -0
  33. package/dist/components/form/types.d.ts +1 -1
  34. package/dist/components/nodes/WorkflowNode.svelte +1 -2
  35. package/dist/config/agentSpecEndpoints.d.ts +70 -0
  36. package/dist/config/agentSpecEndpoints.js +65 -0
  37. package/dist/config/endpoints.d.ts +6 -0
  38. package/dist/core/index.d.ts +29 -3
  39. package/dist/core/index.js +31 -1
  40. package/dist/form/code.js +6 -1
  41. package/dist/form/fieldRegistry.d.ts +79 -15
  42. package/dist/form/fieldRegistry.js +104 -49
  43. package/dist/form/full.d.ts +2 -2
  44. package/dist/form/full.js +2 -2
  45. package/dist/form/index.d.ts +5 -3
  46. package/dist/form/index.js +9 -2
  47. package/dist/form/markdown.d.ts +3 -3
  48. package/dist/form/markdown.js +8 -4
  49. package/dist/helpers/workflowEditorHelper.d.ts +24 -0
  50. package/dist/helpers/workflowEditorHelper.js +55 -0
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.js +2 -2
  53. package/dist/registry/BaseRegistry.d.ts +92 -0
  54. package/dist/registry/BaseRegistry.js +124 -0
  55. package/dist/registry/builtinFormats.d.ts +23 -0
  56. package/dist/registry/builtinFormats.js +70 -0
  57. package/dist/registry/builtinNodes.js +4 -0
  58. package/dist/registry/index.d.ts +2 -1
  59. package/dist/registry/index.js +2 -0
  60. package/dist/registry/nodeComponentRegistry.d.ts +26 -57
  61. package/dist/registry/nodeComponentRegistry.js +29 -82
  62. package/dist/registry/workflowFormatRegistry.d.ts +122 -0
  63. package/dist/registry/workflowFormatRegistry.js +96 -0
  64. package/dist/schema/index.d.ts +23 -0
  65. package/dist/schema/index.js +23 -0
  66. package/dist/services/agentSpecExecutionService.d.ts +106 -0
  67. package/dist/services/agentSpecExecutionService.js +333 -0
  68. package/dist/stores/portCoordinateStore.js +1 -4
  69. package/dist/stores/workflowStore.d.ts +3 -0
  70. package/dist/stores/workflowStore.js +3 -0
  71. package/dist/svelte-app.d.ts +4 -0
  72. package/dist/svelte-app.js +9 -1
  73. package/dist/types/agentspec.d.ts +318 -0
  74. package/dist/types/agentspec.js +48 -0
  75. package/dist/types/events.d.ts +28 -1
  76. package/dist/types/index.d.ts +31 -0
  77. package/dist/types/index.js +5 -0
  78. package/dist/types/uischema.d.ts +144 -0
  79. package/dist/types/uischema.js +51 -0
  80. package/dist/utils/uischema.d.ts +52 -0
  81. package/dist/utils/uischema.js +88 -0
  82. package/package.json +231 -225
  83. package/schemas/v1/workflow.schema.json +952 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Agent-Level Adapter
3
+ *
4
+ * Handles conversion between FlowDrop workflows and full Agent Spec Documents
5
+ * (which wrap a Flow with Agent metadata like tools, LLM config, etc.)
6
+ */
7
+ import type { AgentSpecDocument, AgentSpecTool, AgentSpecLLMConfig } from '../../types/agentspec.js';
8
+ import type { StandardWorkflow } from '../WorkflowAdapter.js';
9
+ /**
10
+ * Agent-level configuration that wraps a workflow.
11
+ * Contains the Agent Spec agent metadata that lives outside the flow.
12
+ */
13
+ export interface AgentConfig {
14
+ /** Agent name */
15
+ name: string;
16
+ /** Agent description */
17
+ description?: string;
18
+ /** System prompt for the agent */
19
+ systemPrompt?: string;
20
+ /** Tools available to the agent */
21
+ tools?: AgentSpecTool[];
22
+ /** LLM configuration */
23
+ llmConfig?: AgentSpecLLMConfig;
24
+ }
25
+ /**
26
+ * Result of importing an Agent Spec Document.
27
+ */
28
+ export interface AgentSpecImportResult {
29
+ /** The FlowDrop workflow (from the flow) */
30
+ workflow: StandardWorkflow;
31
+ /** Agent metadata (from the agent, if present) */
32
+ agentConfig?: AgentConfig;
33
+ /** Shared tools declared at document level */
34
+ tools?: AgentSpecTool[];
35
+ /** Shared LLM configurations declared at document level */
36
+ llmConfigs?: AgentSpecLLMConfig[];
37
+ }
38
+ export declare class AgentSpecAgentAdapter {
39
+ private flowAdapter;
40
+ constructor();
41
+ /**
42
+ * Convert a FlowDrop workflow + agent config into a full AgentSpecDocument.
43
+ *
44
+ * The document wraps the flow with agent metadata (tools, LLM config, system prompt).
45
+ */
46
+ toAgentSpecDocument(workflow: StandardWorkflow, agentConfig?: AgentConfig, tools?: AgentSpecTool[], llmConfigs?: AgentSpecLLMConfig[]): AgentSpecDocument;
47
+ /**
48
+ * Import a full AgentSpecDocument, extracting the flow and agent metadata.
49
+ */
50
+ fromAgentSpecDocument(doc: AgentSpecDocument): AgentSpecImportResult;
51
+ /**
52
+ * Export a full AgentSpecDocument as JSON string.
53
+ */
54
+ exportJSON(workflow: StandardWorkflow, agentConfig?: AgentConfig, tools?: AgentSpecTool[], llmConfigs?: AgentSpecLLMConfig[]): string;
55
+ /**
56
+ * Import from JSON string containing an AgentSpecDocument.
57
+ */
58
+ importJSON(json: string): AgentSpecImportResult;
59
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Agent-Level Adapter
3
+ *
4
+ * Handles conversion between FlowDrop workflows and full Agent Spec Documents
5
+ * (which wrap a Flow with Agent metadata like tools, LLM config, etc.)
6
+ */
7
+ import { AgentSpecAdapter } from './AgentSpecAdapter.js';
8
+ export class AgentSpecAgentAdapter {
9
+ flowAdapter;
10
+ constructor() {
11
+ this.flowAdapter = new AgentSpecAdapter();
12
+ }
13
+ /**
14
+ * Convert a FlowDrop workflow + agent config into a full AgentSpecDocument.
15
+ *
16
+ * The document wraps the flow with agent metadata (tools, LLM config, system prompt).
17
+ */
18
+ toAgentSpecDocument(workflow, agentConfig, tools, llmConfigs) {
19
+ const flow = this.flowAdapter.toAgentSpec(workflow);
20
+ const doc = {
21
+ flow,
22
+ metadata: {
23
+ 'flowdrop:exported_at': new Date().toISOString()
24
+ }
25
+ };
26
+ // Add agent definition if config provided
27
+ if (agentConfig) {
28
+ const agent = {
29
+ component_type: 'agent',
30
+ name: agentConfig.name,
31
+ description: agentConfig.description,
32
+ system_prompt: agentConfig.systemPrompt,
33
+ tools: agentConfig.tools,
34
+ llm_config: agentConfig.llmConfig
35
+ };
36
+ doc.agent = agent;
37
+ }
38
+ // Add shared tools
39
+ if (tools && tools.length > 0) {
40
+ doc.tools = tools;
41
+ }
42
+ // Add shared LLM configs
43
+ if (llmConfigs && llmConfigs.length > 0) {
44
+ doc.llm_configs = llmConfigs;
45
+ }
46
+ return doc;
47
+ }
48
+ /**
49
+ * Import a full AgentSpecDocument, extracting the flow and agent metadata.
50
+ */
51
+ fromAgentSpecDocument(doc) {
52
+ if (!doc.flow) {
53
+ throw new Error('AgentSpecDocument has no flow definition');
54
+ }
55
+ const workflow = this.flowAdapter.fromAgentSpec(doc.flow);
56
+ const result = {
57
+ workflow
58
+ };
59
+ // Extract agent config
60
+ if (doc.agent) {
61
+ result.agentConfig = {
62
+ name: doc.agent.name,
63
+ description: doc.agent.description,
64
+ systemPrompt: doc.agent.system_prompt,
65
+ tools: doc.agent.tools?.filter((t) => typeof t !== 'string'),
66
+ llmConfig: doc.agent.llm_config && typeof doc.agent.llm_config !== 'string'
67
+ ? doc.agent.llm_config
68
+ : undefined
69
+ };
70
+ }
71
+ // Extract shared declarations
72
+ if (doc.tools)
73
+ result.tools = doc.tools;
74
+ if (doc.llm_configs)
75
+ result.llmConfigs = doc.llm_configs;
76
+ return result;
77
+ }
78
+ /**
79
+ * Export a full AgentSpecDocument as JSON string.
80
+ */
81
+ exportJSON(workflow, agentConfig, tools, llmConfigs) {
82
+ return JSON.stringify(this.toAgentSpecDocument(workflow, agentConfig, tools, llmConfigs), null, 2);
83
+ }
84
+ /**
85
+ * Import from JSON string containing an AgentSpecDocument.
86
+ */
87
+ importJSON(json) {
88
+ const doc = JSON.parse(json);
89
+ return this.fromAgentSpecDocument(doc);
90
+ }
91
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Auto-Layout for Agent Spec Flows
3
+ *
4
+ * Agent Spec has no visual position information. This module assigns
5
+ * positions to imported nodes using a layered layout algorithm:
6
+ *
7
+ * 1. Topological sort from StartNode using control-flow edges
8
+ * 2. Assign layers based on longest path from StartNode
9
+ * 3. Position nodes with configurable spacing
10
+ * 4. Fan out branches vertically from BranchingNode
11
+ */
12
+ import type { AgentSpecFlow } from '../../types/agentspec.js';
13
+ /** Layout configuration */
14
+ export interface AutoLayoutConfig {
15
+ /** Horizontal spacing between layers (px) */
16
+ horizontalSpacing: number;
17
+ /** Vertical spacing between nodes in the same layer (px) */
18
+ verticalSpacing: number;
19
+ /** Starting X position */
20
+ startX: number;
21
+ /** Starting Y position */
22
+ startY: number;
23
+ }
24
+ /**
25
+ * Compute node positions for an Agent Spec flow using layered layout.
26
+ *
27
+ * @param flow - The Agent Spec flow to layout
28
+ * @param config - Optional layout configuration
29
+ * @returns Map of node name to {x, y} position
30
+ */
31
+ export declare function computeAutoLayout(flow: AgentSpecFlow, config?: Partial<AutoLayoutConfig>): Map<string, {
32
+ x: number;
33
+ y: number;
34
+ }>;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Auto-Layout for Agent Spec Flows
3
+ *
4
+ * Agent Spec has no visual position information. This module assigns
5
+ * positions to imported nodes using a layered layout algorithm:
6
+ *
7
+ * 1. Topological sort from StartNode using control-flow edges
8
+ * 2. Assign layers based on longest path from StartNode
9
+ * 3. Position nodes with configurable spacing
10
+ * 4. Fan out branches vertically from BranchingNode
11
+ */
12
+ const DEFAULT_CONFIG = {
13
+ horizontalSpacing: 300,
14
+ verticalSpacing: 150,
15
+ startX: 100,
16
+ startY: 100
17
+ };
18
+ /**
19
+ * Compute node positions for an Agent Spec flow using layered layout.
20
+ *
21
+ * @param flow - The Agent Spec flow to layout
22
+ * @param config - Optional layout configuration
23
+ * @returns Map of node name to {x, y} position
24
+ */
25
+ export function computeAutoLayout(flow, config = {}) {
26
+ const cfg = { ...DEFAULT_CONFIG, ...config };
27
+ const positions = new Map();
28
+ if (flow.nodes.length === 0)
29
+ return positions;
30
+ // Build adjacency list from control-flow edges
31
+ const adjacency = new Map();
32
+ const inDegree = new Map();
33
+ for (const node of flow.nodes) {
34
+ adjacency.set(node.name, []);
35
+ inDegree.set(node.name, 0);
36
+ }
37
+ for (const edge of flow.control_flow_connections) {
38
+ const neighbors = adjacency.get(edge.from_node);
39
+ if (neighbors) {
40
+ neighbors.push(edge.to_node);
41
+ }
42
+ inDegree.set(edge.to_node, (inDegree.get(edge.to_node) || 0) + 1);
43
+ }
44
+ // Also consider data-flow edges for connectivity (but don't affect layering priority)
45
+ if (flow.data_flow_connections) {
46
+ for (const edge of flow.data_flow_connections) {
47
+ if (!adjacency.get(edge.source_node)?.includes(edge.destination_node)) {
48
+ adjacency.get(edge.source_node)?.push(edge.destination_node);
49
+ }
50
+ }
51
+ }
52
+ // Assign layers using longest path from start node (BFS with level tracking)
53
+ const layers = assignLayers(flow.start_node, adjacency, flow.nodes.length);
54
+ // Group nodes by layer
55
+ const layerGroups = new Map();
56
+ for (const [nodeName, layer] of layers) {
57
+ if (!layerGroups.has(layer)) {
58
+ layerGroups.set(layer, []);
59
+ }
60
+ layerGroups.get(layer).push(nodeName);
61
+ }
62
+ // Handle any disconnected nodes (not reachable from start)
63
+ const assignedNodes = new Set(layers.keys());
64
+ const disconnected = [];
65
+ for (const node of flow.nodes) {
66
+ if (!assignedNodes.has(node.name)) {
67
+ disconnected.push(node.name);
68
+ }
69
+ }
70
+ // Place disconnected nodes in a final layer
71
+ if (disconnected.length > 0) {
72
+ const maxLayer = layerGroups.size > 0 ? Math.max(...layerGroups.keys()) + 1 : 0;
73
+ layerGroups.set(maxLayer, disconnected);
74
+ }
75
+ // Sort layers and assign positions
76
+ const sortedLayers = Array.from(layerGroups.keys()).sort((a, b) => a - b);
77
+ for (const layerIndex of sortedLayers) {
78
+ const nodesInLayer = layerGroups.get(layerIndex);
79
+ const x = cfg.startX + layerIndex * cfg.horizontalSpacing;
80
+ // Center nodes vertically
81
+ const totalHeight = (nodesInLayer.length - 1) * cfg.verticalSpacing;
82
+ const startY = cfg.startY - totalHeight / 2;
83
+ for (let i = 0; i < nodesInLayer.length; i++) {
84
+ positions.set(nodesInLayer[i], {
85
+ x,
86
+ y: startY + i * cfg.verticalSpacing
87
+ });
88
+ }
89
+ }
90
+ return positions;
91
+ }
92
+ /**
93
+ * Assign layers using longest path from the start node (modified BFS).
94
+ * This ensures branching nodes fan out properly and convergence points
95
+ * are placed at the correct depth.
96
+ */
97
+ function assignLayers(startNode, adjacency, nodeCount) {
98
+ const layers = new Map();
99
+ layers.set(startNode, 0);
100
+ // Use BFS but take the maximum layer for each node
101
+ // (longest path ensures proper branching layout)
102
+ const queue = [startNode];
103
+ const visited = new Set();
104
+ let iterations = 0;
105
+ const maxIterations = nodeCount * nodeCount + 100; // Safety limit for cycles
106
+ while (queue.length > 0 && iterations < maxIterations) {
107
+ iterations++;
108
+ const current = queue.shift();
109
+ if (visited.has(current))
110
+ continue;
111
+ visited.add(current);
112
+ const currentLayer = layers.get(current) || 0;
113
+ const neighbors = adjacency.get(current) || [];
114
+ for (const neighbor of neighbors) {
115
+ const existingLayer = layers.get(neighbor);
116
+ const newLayer = currentLayer + 1;
117
+ // Take the max layer (longest path)
118
+ if (existingLayer === undefined || newLayer > existingLayer) {
119
+ layers.set(neighbor, newLayer);
120
+ }
121
+ if (!visited.has(neighbor)) {
122
+ queue.push(neighbor);
123
+ }
124
+ }
125
+ }
126
+ return layers;
127
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Agent Spec Component Type Defaults
3
+ *
4
+ * Internal adapter infrastructure for import/export.
5
+ * Provides lightweight defaults per component_type (trigger ports, visual styling)
6
+ * WITHOUT prescribing full node type definitions (data ports, config schemas).
7
+ *
8
+ * Full node type definitions are user-provided via getDefaultAgentSpecNodeTypes()
9
+ * or custom node arrays passed to mountFlowDropApp().
10
+ */
11
+ import type { NodePort } from '../../types/index.js';
12
+ /** Namespace prefix for Agent Spec node type IDs */
13
+ export declare const AGENTSPEC_NAMESPACE = "agentspec";
14
+ /** Standard trigger input port — control flow into a node */
15
+ export declare const TRIGGER_INPUT: NodePort;
16
+ /** Standard trigger output port — control flow out of a node */
17
+ export declare const TRIGGER_OUTPUT: NodePort;
18
+ /**
19
+ * Lightweight defaults for a component_type.
20
+ * Used during import to construct minimal NodeMetadata from Agent Spec JSON.
21
+ * These are NOT full node type definitions — they only contain what the
22
+ * adapter needs to create valid FlowDrop nodes.
23
+ */
24
+ export interface ComponentTypeDefaults {
25
+ /** FlowDrop visual node type (terminal, gateway, default, tool, simple) */
26
+ visualType: string;
27
+ /** Node category for sidebar grouping */
28
+ category: string;
29
+ /** Default display color */
30
+ color: string;
31
+ /** Default icon (MDI format) */
32
+ icon: string;
33
+ /** Badge text for node header */
34
+ badge: string;
35
+ /** Default node name when no name provided */
36
+ defaultName: string;
37
+ /** Default description */
38
+ defaultDescription: string;
39
+ /** Trigger/tool ports to prepend to data inputs during import */
40
+ triggerInputs: NodePort[];
41
+ /** Trigger/tool ports to prepend to data outputs during import */
42
+ triggerOutputs: NodePort[];
43
+ }
44
+ /**
45
+ * Get adapter defaults for a component type.
46
+ * Returns sensible fallbacks for unrecognized types (never throws).
47
+ *
48
+ * @param componentType - The Agent Spec component_type value
49
+ * @returns ComponentTypeDefaults for the type, or fallback for unknown types
50
+ */
51
+ export declare function getComponentTypeDefaults(componentType: string): ComponentTypeDefaults;
52
+ /**
53
+ * Check if a FlowDrop node ID belongs to an Agent Spec node type.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * isAgentSpecNodeId('agentspec.llm_node') // true
58
+ * isAgentSpecNodeId('calculator') // false
59
+ * ```
60
+ */
61
+ export declare function isAgentSpecNodeId(nodeId: string): boolean;
62
+ /**
63
+ * Extract the component_type string from a FlowDrop node type ID.
64
+ * Does not validate against any registry — any string after the namespace prefix is returned.
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * extractComponentType('agentspec.llm_node') // 'llm_node'
69
+ * extractComponentType('agentspec.my_custom') // 'my_custom'
70
+ * extractComponentType('calculator') // undefined
71
+ * ```
72
+ */
73
+ export declare function extractComponentType(nodeTypeId: string): string | undefined;
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Agent Spec Component Type Defaults
3
+ *
4
+ * Internal adapter infrastructure for import/export.
5
+ * Provides lightweight defaults per component_type (trigger ports, visual styling)
6
+ * WITHOUT prescribing full node type definitions (data ports, config schemas).
7
+ *
8
+ * Full node type definitions are user-provided via getDefaultAgentSpecNodeTypes()
9
+ * or custom node arrays passed to mountFlowDropApp().
10
+ */
11
+ // ============================================================================
12
+ // Constants
13
+ // ============================================================================
14
+ /** Namespace prefix for Agent Spec node type IDs */
15
+ export const AGENTSPEC_NAMESPACE = 'agentspec';
16
+ // ============================================================================
17
+ // Standard ports (adapter infrastructure)
18
+ // ============================================================================
19
+ /** Standard trigger input port — control flow into a node */
20
+ export const TRIGGER_INPUT = {
21
+ id: 'trigger',
22
+ name: 'Trigger',
23
+ type: 'input',
24
+ dataType: 'trigger',
25
+ required: false,
26
+ description: 'Control flow input'
27
+ };
28
+ /** Standard trigger output port — control flow out of a node */
29
+ export const TRIGGER_OUTPUT = {
30
+ id: 'trigger',
31
+ name: 'Trigger',
32
+ type: 'output',
33
+ dataType: 'trigger',
34
+ required: false,
35
+ description: 'Control flow output'
36
+ };
37
+ /** Tool input port for tool_node */
38
+ const TOOL_INPUT = {
39
+ id: 'tool',
40
+ name: 'Tool',
41
+ type: 'input',
42
+ dataType: 'tool',
43
+ required: false,
44
+ description: 'Tool connection'
45
+ };
46
+ /** Tool output port for tool_node */
47
+ const TOOL_OUTPUT = {
48
+ id: 'tool',
49
+ name: 'Tool',
50
+ type: 'output',
51
+ dataType: 'tool',
52
+ description: 'Tool passthrough'
53
+ };
54
+ // ============================================================================
55
+ // Defaults mapping
56
+ // ============================================================================
57
+ const COMPONENT_TYPE_DEFAULTS = new Map([
58
+ [
59
+ 'start_node',
60
+ {
61
+ visualType: 'terminal',
62
+ category: 'triggers',
63
+ color: '#22c55e',
64
+ icon: 'mdi:play-circle',
65
+ badge: 'START',
66
+ defaultName: 'Start',
67
+ defaultDescription: 'Flow entry point. Defines the initial inputs for the flow.',
68
+ triggerInputs: [],
69
+ triggerOutputs: [TRIGGER_OUTPUT]
70
+ }
71
+ ],
72
+ [
73
+ 'end_node',
74
+ {
75
+ visualType: 'terminal',
76
+ category: 'outputs',
77
+ color: '#ef4444',
78
+ icon: 'mdi:stop-circle',
79
+ badge: 'END',
80
+ defaultName: 'End',
81
+ defaultDescription: 'Flow exit point. Defines the final outputs of the flow.',
82
+ triggerInputs: [TRIGGER_INPUT],
83
+ triggerOutputs: []
84
+ }
85
+ ],
86
+ [
87
+ 'llm_node',
88
+ {
89
+ visualType: 'default',
90
+ category: 'ai',
91
+ color: '#8b5cf6',
92
+ icon: 'mdi:brain',
93
+ badge: 'LLM',
94
+ defaultName: 'LLM',
95
+ defaultDescription: 'Generate text using a large language model with configurable prompts.',
96
+ triggerInputs: [TRIGGER_INPUT],
97
+ triggerOutputs: [TRIGGER_OUTPUT]
98
+ }
99
+ ],
100
+ [
101
+ 'branching_node',
102
+ {
103
+ visualType: 'gateway',
104
+ category: 'logic',
105
+ color: '#f59e0b',
106
+ icon: 'mdi:source-branch',
107
+ badge: 'BRANCH',
108
+ defaultName: 'Branch',
109
+ defaultDescription: 'Route execution to different paths based on conditions.',
110
+ triggerInputs: [TRIGGER_INPUT],
111
+ triggerOutputs: []
112
+ }
113
+ ],
114
+ [
115
+ 'tool_node',
116
+ {
117
+ visualType: 'tool',
118
+ category: 'tools',
119
+ color: '#06b6d4',
120
+ icon: 'mdi:wrench',
121
+ badge: 'TOOL',
122
+ defaultName: 'Tool',
123
+ defaultDescription: 'Execute a tool function with inputs and receive outputs.',
124
+ triggerInputs: [TRIGGER_INPUT, TOOL_INPUT],
125
+ triggerOutputs: [TRIGGER_OUTPUT, TOOL_OUTPUT]
126
+ }
127
+ ],
128
+ [
129
+ 'api_node',
130
+ {
131
+ visualType: 'default',
132
+ category: 'data',
133
+ color: '#3b82f6',
134
+ icon: 'mdi:api',
135
+ badge: 'API',
136
+ defaultName: 'API Call',
137
+ defaultDescription: 'Make an HTTP API call with configurable endpoint, method, and headers.',
138
+ triggerInputs: [TRIGGER_INPUT],
139
+ triggerOutputs: [TRIGGER_OUTPUT]
140
+ }
141
+ ],
142
+ [
143
+ 'agent_node',
144
+ {
145
+ visualType: 'default',
146
+ category: 'agents',
147
+ color: '#ec4899',
148
+ icon: 'mdi:robot',
149
+ badge: 'AGENT',
150
+ defaultName: 'Agent',
151
+ defaultDescription: 'Run a multi-round agent conversation within the flow.',
152
+ triggerInputs: [TRIGGER_INPUT],
153
+ triggerOutputs: [TRIGGER_OUTPUT]
154
+ }
155
+ ],
156
+ [
157
+ 'flow_node',
158
+ {
159
+ visualType: 'simple',
160
+ category: 'processing',
161
+ color: '#14b8a6',
162
+ icon: 'mdi:sitemap',
163
+ badge: 'FLOW',
164
+ defaultName: 'Sub-Flow',
165
+ defaultDescription: 'Execute another flow as a sub-routine within this flow.',
166
+ triggerInputs: [TRIGGER_INPUT],
167
+ triggerOutputs: [TRIGGER_OUTPUT]
168
+ }
169
+ ],
170
+ [
171
+ 'map_node',
172
+ {
173
+ visualType: 'default',
174
+ category: 'processing',
175
+ color: '#f97316',
176
+ icon: 'mdi:map-marker-path',
177
+ badge: 'MAP',
178
+ defaultName: 'Map',
179
+ defaultDescription: 'Apply a flow or operation to each item in a collection (map-reduce).',
180
+ triggerInputs: [TRIGGER_INPUT],
181
+ triggerOutputs: [TRIGGER_OUTPUT]
182
+ }
183
+ ]
184
+ ]);
185
+ /** Fallback defaults for unrecognized component types */
186
+ const UNKNOWN_DEFAULTS = {
187
+ visualType: 'default',
188
+ category: 'processing',
189
+ color: '#6b7280',
190
+ icon: 'mdi:puzzle',
191
+ badge: '',
192
+ defaultName: 'Unknown',
193
+ defaultDescription: 'Agent Spec node',
194
+ triggerInputs: [TRIGGER_INPUT],
195
+ triggerOutputs: [TRIGGER_OUTPUT]
196
+ };
197
+ // ============================================================================
198
+ // Public API
199
+ // ============================================================================
200
+ /**
201
+ * Get adapter defaults for a component type.
202
+ * Returns sensible fallbacks for unrecognized types (never throws).
203
+ *
204
+ * @param componentType - The Agent Spec component_type value
205
+ * @returns ComponentTypeDefaults for the type, or fallback for unknown types
206
+ */
207
+ export function getComponentTypeDefaults(componentType) {
208
+ return COMPONENT_TYPE_DEFAULTS.get(componentType) ?? UNKNOWN_DEFAULTS;
209
+ }
210
+ /**
211
+ * Check if a FlowDrop node ID belongs to an Agent Spec node type.
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * isAgentSpecNodeId('agentspec.llm_node') // true
216
+ * isAgentSpecNodeId('calculator') // false
217
+ * ```
218
+ */
219
+ export function isAgentSpecNodeId(nodeId) {
220
+ return nodeId.startsWith(`${AGENTSPEC_NAMESPACE}.`);
221
+ }
222
+ /**
223
+ * Extract the component_type string from a FlowDrop node type ID.
224
+ * Does not validate against any registry — any string after the namespace prefix is returned.
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * extractComponentType('agentspec.llm_node') // 'llm_node'
229
+ * extractComponentType('agentspec.my_custom') // 'my_custom'
230
+ * extractComponentType('calculator') // undefined
231
+ * ```
232
+ */
233
+ export function extractComponentType(nodeTypeId) {
234
+ if (!isAgentSpecNodeId(nodeTypeId))
235
+ return undefined;
236
+ const componentType = nodeTypeId.slice(AGENTSPEC_NAMESPACE.length + 1);
237
+ return componentType || undefined;
238
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Agent Spec Default Node Types
3
+ *
4
+ * Provides optional starter node type definitions for the Agent Spec format.
5
+ * These are full NodeMetadata objects with visual type, category, default ports,
6
+ * config schema, and icon — suitable for populating the sidebar.
7
+ *
8
+ * These definitions are NOT required by the adapter — the adapter uses
9
+ * componentTypeDefaults.ts for import/export infrastructure.
10
+ * Users can provide their own node definitions instead.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { getDefaultAgentSpecNodeTypes } from '@d34dman/flowdrop/core';
15
+ *
16
+ * mountFlowDropApp(container, {
17
+ * nodes: getDefaultAgentSpecNodeTypes(), // or your own definitions
18
+ * });
19
+ * ```
20
+ */
21
+ import type { NodeMetadata, NodePort } from '../../types/index.js';
22
+ import type { AgentSpecNodeComponentType } from '../../types/agentspec.js';
23
+ /**
24
+ * Get FlowDrop NodeMetadata for an Agent Spec component type.
25
+ *
26
+ * @param componentType - The Agent Spec component_type value
27
+ * @returns NodeMetadata for the component type, or undefined if not found
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const metadata = getAgentSpecNodeMetadata('llm_node');
32
+ * // Returns NodeMetadata with id='agentspec.llm_node', type='default', category='ai', etc.
33
+ * ```
34
+ */
35
+ export declare function getAgentSpecNodeMetadata(componentType: AgentSpecNodeComponentType): NodeMetadata | undefined;
36
+ /**
37
+ * Get all default Agent Spec node types as FlowDrop NodeMetadata.
38
+ * These are starter templates — users can provide their own node types instead.
39
+ *
40
+ * @returns Array of NodeMetadata for all 9 default Agent Spec node types
41
+ */
42
+ export declare function getDefaultAgentSpecNodeTypes(): NodeMetadata[];
43
+ /**
44
+ * Get a copy of the NodeMetadata for a component type with custom inputs/outputs.
45
+ * Used during import to create node metadata that matches the Agent Spec definition's
46
+ * actual ports rather than the defaults.
47
+ *
48
+ * @param componentType - The Agent Spec component_type value
49
+ * @param inputs - Custom input ports
50
+ * @param outputs - Custom output ports
51
+ * @returns A new NodeMetadata with the custom ports merged in
52
+ */
53
+ export declare function createAgentSpecNodeMetadata(componentType: AgentSpecNodeComponentType, inputs?: NodePort[], outputs?: NodePort[]): NodeMetadata | undefined;