@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,326 @@
|
|
|
1
|
+
// Storage utility for RuneBook canvases
|
|
2
|
+
// Integrated with PluresDB for persistent storage
|
|
3
|
+
|
|
4
|
+
import type { Canvas } from '../types/canvas';
|
|
5
|
+
|
|
6
|
+
export interface StorageAdapter {
|
|
7
|
+
save(canvas: Canvas): Promise<void>;
|
|
8
|
+
load(id: string): Promise<Canvas | null>;
|
|
9
|
+
list(): Promise<{ id: string; name: string; timestamp: number }[]>;
|
|
10
|
+
delete(id: string): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* LocalStorage adapter for browser-based storage
|
|
15
|
+
* Fallback option when PluresDB is not available
|
|
16
|
+
*/
|
|
17
|
+
export class LocalStorageAdapter implements StorageAdapter {
|
|
18
|
+
private readonly prefix = 'runebook_canvas_';
|
|
19
|
+
|
|
20
|
+
private validateCanvas(data: any): data is { canvas: Canvas; timestamp: number } {
|
|
21
|
+
return (
|
|
22
|
+
data &&
|
|
23
|
+
typeof data === 'object' &&
|
|
24
|
+
'canvas' in data &&
|
|
25
|
+
'timestamp' in data &&
|
|
26
|
+
typeof data.timestamp === 'number' &&
|
|
27
|
+
data.canvas &&
|
|
28
|
+
typeof data.canvas === 'object' &&
|
|
29
|
+
'id' in data.canvas &&
|
|
30
|
+
'name' in data.canvas &&
|
|
31
|
+
'nodes' in data.canvas &&
|
|
32
|
+
Array.isArray(data.canvas.nodes)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async save(canvas: Canvas): Promise<void> {
|
|
37
|
+
const key = this.prefix + canvas.id;
|
|
38
|
+
const data = {
|
|
39
|
+
canvas,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
};
|
|
42
|
+
localStorage.setItem(key, JSON.stringify(data));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async load(id: string): Promise<Canvas | null> {
|
|
46
|
+
const key = this.prefix + id;
|
|
47
|
+
const item = localStorage.getItem(key);
|
|
48
|
+
if (!item) return null;
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const data = JSON.parse(item);
|
|
52
|
+
if (!this.validateCanvas(data)) {
|
|
53
|
+
console.error('Invalid canvas data structure');
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return data.canvas;
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.error('Failed to parse canvas data:', e);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async list(): Promise<{ id: string; name: string; timestamp: number }[]> {
|
|
64
|
+
const canvases: { id: string; name: string; timestamp: number }[] = [];
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
67
|
+
const key = localStorage.key(i);
|
|
68
|
+
if (key && key.startsWith(this.prefix)) {
|
|
69
|
+
try {
|
|
70
|
+
const item = localStorage.getItem(key);
|
|
71
|
+
if (item) {
|
|
72
|
+
const data = JSON.parse(item);
|
|
73
|
+
if (this.validateCanvas(data)) {
|
|
74
|
+
canvases.push({
|
|
75
|
+
id: data.canvas.id,
|
|
76
|
+
name: data.canvas.name,
|
|
77
|
+
timestamp: data.timestamp,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch (e) {
|
|
82
|
+
console.error('Failed to parse canvas metadata:', e);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return canvases.sort((a, b) => b.timestamp - a.timestamp);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async delete(id: string): Promise<void> {
|
|
91
|
+
const key = this.prefix + id;
|
|
92
|
+
localStorage.removeItem(key);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* PluresDB adapter for persistent, P2P-enabled storage
|
|
98
|
+
* Uses PluresDB's key-value API for storing canvas data
|
|
99
|
+
*/
|
|
100
|
+
export class PluresDBAdapter implements StorageAdapter {
|
|
101
|
+
private db: any = null;
|
|
102
|
+
private readonly prefix = 'runebook:canvas:';
|
|
103
|
+
private readonly metaPrefix = 'runebook:meta:';
|
|
104
|
+
private initialized = false;
|
|
105
|
+
private config: {
|
|
106
|
+
port?: number;
|
|
107
|
+
host?: string;
|
|
108
|
+
dataDir?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
constructor(config?: { port?: number; host?: string; dataDir?: string }) {
|
|
112
|
+
// Configuration can be provided or will use defaults
|
|
113
|
+
this.config = {
|
|
114
|
+
port: config?.port ?? 34567,
|
|
115
|
+
host: config?.host ?? 'localhost',
|
|
116
|
+
dataDir: config?.dataDir ?? './pluresdb-data',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private async ensureInitialized(): Promise<void> {
|
|
121
|
+
if (this.initialized && this.db) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
// Dynamic import to avoid bundling issues
|
|
127
|
+
const { SQLiteCompatibleAPI } = await import('pluresdb');
|
|
128
|
+
|
|
129
|
+
this.db = new SQLiteCompatibleAPI({
|
|
130
|
+
config: this.config,
|
|
131
|
+
autoStart: true,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Wait for initialization
|
|
135
|
+
await this.db.start();
|
|
136
|
+
this.initialized = true;
|
|
137
|
+
console.log('PluresDB initialized successfully with config:', this.config);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error('Failed to initialize PluresDB:', error);
|
|
140
|
+
throw new Error('PluresDB initialization failed. Make sure PluresDB server is running or use LocalStorageAdapter as fallback.');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private validateCanvas(data: any): data is { canvas: Canvas; timestamp: number } {
|
|
145
|
+
return (
|
|
146
|
+
data &&
|
|
147
|
+
typeof data === 'object' &&
|
|
148
|
+
'canvas' in data &&
|
|
149
|
+
'timestamp' in data &&
|
|
150
|
+
typeof data.timestamp === 'number' &&
|
|
151
|
+
data.canvas &&
|
|
152
|
+
typeof data.canvas === 'object' &&
|
|
153
|
+
'id' in data.canvas &&
|
|
154
|
+
'name' in data.canvas &&
|
|
155
|
+
'nodes' in data.canvas &&
|
|
156
|
+
Array.isArray(data.canvas.nodes)
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async save(canvas: Canvas): Promise<void> {
|
|
161
|
+
await this.ensureInitialized();
|
|
162
|
+
|
|
163
|
+
const key = this.prefix + canvas.id;
|
|
164
|
+
const metaKey = this.metaPrefix + canvas.id;
|
|
165
|
+
const timestamp = Date.now();
|
|
166
|
+
|
|
167
|
+
const data = {
|
|
168
|
+
canvas,
|
|
169
|
+
timestamp,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Save the full canvas data
|
|
173
|
+
await this.db.put(key, data);
|
|
174
|
+
|
|
175
|
+
// Save metadata for efficient listing
|
|
176
|
+
await this.db.put(metaKey, {
|
|
177
|
+
id: canvas.id,
|
|
178
|
+
name: canvas.name,
|
|
179
|
+
timestamp,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async load(id: string): Promise<Canvas | null> {
|
|
184
|
+
await this.ensureInitialized();
|
|
185
|
+
|
|
186
|
+
const key = this.prefix + id;
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const data = await this.db.getValue(key);
|
|
190
|
+
|
|
191
|
+
if (!data) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!this.validateCanvas(data)) {
|
|
196
|
+
console.error('Invalid canvas data structure in PluresDB');
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return data.canvas;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error('Failed to load canvas from PluresDB:', error);
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async list(): Promise<{ id: string; name: string; timestamp: number }[]> {
|
|
208
|
+
await this.ensureInitialized();
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
// Get all metadata keys
|
|
212
|
+
const keys = await this.db.list(this.metaPrefix);
|
|
213
|
+
const canvases: { id: string; name: string; timestamp: number }[] = [];
|
|
214
|
+
|
|
215
|
+
// Fetch each metadata entry
|
|
216
|
+
for (const key of keys) {
|
|
217
|
+
try {
|
|
218
|
+
const meta = await this.db.getValue(key);
|
|
219
|
+
if (meta && meta.id && meta.name && typeof meta.timestamp === 'number') {
|
|
220
|
+
canvases.push({
|
|
221
|
+
id: meta.id,
|
|
222
|
+
name: meta.name,
|
|
223
|
+
timestamp: meta.timestamp,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.error('Failed to load canvas metadata:', error);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Sort by timestamp, newest first
|
|
232
|
+
return canvases.sort((a, b) => b.timestamp - a.timestamp);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error('Failed to list canvases from PluresDB:', error);
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async delete(id: string): Promise<void> {
|
|
240
|
+
await this.ensureInitialized();
|
|
241
|
+
|
|
242
|
+
const key = this.prefix + id;
|
|
243
|
+
const metaKey = this.metaPrefix + id;
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
// Delete both the canvas data and metadata
|
|
247
|
+
await this.db.delete(key);
|
|
248
|
+
await this.db.delete(metaKey);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error('Failed to delete canvas from PluresDB:', error);
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Stop the PluresDB server (cleanup)
|
|
257
|
+
*/
|
|
258
|
+
async stop(): Promise<void> {
|
|
259
|
+
if (this.db && this.initialized) {
|
|
260
|
+
try {
|
|
261
|
+
await this.db.stop();
|
|
262
|
+
this.initialized = false;
|
|
263
|
+
console.log('PluresDB stopped');
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error('Failed to stop PluresDB:', error);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Default storage adapter - use LocalStorage for browser compatibility
|
|
272
|
+
// Users can switch to PluresDBAdapter if they have PluresDB server running
|
|
273
|
+
export const storage: StorageAdapter = new LocalStorageAdapter();
|
|
274
|
+
|
|
275
|
+
// Storage adapter management
|
|
276
|
+
let currentAdapter: StorageAdapter = storage;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Switch to LocalStorage adapter
|
|
280
|
+
*/
|
|
281
|
+
export function useLocalStorage(): void {
|
|
282
|
+
currentAdapter = new LocalStorageAdapter();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Switch to PluresDB adapter
|
|
287
|
+
* @param config Optional PluresDB configuration
|
|
288
|
+
*/
|
|
289
|
+
export function usePluresDB(config?: { port?: number; host?: string; dataDir?: string }): void {
|
|
290
|
+
currentAdapter = new PluresDBAdapter(config);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get the current storage adapter
|
|
295
|
+
*/
|
|
296
|
+
export function getCurrentAdapter(): StorageAdapter {
|
|
297
|
+
return currentAdapter;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Save canvas to persistent storage
|
|
302
|
+
*/
|
|
303
|
+
export async function saveCanvas(canvas: Canvas): Promise<void> {
|
|
304
|
+
await currentAdapter.save(canvas);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Load canvas from persistent storage
|
|
309
|
+
*/
|
|
310
|
+
export async function loadCanvas(id: string): Promise<Canvas | null> {
|
|
311
|
+
return await currentAdapter.load(id);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* List all saved canvases
|
|
316
|
+
*/
|
|
317
|
+
export async function listCanvases(): Promise<{ id: string; name: string; timestamp: number }[]> {
|
|
318
|
+
return await currentAdapter.list();
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Delete a saved canvas
|
|
323
|
+
*/
|
|
324
|
+
export async function deleteCanvas(id: string): Promise<void> {
|
|
325
|
+
await currentAdapter.delete(id);
|
|
326
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import yaml from 'js-yaml';
|
|
2
|
+
import type { Canvas } from '../types/canvas';
|
|
3
|
+
|
|
4
|
+
export async function loadCanvasFromYAML(yamlContent: string): Promise<Canvas> {
|
|
5
|
+
try {
|
|
6
|
+
const data = yaml.load(yamlContent) as any;
|
|
7
|
+
|
|
8
|
+
// Validate required fields
|
|
9
|
+
if (!data.id || !data.name || !data.nodes || !data.connections) {
|
|
10
|
+
throw new Error('Invalid canvas YAML: missing required fields');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
id: data.id,
|
|
15
|
+
name: data.name,
|
|
16
|
+
description: data.description || '',
|
|
17
|
+
nodes: data.nodes || [],
|
|
18
|
+
connections: data.connections || [],
|
|
19
|
+
version: data.version || '1.0.0'
|
|
20
|
+
};
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Error parsing canvas YAML:', error);
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function saveCanvasToYAML(canvas: Canvas): string {
|
|
28
|
+
try {
|
|
29
|
+
return yaml.dump(canvas, {
|
|
30
|
+
indent: 2,
|
|
31
|
+
lineWidth: 120,
|
|
32
|
+
noRefs: true
|
|
33
|
+
});
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('Error serializing canvas to YAML:', error);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function loadCanvasFromFile(filePath: string): Promise<Canvas> {
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(filePath);
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Failed to load canvas file: ${response.statusText}`);
|
|
45
|
+
}
|
|
46
|
+
const yamlContent = await response.text();
|
|
47
|
+
return loadCanvasFromYAML(yamlContent);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('Error loading canvas file:', error);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Tauri doesn't have a Node.js server to do proper SSR
|
|
2
|
+
// so we use adapter-static with a fallback to index.html to put the site in SPA mode
|
|
3
|
+
// See: https://svelte.dev/docs/kit/single-page-apps
|
|
4
|
+
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
|
5
|
+
export const ssr = false;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Canvas from '$lib/components/Canvas.svelte';
|
|
3
|
+
import Toolbar from '$lib/components/Toolbar.svelte';
|
|
4
|
+
|
|
5
|
+
const tui = false;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="app">
|
|
9
|
+
<Toolbar {tui} />
|
|
10
|
+
<div class="canvas-wrapper">
|
|
11
|
+
<Canvas {tui} />
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
:global(body) {
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.app {
|
|
23
|
+
display: flex;
|
|
24
|
+
height: 100vh;
|
|
25
|
+
width: 100vw;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.canvas-wrapper {
|
|
29
|
+
flex: 1;
|
|
30
|
+
margin-left: 200px;
|
|
31
|
+
}
|
|
32
|
+
</style>
|