@flowdrop/flowdrop 1.3.0 → 1.5.0
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 +68 -24
- package/dist/adapters/WorkflowAdapter.js +2 -22
- package/dist/adapters/agentspec/autoLayout.d.ts +51 -5
- package/dist/adapters/agentspec/autoLayout.js +120 -23
- package/dist/chat/commandClassifier.d.ts +19 -0
- package/dist/chat/commandClassifier.js +30 -0
- package/dist/chat/index.d.ts +27 -0
- package/dist/chat/index.js +32 -0
- package/dist/chat/responseParser.d.ts +21 -0
- package/dist/chat/responseParser.js +87 -0
- package/dist/commands/batch.d.ts +18 -0
- package/dist/commands/batch.js +56 -0
- package/dist/commands/executor.d.ts +37 -0
- package/dist/commands/executor.js +1044 -0
- package/dist/commands/index.d.ts +14 -0
- package/dist/commands/index.js +17 -0
- package/dist/commands/parser.d.ts +16 -0
- package/dist/commands/parser.js +278 -0
- package/dist/commands/positioner.d.ts +19 -0
- package/dist/commands/positioner.js +33 -0
- package/dist/commands/storeIntegration.svelte.d.ts +16 -0
- package/dist/commands/storeIntegration.svelte.js +67 -0
- package/dist/commands/types.d.ts +343 -0
- package/dist/commands/types.js +45 -0
- package/dist/components/App.svelte +431 -17
- package/dist/components/App.svelte.d.ts +10 -0
- package/dist/components/CanvasBanner.stories.svelte +6 -2
- package/dist/components/CanvasController.svelte +38 -0
- package/dist/components/CanvasController.svelte.d.ts +32 -0
- package/dist/components/ConfigMappingRow.svelte +130 -0
- package/dist/components/ConfigMappingRow.svelte.d.ts +8 -0
- package/dist/components/ConfigPanel.svelte +56 -7
- package/dist/components/ConfigPanel.svelte.d.ts +2 -0
- package/dist/components/FlowDropEdge.svelte +8 -57
- package/dist/components/Logo.svelte +14 -14
- package/dist/components/LogsSidebar.svelte +5 -5
- package/dist/components/Navbar.svelte +58 -10
- package/dist/components/Navbar.svelte.d.ts +7 -0
- package/dist/components/NodeSidebar.svelte +238 -362
- package/dist/components/NodeSwapPicker.svelte +537 -0
- package/dist/components/NodeSwapPicker.svelte.d.ts +16 -0
- package/dist/components/PortMappingRow.svelte +209 -0
- package/dist/components/PortMappingRow.svelte.d.ts +12 -0
- package/dist/components/SwapMappingEditor.svelte +550 -0
- package/dist/components/SwapMappingEditor.svelte.d.ts +12 -0
- package/dist/components/WorkflowEditor.svelte +99 -4
- package/dist/components/WorkflowEditor.svelte.d.ts +8 -0
- package/dist/components/chat/AIChatPanel.svelte +658 -0
- package/dist/components/chat/AIChatPanel.svelte.d.ts +13 -0
- package/dist/components/chat/CommandPreview.svelte +184 -0
- package/dist/components/chat/CommandPreview.svelte.d.ts +9 -0
- package/dist/components/console/CommandConsole.stories.svelte +93 -0
- package/dist/components/console/CommandConsole.stories.svelte.d.ts +27 -0
- package/dist/components/console/CommandConsole.svelte +259 -0
- package/dist/components/console/CommandConsole.svelte.d.ts +11 -0
- package/dist/components/console/ConsoleAutocomplete.svelte +139 -0
- package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +21 -0
- package/dist/components/console/ConsoleInput.svelte +712 -0
- package/dist/components/console/ConsoleInput.svelte.d.ts +16 -0
- package/dist/components/console/ConsoleOutput.svelte +121 -0
- package/dist/components/console/ConsoleOutput.svelte.d.ts +11 -0
- package/dist/components/console/formatters.d.ts +26 -0
- package/dist/components/console/formatters.js +118 -0
- package/dist/components/interrupt/index.d.ts +1 -0
- package/dist/components/interrupt/index.js +1 -0
- package/dist/components/nodes/SimpleNode.stories.svelte +64 -0
- package/dist/components/nodes/SimpleNode.svelte +27 -11
- package/dist/components/nodes/SquareNode.stories.svelte +45 -0
- package/dist/components/nodes/SquareNode.svelte +27 -11
- package/dist/components/nodes/WorkflowNode.stories.svelte +63 -0
- package/dist/config/endpoints.d.ts +8 -0
- package/dist/config/endpoints.js +5 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +9 -0
- package/dist/editor/index.d.ts +3 -1
- package/dist/editor/index.js +4 -2
- package/dist/helpers/proximityConnect.js +8 -1
- package/dist/helpers/workflowEditorHelper.d.ts +3 -53
- package/dist/helpers/workflowEditorHelper.js +13 -228
- package/dist/playground/index.d.ts +1 -1
- package/dist/playground/index.js +1 -1
- package/dist/schemas/v1/workflow.schema.json +107 -22
- package/dist/services/chatService.d.ts +65 -0
- package/dist/services/chatService.js +131 -0
- package/dist/services/historyService.d.ts +6 -4
- package/dist/services/historyService.js +21 -6
- package/dist/skins/slate.js +16 -0
- package/dist/stores/interruptStore.svelte.js +6 -1
- package/dist/stores/playgroundStore.svelte.d.ts +1 -1
- package/dist/stores/playgroundStore.svelte.js +11 -2
- package/dist/stores/portCoordinateStore.svelte.d.ts +4 -0
- package/dist/stores/portCoordinateStore.svelte.js +20 -26
- package/dist/stores/workflowStore.svelte.d.ts +31 -2
- package/dist/stores/workflowStore.svelte.js +84 -64
- package/dist/stories/EdgeDecorator.svelte +4 -4
- package/dist/styles/base.css +48 -0
- package/dist/svelte-app.d.ts +7 -1
- package/dist/svelte-app.js +4 -1
- package/dist/types/chat.d.ts +63 -0
- package/dist/types/chat.js +9 -0
- package/dist/types/events.d.ts +28 -2
- package/dist/types/events.js +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/settings.d.ts +6 -0
- package/dist/types/settings.js +3 -0
- package/dist/utils/edgeStyling.d.ts +42 -0
- package/dist/utils/edgeStyling.js +176 -0
- package/dist/utils/nodeIds.d.ts +31 -0
- package/dist/utils/nodeIds.js +42 -0
- package/dist/utils/nodeSwap.d.ts +221 -0
- package/dist/utils/nodeSwap.js +686 -0
- package/package.json +6 -1
- package/dist/helpers/nodeLayoutHelper.d.ts +0 -14
- package/dist/helpers/nodeLayoutHelper.js +0 -19
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowDrop Command DSL
|
|
3
|
+
*
|
|
4
|
+
* A deterministic command language for programmatic workflow manipulation.
|
|
5
|
+
* Excludes storeIntegration.svelte.ts (Svelte-coupled, import separately).
|
|
6
|
+
*
|
|
7
|
+
* @module commands
|
|
8
|
+
*/
|
|
9
|
+
export type { AddNodeCommand, DeleteNodeCommand, RenameNodeCommand, SetConfigCommand, GetConfigCommand, ConnectCommand, DisconnectPortsCommand, DisconnectNodeCommand, ListNodesCommand, ListEdgesCommand, ListTypesCommand, InfoCommand, UndoCommand, RedoCommand, ConfigOpenCommand, SelectNodeCommand, HelpCommand, ClearCommand, SwapNodeCommand, MoveNodeCommand, AutoLayoutCommand, BeautifyLayoutCommand, CanvasFitViewCommand, CanvasZoomInCommand, CanvasZoomOutCommand, CanvasZoomToCommand, CanvasPanToCommand, CanvasResetViewCommand, Command, ParseResult, CommandErrorCode, AddNodeResultData, ListNodesResultData, ListEdgesResultData, ListTypesResultData, InfoResultData, GetConfigResultData, SetConfigResultData, HelpResultData, SwapNodeResultData, CommandResultData, CommandResultOk, CommandResultError, CommandResult, BatchResult, UIAction, CommandDispatch, CommandContext, } from "./types.js";
|
|
10
|
+
export { buildTypeMap } from "./types.js";
|
|
11
|
+
export { parseCommand } from "./parser.js";
|
|
12
|
+
export { executeCommand, toShortId, toShortTypeId, resolveNode, COMMAND_HELP, } from "./executor.js";
|
|
13
|
+
export { executeBatch } from "./batch.js";
|
|
14
|
+
export { computeAutoPosition } from "./positioner.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowDrop Command DSL
|
|
3
|
+
*
|
|
4
|
+
* A deterministic command language for programmatic workflow manipulation.
|
|
5
|
+
* Excludes storeIntegration.svelte.ts (Svelte-coupled, import separately).
|
|
6
|
+
*
|
|
7
|
+
* @module commands
|
|
8
|
+
*/
|
|
9
|
+
export { buildTypeMap } from "./types.js";
|
|
10
|
+
// Parser
|
|
11
|
+
export { parseCommand } from "./parser.js";
|
|
12
|
+
// Executor
|
|
13
|
+
export { executeCommand, toShortId, toShortTypeId, resolveNode, COMMAND_HELP, } from "./executor.js";
|
|
14
|
+
// Batch executor
|
|
15
|
+
export { executeBatch } from "./batch.js";
|
|
16
|
+
// Positioner
|
|
17
|
+
export { computeAutoPosition } from "./positioner.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses DSL command strings into typed Command objects using
|
|
5
|
+
* regex-based pattern matching with ordered rules (first match wins).
|
|
6
|
+
*
|
|
7
|
+
* @module commands/parser
|
|
8
|
+
*/
|
|
9
|
+
import type { ParseResult } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Parse a command string into a typed Command object.
|
|
12
|
+
*
|
|
13
|
+
* Command verbs are case-insensitive; identifiers are case-sensitive.
|
|
14
|
+
* Returns ParseResult with ok: true on success, ok: false on failure.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseCommand(input: string): ParseResult;
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses DSL command strings into typed Command objects using
|
|
5
|
+
* regex-based pattern matching with ordered rules (first match wins).
|
|
6
|
+
*
|
|
7
|
+
* @module commands/parser
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Parse a coordinate pair like "200,300" or "-50, 100"
|
|
11
|
+
*/
|
|
12
|
+
function parseCoords(x, y) {
|
|
13
|
+
return { x: Number(x), y: Number(y) };
|
|
14
|
+
}
|
|
15
|
+
const rules = [
|
|
16
|
+
// add <type> at <x>,<y>
|
|
17
|
+
{
|
|
18
|
+
pattern: /^add\s+(\S+)\s+at\s+(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)$/i,
|
|
19
|
+
parse: (m) => ({
|
|
20
|
+
type: "add_node",
|
|
21
|
+
nodeTypeId: m[1],
|
|
22
|
+
position: parseCoords(m[2], m[3]),
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
// add <type>
|
|
26
|
+
{
|
|
27
|
+
pattern: /^add\s+(\S+)$/i,
|
|
28
|
+
parse: (m) => ({
|
|
29
|
+
type: "add_node",
|
|
30
|
+
nodeTypeId: m[1],
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
// delete <nodeId>
|
|
34
|
+
{
|
|
35
|
+
pattern: /^delete\s+(\S+)$/i,
|
|
36
|
+
parse: (m) => ({
|
|
37
|
+
type: "delete_node",
|
|
38
|
+
nodeId: m[1],
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
// rename <nodeId> <label...>
|
|
42
|
+
{
|
|
43
|
+
pattern: /^rename\s+(\S+)\s+(.+)$/i,
|
|
44
|
+
parse: (m) => ({
|
|
45
|
+
type: "rename_node",
|
|
46
|
+
nodeId: m[1],
|
|
47
|
+
label: m[2].trim(),
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
// set <nodeId>:<key> """<multiline value>"""
|
|
51
|
+
{
|
|
52
|
+
pattern: /^set\s+(\S+?):(\S+)\s+"""([\s\S]*)"""$/,
|
|
53
|
+
parse: (m) => ({
|
|
54
|
+
type: "set_config",
|
|
55
|
+
nodeId: m[1],
|
|
56
|
+
key: m[2],
|
|
57
|
+
// trim one leading/trailing newline added by the textarea wrapper
|
|
58
|
+
value: m[3].replace(/^\n/, "").replace(/\n$/, ""),
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
// set <nodeId>:<key> <value...>
|
|
62
|
+
{
|
|
63
|
+
pattern: /^set\s+(\S+?):(\S+)\s+(.+)$/i,
|
|
64
|
+
parse: (m) => ({
|
|
65
|
+
type: "set_config",
|
|
66
|
+
nodeId: m[1],
|
|
67
|
+
key: m[2],
|
|
68
|
+
value: m[3],
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
// get <nodeId>:<key>
|
|
72
|
+
{
|
|
73
|
+
pattern: /^get\s+(\S+?):(\S+)$/i,
|
|
74
|
+
parse: (m) => ({
|
|
75
|
+
type: "get_config",
|
|
76
|
+
nodeId: m[1],
|
|
77
|
+
key: m[2],
|
|
78
|
+
}),
|
|
79
|
+
},
|
|
80
|
+
// info <nodeId>
|
|
81
|
+
{
|
|
82
|
+
pattern: /^info\s+(\S+)$/i,
|
|
83
|
+
parse: (m) => ({
|
|
84
|
+
type: "info",
|
|
85
|
+
nodeId: m[1],
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
// config <nodeId>
|
|
89
|
+
{
|
|
90
|
+
pattern: /^config\s+(\S+)$/i,
|
|
91
|
+
parse: (m) => ({
|
|
92
|
+
type: "config_open",
|
|
93
|
+
nodeId: m[1],
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
// select <nodeId>
|
|
97
|
+
{
|
|
98
|
+
pattern: /^select\s+(\S+)$/i,
|
|
99
|
+
parse: (m) => ({
|
|
100
|
+
type: "select_node",
|
|
101
|
+
nodeId: m[1],
|
|
102
|
+
}),
|
|
103
|
+
},
|
|
104
|
+
// connect <nid>:<port> to <nid>:<port>
|
|
105
|
+
{
|
|
106
|
+
pattern: /^connect\s+(\S+?):(\S+)\s+to\s+(\S+?):(\S+)$/i,
|
|
107
|
+
parse: (m) => ({
|
|
108
|
+
type: "connect",
|
|
109
|
+
sourceNodeId: m[1],
|
|
110
|
+
sourcePort: m[2],
|
|
111
|
+
targetNodeId: m[3],
|
|
112
|
+
targetPort: m[4],
|
|
113
|
+
}),
|
|
114
|
+
},
|
|
115
|
+
// disconnect <nid>:<port> from <nid>:<port>
|
|
116
|
+
{
|
|
117
|
+
pattern: /^disconnect\s+(\S+?):(\S+)\s+from\s+(\S+?):(\S+)$/i,
|
|
118
|
+
parse: (m) => ({
|
|
119
|
+
type: "disconnect_ports",
|
|
120
|
+
sourceNodeId: m[1],
|
|
121
|
+
sourcePort: m[2],
|
|
122
|
+
targetNodeId: m[3],
|
|
123
|
+
targetPort: m[4],
|
|
124
|
+
}),
|
|
125
|
+
},
|
|
126
|
+
// disconnect <nodeId> (disconnect all)
|
|
127
|
+
{
|
|
128
|
+
pattern: /^disconnect\s+(\S+)$/i,
|
|
129
|
+
parse: (m) => ({
|
|
130
|
+
type: "disconnect_node",
|
|
131
|
+
nodeId: m[1],
|
|
132
|
+
}),
|
|
133
|
+
},
|
|
134
|
+
// list nodes
|
|
135
|
+
{
|
|
136
|
+
pattern: /^list\s+nodes$/i,
|
|
137
|
+
parse: () => ({ type: "list_nodes" }),
|
|
138
|
+
},
|
|
139
|
+
// list edges
|
|
140
|
+
{
|
|
141
|
+
pattern: /^list\s+edges$/i,
|
|
142
|
+
parse: () => ({ type: "list_edges" }),
|
|
143
|
+
},
|
|
144
|
+
// list types
|
|
145
|
+
{
|
|
146
|
+
pattern: /^list\s+types$/i,
|
|
147
|
+
parse: () => ({ type: "list_types" }),
|
|
148
|
+
},
|
|
149
|
+
// undo
|
|
150
|
+
{
|
|
151
|
+
pattern: /^undo$/i,
|
|
152
|
+
parse: () => ({ type: "undo" }),
|
|
153
|
+
},
|
|
154
|
+
// redo
|
|
155
|
+
{
|
|
156
|
+
pattern: /^redo$/i,
|
|
157
|
+
parse: () => ({ type: "redo" }),
|
|
158
|
+
},
|
|
159
|
+
// help <command>
|
|
160
|
+
{
|
|
161
|
+
pattern: /^help\s+(\S+)$/i,
|
|
162
|
+
parse: (m) => ({
|
|
163
|
+
type: "help",
|
|
164
|
+
command: m[1],
|
|
165
|
+
}),
|
|
166
|
+
},
|
|
167
|
+
// help
|
|
168
|
+
{
|
|
169
|
+
pattern: /^help$/i,
|
|
170
|
+
parse: () => ({ type: "help" }),
|
|
171
|
+
},
|
|
172
|
+
// clear
|
|
173
|
+
{
|
|
174
|
+
pattern: /^clear$/i,
|
|
175
|
+
parse: () => ({ type: "clear" }),
|
|
176
|
+
},
|
|
177
|
+
// swap <nodeId> with <type> (Phase 2)
|
|
178
|
+
{
|
|
179
|
+
pattern: /^swap\s+(\S+)\s+with\s+(\S+)$/i,
|
|
180
|
+
parse: (m) => ({
|
|
181
|
+
type: "swap_node",
|
|
182
|
+
nodeId: m[1],
|
|
183
|
+
newTypeId: m[2],
|
|
184
|
+
}),
|
|
185
|
+
},
|
|
186
|
+
// move <nodeId> to <x>,<y> (Phase 2)
|
|
187
|
+
{
|
|
188
|
+
pattern: /^move\s+(\S+)\s+to\s+(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)$/i,
|
|
189
|
+
parse: (m) => ({
|
|
190
|
+
type: "move_node",
|
|
191
|
+
nodeId: m[1],
|
|
192
|
+
position: parseCoords(m[2], m[3]),
|
|
193
|
+
}),
|
|
194
|
+
},
|
|
195
|
+
// layout auto [--direction horizontal|vertical] (Phase 2)
|
|
196
|
+
{
|
|
197
|
+
pattern: /^layout\s+auto\s+--direction\s+(horizontal|vertical)$/i,
|
|
198
|
+
parse: (m) => ({
|
|
199
|
+
type: "auto_layout",
|
|
200
|
+
direction: m[1].toLowerCase(),
|
|
201
|
+
}),
|
|
202
|
+
},
|
|
203
|
+
// layout auto (Phase 2)
|
|
204
|
+
{
|
|
205
|
+
pattern: /^layout\s+auto$/i,
|
|
206
|
+
parse: () => ({ type: "auto_layout" }),
|
|
207
|
+
},
|
|
208
|
+
// layout beautify — preserve relative positions, normalize spacing
|
|
209
|
+
{
|
|
210
|
+
pattern: /^layout\s+beautify$/i,
|
|
211
|
+
parse: () => ({ type: "beautify_layout" }),
|
|
212
|
+
},
|
|
213
|
+
// canvas fitview | canvas fit
|
|
214
|
+
{
|
|
215
|
+
pattern: /^canvas\s+fit(?:\s*view)?$/i,
|
|
216
|
+
parse: () => ({ type: "canvas_fit_view" }),
|
|
217
|
+
},
|
|
218
|
+
// canvas zoom in
|
|
219
|
+
{
|
|
220
|
+
pattern: /^canvas\s+zoom\s+in$/i,
|
|
221
|
+
parse: () => ({ type: "canvas_zoom_in" }),
|
|
222
|
+
},
|
|
223
|
+
// canvas zoom out
|
|
224
|
+
{
|
|
225
|
+
pattern: /^canvas\s+zoom\s+out$/i,
|
|
226
|
+
parse: () => ({ type: "canvas_zoom_out" }),
|
|
227
|
+
},
|
|
228
|
+
// canvas zoom <level>
|
|
229
|
+
{
|
|
230
|
+
pattern: /^canvas\s+zoom\s+(\d+(?:\.\d+)?)$/i,
|
|
231
|
+
parse: (m) => ({ type: "canvas_zoom_to", level: Number(m[1]) }),
|
|
232
|
+
},
|
|
233
|
+
// canvas pan <x>,<y>
|
|
234
|
+
{
|
|
235
|
+
pattern: /^canvas\s+pan\s+(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)$/i,
|
|
236
|
+
parse: (m) => ({
|
|
237
|
+
type: "canvas_pan_to",
|
|
238
|
+
position: parseCoords(m[1], m[2]),
|
|
239
|
+
}),
|
|
240
|
+
},
|
|
241
|
+
// canvas reset
|
|
242
|
+
{
|
|
243
|
+
pattern: /^canvas\s+reset$/i,
|
|
244
|
+
parse: () => ({ type: "canvas_reset_view" }),
|
|
245
|
+
},
|
|
246
|
+
];
|
|
247
|
+
// ============================================================================
|
|
248
|
+
// Public API
|
|
249
|
+
// ============================================================================
|
|
250
|
+
/**
|
|
251
|
+
* Parse a command string into a typed Command object.
|
|
252
|
+
*
|
|
253
|
+
* Command verbs are case-insensitive; identifiers are case-sensitive.
|
|
254
|
+
* Returns ParseResult with ok: true on success, ok: false on failure.
|
|
255
|
+
*/
|
|
256
|
+
export function parseCommand(input) {
|
|
257
|
+
const trimmed = input.trim();
|
|
258
|
+
if (!trimmed) {
|
|
259
|
+
return { ok: false, error: "Empty command", input };
|
|
260
|
+
}
|
|
261
|
+
for (const rule of rules) {
|
|
262
|
+
const match = trimmed.match(rule.pattern);
|
|
263
|
+
if (match) {
|
|
264
|
+
return { ok: true, command: rule.parse(match) };
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Extract verb for better error message
|
|
268
|
+
const verb = trimmed.split(/\s+/)[0].toLowerCase();
|
|
269
|
+
const knownVerbs = [
|
|
270
|
+
"add", "delete", "rename", "set", "get", "info", "config",
|
|
271
|
+
"select", "connect", "disconnect", "list", "undo", "redo",
|
|
272
|
+
"help", "clear", "swap", "move", "layout", "canvas",
|
|
273
|
+
];
|
|
274
|
+
if (knownVerbs.includes(verb)) {
|
|
275
|
+
return { ok: false, error: `Invalid syntax for '${verb}' command`, input };
|
|
276
|
+
}
|
|
277
|
+
return { ok: false, error: `Unknown command: ${verb}`, input };
|
|
278
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-positioner for command-created nodes.
|
|
3
|
+
*
|
|
4
|
+
* Computes a reasonable canvas position when no explicit coordinates are given.
|
|
5
|
+
*
|
|
6
|
+
* @module commands/positioner
|
|
7
|
+
*/
|
|
8
|
+
import type { WorkflowNode } from "../types/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Computes an auto-position for a new node based on existing nodes.
|
|
11
|
+
*
|
|
12
|
+
* - Empty canvas: returns `{ x: 100, y: 100 }`.
|
|
13
|
+
* - Non-empty canvas: places new node 250px to the right of the rightmost node,
|
|
14
|
+
* at the same y as the rightmost node.
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeAutoPosition(existingNodes: Pick<WorkflowNode, "position">[]): {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-positioner for command-created nodes.
|
|
3
|
+
*
|
|
4
|
+
* Computes a reasonable canvas position when no explicit coordinates are given.
|
|
5
|
+
*
|
|
6
|
+
* @module commands/positioner
|
|
7
|
+
*/
|
|
8
|
+
/** Default starting position for the first node on an empty canvas. */
|
|
9
|
+
const DEFAULT_START = { x: 100, y: 100 };
|
|
10
|
+
/** Horizontal gap between the rightmost existing node and a new node. */
|
|
11
|
+
const HORIZONTAL_GAP = 250;
|
|
12
|
+
/**
|
|
13
|
+
* Computes an auto-position for a new node based on existing nodes.
|
|
14
|
+
*
|
|
15
|
+
* - Empty canvas: returns `{ x: 100, y: 100 }`.
|
|
16
|
+
* - Non-empty canvas: places new node 250px to the right of the rightmost node,
|
|
17
|
+
* at the same y as the rightmost node.
|
|
18
|
+
*/
|
|
19
|
+
export function computeAutoPosition(existingNodes) {
|
|
20
|
+
if (existingNodes.length === 0) {
|
|
21
|
+
return { ...DEFAULT_START };
|
|
22
|
+
}
|
|
23
|
+
let rightmost = existingNodes[0];
|
|
24
|
+
for (const node of existingNodes) {
|
|
25
|
+
if (node.position.x > rightmost.position.x) {
|
|
26
|
+
rightmost = node;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
x: rightmost.position.x + HORIZONTAL_GAP,
|
|
31
|
+
y: rightmost.position.y,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store Integration Bridge
|
|
3
|
+
*
|
|
4
|
+
* Bridges the command system to the live Svelte stores.
|
|
5
|
+
* This is the only Svelte-coupled file in commands/.
|
|
6
|
+
*/
|
|
7
|
+
import { type CommandContext, type UIAction } from "./types.js";
|
|
8
|
+
import type { NodeMetadata } from "../types/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Creates a CommandContext that bridges the command system to the live Svelte stores.
|
|
11
|
+
*
|
|
12
|
+
* @param nodeTypes - Available node type definitions
|
|
13
|
+
* @param onUIAction - Optional callback for UI-side actions (open config panel, select node)
|
|
14
|
+
* @returns CommandContext connected to live stores, or null if no workflow is loaded
|
|
15
|
+
*/
|
|
16
|
+
export declare function createStoreCommandContext(nodeTypes: NodeMetadata[], onUIAction?: (action: UIAction) => void): CommandContext | null;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store Integration Bridge
|
|
3
|
+
*
|
|
4
|
+
* Bridges the command system to the live Svelte stores.
|
|
5
|
+
* This is the only Svelte-coupled file in commands/.
|
|
6
|
+
*/
|
|
7
|
+
import { getWorkflowStore, workflowActions, } from "../stores/workflowStore.svelte.js";
|
|
8
|
+
import { historyService } from "../services/historyService.js";
|
|
9
|
+
import { buildTypeMap, } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Creates a CommandContext that bridges the command system to the live Svelte stores.
|
|
12
|
+
*
|
|
13
|
+
* @param nodeTypes - Available node type definitions
|
|
14
|
+
* @param onUIAction - Optional callback for UI-side actions (open config panel, select node)
|
|
15
|
+
* @returns CommandContext connected to live stores, or null if no workflow is loaded
|
|
16
|
+
*/
|
|
17
|
+
export function createStoreCommandContext(nodeTypes, onUIAction) {
|
|
18
|
+
const workflow = getWorkflowStore();
|
|
19
|
+
if (!workflow) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const dispatch = {
|
|
23
|
+
addNode: (node) => workflowActions.addNode(node),
|
|
24
|
+
removeNode: (nodeId) => workflowActions.removeNode(nodeId),
|
|
25
|
+
updateNode: (nodeId, updates) => workflowActions.updateNode(nodeId, updates),
|
|
26
|
+
addEdge: (edge) => workflowActions.addEdge(edge),
|
|
27
|
+
removeEdge: (edgeId) => workflowActions.removeEdge(edgeId),
|
|
28
|
+
batchUpdate: (updates) => workflowActions.batchUpdate(updates),
|
|
29
|
+
undo: () => {
|
|
30
|
+
const previousState = historyService.undo();
|
|
31
|
+
if (previousState) {
|
|
32
|
+
workflowActions.restoreFromHistory(previousState);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
},
|
|
37
|
+
redo: () => {
|
|
38
|
+
const nextState = historyService.redo();
|
|
39
|
+
if (nextState) {
|
|
40
|
+
workflowActions.restoreFromHistory(nextState);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
},
|
|
45
|
+
startTransaction: (description) => {
|
|
46
|
+
const currentWorkflow = getWorkflowStore();
|
|
47
|
+
if (currentWorkflow) {
|
|
48
|
+
historyService.startTransaction(currentWorkflow, description);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
commitTransaction: () => historyService.commitTransaction(),
|
|
52
|
+
cancelTransaction: () => {
|
|
53
|
+
const snapshot = historyService.cancelTransaction();
|
|
54
|
+
if (snapshot) {
|
|
55
|
+
workflowActions.restoreFromHistory(snapshot);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
emitUIAction: onUIAction,
|
|
59
|
+
swapNode: (updates) => workflowActions.swapNode(updates),
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
getWorkflow: () => getWorkflowStore(),
|
|
63
|
+
nodeTypes,
|
|
64
|
+
typeMap: buildTypeMap(nodeTypes),
|
|
65
|
+
dispatch,
|
|
66
|
+
};
|
|
67
|
+
}
|