@plures/runebook 0.4.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/ANALYSIS_LADDER.md +231 -0
- package/CHANGELOG.md +124 -0
- package/INTEGRATIONS.md +242 -0
- package/LICENSE +21 -0
- package/MEMORY.md +253 -0
- package/NIXOS.md +357 -0
- package/QUICKSTART.md +157 -0
- package/README.md +295 -0
- package/RELEASE.md +190 -0
- package/ValidationChecklist.md +598 -0
- package/docs/demo.md +338 -0
- package/docs/llm-integration.md +300 -0
- package/docs/parallel-execution-plan.md +160 -0
- package/flake.nix +228 -0
- package/integrations/README.md +242 -0
- package/integrations/demo-steps.sh +64 -0
- package/integrations/nvim-runebook.lua +140 -0
- package/integrations/tmux-status.sh +51 -0
- package/integrations/vim-runebook.vim +77 -0
- package/integrations/wezterm-status-simple.lua +48 -0
- package/integrations/wezterm-status.lua +76 -0
- package/nixos-module.nix +156 -0
- package/package.json +76 -0
- package/packages/design-dojo/index.js +4 -0
- package/packages/design-dojo/package.json +20 -0
- package/packages/design-dojo/tokens.css +69 -0
- package/playwright.config.ts +16 -0
- package/scripts/check-versions.cjs +62 -0
- package/scripts/demo.sh +220 -0
- package/shell.nix +31 -0
- package/src/app.html +13 -0
- package/src/cli/index.ts +1050 -0
- package/src/lib/agent/analysis-pipeline.ts +347 -0
- package/src/lib/agent/analysis-service.ts +171 -0
- package/src/lib/agent/analysis.ts +159 -0
- package/src/lib/agent/analyzers/heuristic.ts +289 -0
- package/src/lib/agent/analyzers/index.ts +7 -0
- package/src/lib/agent/analyzers/llm.ts +204 -0
- package/src/lib/agent/analyzers/local-search.ts +215 -0
- package/src/lib/agent/capture.ts +123 -0
- package/src/lib/agent/index.ts +244 -0
- package/src/lib/agent/integration.ts +81 -0
- package/src/lib/agent/llm/providers/base.ts +99 -0
- package/src/lib/agent/llm/providers/index.ts +60 -0
- package/src/lib/agent/llm/providers/mock.ts +67 -0
- package/src/lib/agent/llm/providers/ollama.ts +151 -0
- package/src/lib/agent/llm/providers/openai.ts +153 -0
- package/src/lib/agent/llm/sanitizer.ts +170 -0
- package/src/lib/agent/llm/types.ts +118 -0
- package/src/lib/agent/memory.ts +363 -0
- package/src/lib/agent/node-status.ts +56 -0
- package/src/lib/agent/node-suggestions.ts +64 -0
- package/src/lib/agent/status.ts +80 -0
- package/src/lib/agent/suggestions.ts +169 -0
- package/src/lib/components/Canvas.svelte +124 -0
- package/src/lib/components/ConnectionLine.svelte +46 -0
- package/src/lib/components/DisplayNode.svelte +167 -0
- package/src/lib/components/InputNode.svelte +158 -0
- package/src/lib/components/TerminalNode.svelte +237 -0
- package/src/lib/components/Toolbar.svelte +359 -0
- package/src/lib/components/TransformNode.svelte +327 -0
- package/src/lib/core/index.ts +31 -0
- package/src/lib/core/observer.ts +278 -0
- package/src/lib/core/redaction.ts +158 -0
- package/src/lib/core/shell-adapters/base.ts +325 -0
- package/src/lib/core/shell-adapters/bash.ts +110 -0
- package/src/lib/core/shell-adapters/index.ts +62 -0
- package/src/lib/core/shell-adapters/zsh.ts +105 -0
- package/src/lib/core/storage.ts +360 -0
- package/src/lib/core/types.ts +176 -0
- package/src/lib/design-dojo/Box.svelte +47 -0
- package/src/lib/design-dojo/Button.svelte +75 -0
- package/src/lib/design-dojo/Input.svelte +65 -0
- package/src/lib/design-dojo/List.svelte +38 -0
- package/src/lib/design-dojo/Select.svelte +48 -0
- package/src/lib/design-dojo/SplitPane.svelte +43 -0
- package/src/lib/design-dojo/StatusBar.svelte +61 -0
- package/src/lib/design-dojo/Table.svelte +47 -0
- package/src/lib/design-dojo/Text.svelte +36 -0
- package/src/lib/design-dojo/Toggle.svelte +48 -0
- package/src/lib/design-dojo/index.ts +10 -0
- package/src/lib/stores/canvas-praxis.ts +268 -0
- package/src/lib/stores/canvas.ts +58 -0
- package/src/lib/types/agent.ts +78 -0
- package/src/lib/types/canvas.ts +71 -0
- package/src/lib/utils/storage.ts +326 -0
- package/src/lib/utils/yaml-loader.ts +52 -0
- package/src/routes/+layout.svelte +5 -0
- package/src/routes/+layout.ts +5 -0
- package/src/routes/+page.svelte +32 -0
- package/src-tauri/Cargo.lock +5735 -0
- package/src-tauri/Cargo.toml +38 -0
- package/src-tauri/build.rs +3 -0
- package/src-tauri/capabilities/default.json +10 -0
- package/src-tauri/icons/128x128.png +0 -0
- package/src-tauri/icons/128x128@2x.png +0 -0
- package/src-tauri/icons/32x32.png +0 -0
- package/src-tauri/icons/Square107x107Logo.png +0 -0
- package/src-tauri/icons/Square142x142Logo.png +0 -0
- package/src-tauri/icons/Square150x150Logo.png +0 -0
- package/src-tauri/icons/Square284x284Logo.png +0 -0
- package/src-tauri/icons/Square30x30Logo.png +0 -0
- package/src-tauri/icons/Square310x310Logo.png +0 -0
- package/src-tauri/icons/Square44x44Logo.png +0 -0
- package/src-tauri/icons/Square71x71Logo.png +0 -0
- package/src-tauri/icons/Square89x89Logo.png +0 -0
- package/src-tauri/icons/StoreLogo.png +0 -0
- package/src-tauri/icons/icon.icns +0 -0
- package/src-tauri/icons/icon.ico +0 -0
- package/src-tauri/icons/icon.png +0 -0
- package/src-tauri/src/agents/agent1.rs +66 -0
- package/src-tauri/src/agents/agent2.rs +80 -0
- package/src-tauri/src/agents/agent3.rs +73 -0
- package/src-tauri/src/agents/agent4.rs +66 -0
- package/src-tauri/src/agents/agent5.rs +68 -0
- package/src-tauri/src/agents/agent6.rs +75 -0
- package/src-tauri/src/agents/base.rs +52 -0
- package/src-tauri/src/agents/mod.rs +17 -0
- package/src-tauri/src/core/coordination.rs +117 -0
- package/src-tauri/src/core/mod.rs +12 -0
- package/src-tauri/src/core/ownership.rs +61 -0
- package/src-tauri/src/core/types.rs +132 -0
- package/src-tauri/src/execution/mod.rs +5 -0
- package/src-tauri/src/execution/runner.rs +143 -0
- package/src-tauri/src/lib.rs +161 -0
- package/src-tauri/src/main.rs +6 -0
- package/src-tauri/src/memory/api.rs +422 -0
- package/src-tauri/src/memory/client.rs +156 -0
- package/src-tauri/src/memory/encryption.rs +79 -0
- package/src-tauri/src/memory/migration.rs +110 -0
- package/src-tauri/src/memory/mod.rs +28 -0
- package/src-tauri/src/memory/schema.rs +275 -0
- package/src-tauri/src/memory/tests.rs +192 -0
- package/src-tauri/src/orchestrator/coordinator.rs +232 -0
- package/src-tauri/src/orchestrator/mod.rs +13 -0
- package/src-tauri/src/orchestrator/planner.rs +304 -0
- package/src-tauri/tauri.conf.json +35 -0
- package/static/examples/date-time-example.yaml +147 -0
- package/static/examples/hello-world.yaml +74 -0
- package/static/examples/transform-example.yaml +157 -0
- package/static/favicon.png +0 -0
- package/static/svelte.svg +1 -0
- package/static/tauri.svg +6 -0
- package/static/vite.svg +1 -0
- package/svelte.config.js +18 -0
- package/tsconfig.json +19 -0
- package/vite.config.js +45 -0
- package/vitest.config.ts +21 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Praxis-based canvas state management for RuneBook
|
|
2
|
+
// Uses Praxis reactive engine for type-safe, testable state management
|
|
3
|
+
|
|
4
|
+
import { createPraxisEngine, defineEvent, defineRule, PraxisRegistry } from '@plures/praxis';
|
|
5
|
+
import { createPraxisStore } from '@plures/praxis/svelte';
|
|
6
|
+
import type { PraxisState, PraxisEvent } from '@plures/praxis';
|
|
7
|
+
import type { Canvas, CanvasNode, Connection } from '../types/canvas';
|
|
8
|
+
|
|
9
|
+
// Define the canvas context type
|
|
10
|
+
export interface CanvasContext {
|
|
11
|
+
canvas: Canvas;
|
|
12
|
+
nodeData: Record<string, any>; // Node output data: `${nodeId}:${portId}` -> data
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Define events for canvas operations
|
|
16
|
+
export const AddNodeEvent = defineEvent<'ADD_NODE', { node: CanvasNode }>('ADD_NODE');
|
|
17
|
+
export const RemoveNodeEvent = defineEvent<'REMOVE_NODE', { nodeId: string }>('REMOVE_NODE');
|
|
18
|
+
export const UpdateNodeEvent = defineEvent<'UPDATE_NODE', { nodeId: string; updates: Partial<CanvasNode> }>('UPDATE_NODE');
|
|
19
|
+
export const UpdateNodePositionEvent = defineEvent<'UPDATE_NODE_POSITION', { nodeId: string; x: number; y: number }>('UPDATE_NODE_POSITION');
|
|
20
|
+
export const AddConnectionEvent = defineEvent<'ADD_CONNECTION', { connection: Connection }>('ADD_CONNECTION');
|
|
21
|
+
export const RemoveConnectionEvent = defineEvent<'REMOVE_CONNECTION', { from: string; to: string; fromPort: string; toPort: string }>('REMOVE_CONNECTION');
|
|
22
|
+
export const LoadCanvasEvent = defineEvent<'LOAD_CANVAS', { canvas: Canvas }>('LOAD_CANVAS');
|
|
23
|
+
export const ClearCanvasEvent = defineEvent<'CLEAR_CANVAS', {}>('CLEAR_CANVAS');
|
|
24
|
+
export const UpdateNodeDataEvent = defineEvent<'UPDATE_NODE_DATA', { nodeId: string; portId: string; data: any }>('UPDATE_NODE_DATA');
|
|
25
|
+
|
|
26
|
+
// Define rules for canvas operations
|
|
27
|
+
const addNodeRule = defineRule<CanvasContext>({
|
|
28
|
+
id: 'canvas.addNode',
|
|
29
|
+
description: 'Add a new node to the canvas',
|
|
30
|
+
impl: (state, events) => {
|
|
31
|
+
const evt = events.find(AddNodeEvent.is);
|
|
32
|
+
if (!evt) return [];
|
|
33
|
+
|
|
34
|
+
state.context.canvas.nodes = [...state.context.canvas.nodes, evt.payload.node];
|
|
35
|
+
return [];
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const removeNodeRule = defineRule<CanvasContext>({
|
|
40
|
+
id: 'canvas.removeNode',
|
|
41
|
+
description: 'Remove a node from the canvas',
|
|
42
|
+
impl: (state, events) => {
|
|
43
|
+
const evt = events.find(RemoveNodeEvent.is);
|
|
44
|
+
if (!evt) return [];
|
|
45
|
+
|
|
46
|
+
const { nodeId } = evt.payload;
|
|
47
|
+
state.context.canvas.nodes = state.context.canvas.nodes.filter(n => n.id !== nodeId);
|
|
48
|
+
state.context.canvas.connections = state.context.canvas.connections.filter(
|
|
49
|
+
c => c.from !== nodeId && c.to !== nodeId
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Remove node data
|
|
53
|
+
const prefix = `${nodeId}:`;
|
|
54
|
+
state.context.nodeData = Object.fromEntries(
|
|
55
|
+
Object.entries(state.context.nodeData).filter(([key]) => !key.startsWith(prefix))
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return [];
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const updateNodeRule = defineRule<CanvasContext>({
|
|
63
|
+
id: 'canvas.updateNode',
|
|
64
|
+
description: 'Update a node\'s properties',
|
|
65
|
+
impl: (state, events) => {
|
|
66
|
+
const evt = events.find(UpdateNodeEvent.is);
|
|
67
|
+
if (!evt) return [];
|
|
68
|
+
|
|
69
|
+
const { nodeId, updates } = evt.payload;
|
|
70
|
+
const nodeIndex = state.context.canvas.nodes.findIndex(n => n.id === nodeId);
|
|
71
|
+
if (nodeIndex !== -1) {
|
|
72
|
+
state.context.canvas.nodes[nodeIndex] = {
|
|
73
|
+
...state.context.canvas.nodes[nodeIndex],
|
|
74
|
+
...updates
|
|
75
|
+
} as CanvasNode;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return [];
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const updateNodePositionRule = defineRule<CanvasContext>({
|
|
83
|
+
id: 'canvas.updateNodePosition',
|
|
84
|
+
description: 'Update a node\'s position',
|
|
85
|
+
impl: (state, events) => {
|
|
86
|
+
const evt = events.find(UpdateNodePositionEvent.is);
|
|
87
|
+
if (!evt) return [];
|
|
88
|
+
|
|
89
|
+
const { nodeId, x, y } = evt.payload;
|
|
90
|
+
const nodeIndex = state.context.canvas.nodes.findIndex(n => n.id === nodeId);
|
|
91
|
+
if (nodeIndex !== -1) {
|
|
92
|
+
state.context.canvas.nodes[nodeIndex].position = { x, y };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return [];
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const addConnectionRule = defineRule<CanvasContext>({
|
|
100
|
+
id: 'canvas.addConnection',
|
|
101
|
+
description: 'Add a connection between nodes',
|
|
102
|
+
impl: (state, events) => {
|
|
103
|
+
const evt = events.find(AddConnectionEvent.is);
|
|
104
|
+
if (!evt) return [];
|
|
105
|
+
|
|
106
|
+
state.context.canvas.connections = [...state.context.canvas.connections, evt.payload.connection];
|
|
107
|
+
return [];
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const removeConnectionRule = defineRule<CanvasContext>({
|
|
112
|
+
id: 'canvas.removeConnection',
|
|
113
|
+
description: 'Remove a connection',
|
|
114
|
+
impl: (state, events) => {
|
|
115
|
+
const evt = events.find(RemoveConnectionEvent.is);
|
|
116
|
+
if (!evt) return [];
|
|
117
|
+
|
|
118
|
+
const { from, to, fromPort, toPort } = evt.payload;
|
|
119
|
+
state.context.canvas.connections = state.context.canvas.connections.filter(
|
|
120
|
+
c => !(c.from === from && c.to === to && c.fromPort === fromPort && c.toPort === toPort)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return [];
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const loadCanvasRule = defineRule<CanvasContext>({
|
|
128
|
+
id: 'canvas.loadCanvas',
|
|
129
|
+
description: 'Load a canvas from data',
|
|
130
|
+
impl: (state, events) => {
|
|
131
|
+
const evt = events.find(LoadCanvasEvent.is);
|
|
132
|
+
if (!evt) return [];
|
|
133
|
+
|
|
134
|
+
state.context.canvas = evt.payload.canvas;
|
|
135
|
+
return [];
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const clearCanvasRule = defineRule<CanvasContext>({
|
|
140
|
+
id: 'canvas.clearCanvas',
|
|
141
|
+
description: 'Clear the canvas',
|
|
142
|
+
impl: (state, events) => {
|
|
143
|
+
const evt = events.find(ClearCanvasEvent.is);
|
|
144
|
+
if (!evt) return [];
|
|
145
|
+
|
|
146
|
+
state.context.canvas = {
|
|
147
|
+
id: 'default',
|
|
148
|
+
name: 'Untitled Canvas',
|
|
149
|
+
description: '',
|
|
150
|
+
nodes: [],
|
|
151
|
+
connections: [],
|
|
152
|
+
version: '1.0.0'
|
|
153
|
+
};
|
|
154
|
+
state.context.nodeData = {};
|
|
155
|
+
|
|
156
|
+
return [];
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const updateNodeDataRule = defineRule<CanvasContext>({
|
|
161
|
+
id: 'canvas.updateNodeData',
|
|
162
|
+
description: 'Update node output data',
|
|
163
|
+
impl: (state, events) => {
|
|
164
|
+
const evt = events.find(UpdateNodeDataEvent.is);
|
|
165
|
+
if (!evt) return [];
|
|
166
|
+
|
|
167
|
+
const { nodeId, portId, data } = evt.payload;
|
|
168
|
+
state.context.nodeData[`${nodeId}:${portId}`] = data;
|
|
169
|
+
|
|
170
|
+
return [];
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Create the registry and register all rules
|
|
175
|
+
const registry = new PraxisRegistry<CanvasContext>();
|
|
176
|
+
registry.registerRule(addNodeRule);
|
|
177
|
+
registry.registerRule(removeNodeRule);
|
|
178
|
+
registry.registerRule(updateNodeRule);
|
|
179
|
+
registry.registerRule(updateNodePositionRule);
|
|
180
|
+
registry.registerRule(addConnectionRule);
|
|
181
|
+
registry.registerRule(removeConnectionRule);
|
|
182
|
+
registry.registerRule(loadCanvasRule);
|
|
183
|
+
registry.registerRule(clearCanvasRule);
|
|
184
|
+
registry.registerRule(updateNodeDataRule);
|
|
185
|
+
|
|
186
|
+
// Create the reactive engine with initial state
|
|
187
|
+
export const canvasEngine = createPraxisEngine<CanvasContext>({
|
|
188
|
+
initialContext: {
|
|
189
|
+
canvas: {
|
|
190
|
+
id: 'default',
|
|
191
|
+
name: 'Untitled Canvas',
|
|
192
|
+
description: '',
|
|
193
|
+
nodes: [],
|
|
194
|
+
connections: [],
|
|
195
|
+
version: '1.0.0'
|
|
196
|
+
},
|
|
197
|
+
nodeData: {}
|
|
198
|
+
},
|
|
199
|
+
registry
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Create the Praxis store that properly notifies subscribers
|
|
203
|
+
export const canvasPraxisStoreInstance = createPraxisStore<CanvasContext>(canvasEngine);
|
|
204
|
+
|
|
205
|
+
// Export a convenience API that matches the old store interface
|
|
206
|
+
export const canvasPraxisStore = {
|
|
207
|
+
// The reactive context - use in Svelte components with $derived
|
|
208
|
+
get context() {
|
|
209
|
+
return canvasEngine.getContext();
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
get canvas() {
|
|
213
|
+
return canvasEngine.getContext().canvas;
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
get nodeData() {
|
|
217
|
+
return canvasEngine.getContext().nodeData;
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
// Actions
|
|
221
|
+
addNode: (node: CanvasNode) => {
|
|
222
|
+
canvasPraxisStoreInstance.dispatch([AddNodeEvent.create({ node })]);
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
removeNode: (nodeId: string) => {
|
|
226
|
+
canvasPraxisStoreInstance.dispatch([RemoveNodeEvent.create({ nodeId })]);
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
updateNode: (nodeId: string, updates: Partial<CanvasNode>) => {
|
|
230
|
+
canvasPraxisStoreInstance.dispatch([UpdateNodeEvent.create({ nodeId, updates })]);
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
updateNodePosition: (nodeId: string, x: number, y: number) => {
|
|
234
|
+
canvasPraxisStoreInstance.dispatch([UpdateNodePositionEvent.create({ nodeId, x, y })]);
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
addConnection: (connection: Connection) => {
|
|
238
|
+
canvasPraxisStoreInstance.dispatch([AddConnectionEvent.create({ connection })]);
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
removeConnection: (from: string, to: string, fromPort: string, toPort: string) => {
|
|
242
|
+
canvasPraxisStoreInstance.dispatch([RemoveConnectionEvent.create({ from, to, fromPort, toPort })]);
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
loadCanvas: (canvas: Canvas) => {
|
|
246
|
+
canvasPraxisStoreInstance.dispatch([LoadCanvasEvent.create({ canvas })]);
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
clear: () => {
|
|
250
|
+
canvasPraxisStoreInstance.dispatch([ClearCanvasEvent.create({})]);
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
updateNodeData: (nodeId: string, portId: string, data: any) => {
|
|
254
|
+
canvasPraxisStoreInstance.dispatch([UpdateNodeDataEvent.create({ nodeId, portId, data })]);
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
// Helper to get node input data from connections
|
|
258
|
+
getNodeInputData: (nodeId: string, portId: string) => {
|
|
259
|
+
const context = canvasEngine.getContext();
|
|
260
|
+
const connections = context.canvas.connections;
|
|
261
|
+
const nodeData = context.nodeData;
|
|
262
|
+
const connection = connections.find(c => c.to === nodeId && c.toPort === portId);
|
|
263
|
+
if (connection) {
|
|
264
|
+
return nodeData[`${connection.from}:${connection.fromPort}`];
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Re-export the praxis-based canvas store for backward compatibility
|
|
2
|
+
// This maintains the same API while using Praxis reactive engine underneath
|
|
3
|
+
|
|
4
|
+
import { canvasPraxisStore, canvasPraxisStoreInstance, canvasEngine } from './canvas-praxis';
|
|
5
|
+
import type { Canvas, Connection } from '../types/canvas';
|
|
6
|
+
|
|
7
|
+
// Use the praxis store from canvas-praxis instead of creating a new one
|
|
8
|
+
const praxisStore = canvasPraxisStoreInstance;
|
|
9
|
+
|
|
10
|
+
// Create a derived store for just the canvas
|
|
11
|
+
export const canvasStore = {
|
|
12
|
+
subscribe: (fn: (value: Canvas) => void) => {
|
|
13
|
+
return praxisStore.subscribe((state) => {
|
|
14
|
+
fn(state.context.canvas);
|
|
15
|
+
});
|
|
16
|
+
},
|
|
17
|
+
set: (canvas: Canvas) => canvasPraxisStore.loadCanvas(canvas),
|
|
18
|
+
addNode: canvasPraxisStore.addNode,
|
|
19
|
+
removeNode: canvasPraxisStore.removeNode,
|
|
20
|
+
updateNode: canvasPraxisStore.updateNode,
|
|
21
|
+
updateNodePosition: canvasPraxisStore.updateNodePosition,
|
|
22
|
+
addConnection: canvasPraxisStore.addConnection,
|
|
23
|
+
removeConnection: canvasPraxisStore.removeConnection,
|
|
24
|
+
loadCanvas: canvasPraxisStore.loadCanvas,
|
|
25
|
+
clear: canvasPraxisStore.clear
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Create a derived store for node data
|
|
29
|
+
export const nodeDataStore = {
|
|
30
|
+
subscribe: (fn: (value: Record<string, any>) => void) => {
|
|
31
|
+
return praxisStore.subscribe((state) => {
|
|
32
|
+
fn(state.context.nodeData);
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
set: (data: Record<string, any>) => {
|
|
36
|
+
// Not typically used, but provided for compatibility
|
|
37
|
+
const context = canvasEngine.getContext();
|
|
38
|
+
context.nodeData = data;
|
|
39
|
+
},
|
|
40
|
+
update: (fn: (value: Record<string, any>) => Record<string, any>) => {
|
|
41
|
+
const context = canvasEngine.getContext();
|
|
42
|
+
context.nodeData = fn(context.nodeData);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Helper to update node output data
|
|
47
|
+
export function updateNodeData(nodeId: string, portId: string, data: any) {
|
|
48
|
+
canvasPraxisStore.updateNodeData(nodeId, portId, data);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Helper to get node input data from connections
|
|
52
|
+
export function getNodeInputData(nodeId: string, portId: string, connections: Connection[], nodeData: Record<string, any>) {
|
|
53
|
+
const connection = connections.find(c => c.to === nodeId && c.toPort === portId);
|
|
54
|
+
if (connection) {
|
|
55
|
+
return nodeData[`${connection.from}:${connection.fromPort}`];
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Types for Ambient Agent Mode (term-agent capabilities)
|
|
2
|
+
|
|
3
|
+
export interface TerminalEvent {
|
|
4
|
+
id: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
command: string;
|
|
7
|
+
args: string[];
|
|
8
|
+
env: Record<string, string>;
|
|
9
|
+
cwd: string;
|
|
10
|
+
stdout?: string;
|
|
11
|
+
stderr?: string;
|
|
12
|
+
exitCode?: number;
|
|
13
|
+
duration?: number; // milliseconds
|
|
14
|
+
success: boolean;
|
|
15
|
+
context?: EventContext;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface EventContext {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
workingDirectory: string;
|
|
21
|
+
environment: Record<string, string>;
|
|
22
|
+
previousCommand?: string;
|
|
23
|
+
canvasId?: string;
|
|
24
|
+
nodeId?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CommandPattern {
|
|
28
|
+
id: string;
|
|
29
|
+
command: string;
|
|
30
|
+
frequency: number;
|
|
31
|
+
lastUsed: number;
|
|
32
|
+
successRate: number;
|
|
33
|
+
avgDuration: number;
|
|
34
|
+
commonArgs: string[];
|
|
35
|
+
commonEnv: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface Suggestion {
|
|
39
|
+
id: string;
|
|
40
|
+
type: 'command' | 'optimization' | 'shortcut' | 'warning' | 'tip';
|
|
41
|
+
priority: 'low' | 'medium' | 'high';
|
|
42
|
+
title: string;
|
|
43
|
+
description: string;
|
|
44
|
+
command?: string;
|
|
45
|
+
args?: string[];
|
|
46
|
+
context?: Record<string, any>;
|
|
47
|
+
timestamp: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
import type { LLMProviderConfig } from '../agent/llm/types';
|
|
51
|
+
|
|
52
|
+
export interface EventStorage {
|
|
53
|
+
saveEvent(event: TerminalEvent): Promise<void>;
|
|
54
|
+
getEvents(limit?: number, since?: number): Promise<TerminalEvent[]>;
|
|
55
|
+
getEventsByCommand(command: string, limit: number): Promise<TerminalEvent[]>;
|
|
56
|
+
getPatterns(): Promise<CommandPattern[]>;
|
|
57
|
+
savePattern(pattern: CommandPattern): Promise<void>;
|
|
58
|
+
saveSuggestion(suggestion: Suggestion): Promise<void>;
|
|
59
|
+
getSuggestions(limit: number): Promise<Suggestion[]>;
|
|
60
|
+
getStats(): Promise<{
|
|
61
|
+
totalEvents: number;
|
|
62
|
+
uniqueCommands: number;
|
|
63
|
+
avgSuccessRate: number;
|
|
64
|
+
totalDuration: number;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface AgentConfig {
|
|
69
|
+
enabled: boolean;
|
|
70
|
+
captureEvents: boolean;
|
|
71
|
+
analyzePatterns: boolean;
|
|
72
|
+
suggestImprovements: boolean;
|
|
73
|
+
storagePath?: string;
|
|
74
|
+
maxEvents?: number;
|
|
75
|
+
retentionDays?: number;
|
|
76
|
+
llm?: LLMProviderConfig; // LLM/MCP integration config (disabled by default)
|
|
77
|
+
}
|
|
78
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Canvas node types for RuneBook
|
|
2
|
+
export type NodeType = 'terminal' | 'input' | 'display' | 'transform';
|
|
3
|
+
|
|
4
|
+
export interface Position {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Connection {
|
|
10
|
+
from: string; // Source node ID
|
|
11
|
+
to: string; // Target node ID
|
|
12
|
+
fromPort: string; // Output port name
|
|
13
|
+
toPort: string; // Input port name
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Port {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
type: 'input' | 'output';
|
|
20
|
+
dataType?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface BaseNode {
|
|
24
|
+
id: string;
|
|
25
|
+
type: NodeType;
|
|
26
|
+
position: Position;
|
|
27
|
+
label: string;
|
|
28
|
+
inputs: Port[];
|
|
29
|
+
outputs: Port[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TerminalNode extends BaseNode {
|
|
33
|
+
type: 'terminal';
|
|
34
|
+
command: string;
|
|
35
|
+
args?: string[];
|
|
36
|
+
env?: Record<string, string>;
|
|
37
|
+
cwd?: string;
|
|
38
|
+
autoStart?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface InputNode extends BaseNode {
|
|
42
|
+
type: 'input';
|
|
43
|
+
inputType: 'text' | 'number' | 'checkbox' | 'slider';
|
|
44
|
+
value: any;
|
|
45
|
+
min?: number;
|
|
46
|
+
max?: number;
|
|
47
|
+
step?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface DisplayNode extends BaseNode {
|
|
51
|
+
type: 'display';
|
|
52
|
+
displayType: 'text' | 'json' | 'table' | 'chart';
|
|
53
|
+
content: any;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface TransformNode extends BaseNode {
|
|
57
|
+
type: 'transform';
|
|
58
|
+
transformType: 'map' | 'filter' | 'reduce' | 'sudolang';
|
|
59
|
+
code: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type CanvasNode = TerminalNode | InputNode | DisplayNode | TransformNode;
|
|
63
|
+
|
|
64
|
+
export interface Canvas {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
nodes: CanvasNode[];
|
|
69
|
+
connections: Connection[];
|
|
70
|
+
version: string;
|
|
71
|
+
}
|