myrlin-workbook 0.9.7 → 0.9.9
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/package.json +64 -64
- package/scripts/seed-sessions.js +121 -0
- package/src/index.js +177 -176
- package/src/state/docs-manager.js +420 -419
- package/src/state/store.js +125 -7
- package/src/utils/data-dir.js +116 -0
- package/src/web/cost-worker.js +134 -0
- package/src/web/public/app.js +72 -11
- package/src/web/server.js +90 -16
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "myrlin-workbook",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Browser-based project manager for Claude Code sessions - session discovery, multi-terminal, cost tracking, docs, and kanban board",
|
|
5
|
-
"main": "src/index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"myrlin-workbook": "./src/gui.js",
|
|
8
|
-
"myrlin": "./src/gui.js",
|
|
9
|
-
"myrlin-tui": "./src/index.js",
|
|
10
|
-
"cwm": "./src/index.js"
|
|
11
|
-
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"start": "node src/index.js",
|
|
14
|
-
"demo": "node src/demo.js",
|
|
15
|
-
"gui": "node src/supervisor.js",
|
|
16
|
-
"gui:bare": "node src/gui.js",
|
|
17
|
-
"gui:demo": "node src/supervisor.js --demo",
|
|
18
|
-
"test": "node test/run.js",
|
|
19
|
-
"mcp:visual-qa": "node src/mcp/visual-qa.js",
|
|
20
|
-
"gui:cdp": "node src/supervisor.js --cdp",
|
|
21
|
-
"postinstall": "node scripts/postinstall.js",
|
|
22
|
-
"restart": "bash scripts/restart-gui.sh"
|
|
23
|
-
},
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "https://github.com/therealarthur/myrlin-workbook.git"
|
|
27
|
-
},
|
|
28
|
-
"homepage": "https://github.com/therealarthur/myrlin-workbook",
|
|
29
|
-
"engines": {
|
|
30
|
-
"node": ">=18.0.0"
|
|
31
|
-
},
|
|
32
|
-
"keywords": [
|
|
33
|
-
"claude",
|
|
34
|
-
"workspace",
|
|
35
|
-
"manager",
|
|
36
|
-
"terminal",
|
|
37
|
-
"tui",
|
|
38
|
-
"ai",
|
|
39
|
-
"coding-assistant",
|
|
40
|
-
"session-manager",
|
|
41
|
-
"developer-tools",
|
|
42
|
-
"xterm",
|
|
43
|
-
"myrlin"
|
|
44
|
-
],
|
|
45
|
-
"author": "Arthur",
|
|
46
|
-
"license": "AGPL-3.0-only",
|
|
47
|
-
"dependencies": {
|
|
48
|
-
"blessed": "^0.1.81",
|
|
49
|
-
"blessed-contrib": "^4.11.0",
|
|
50
|
-
"chalk": "^5.6.2",
|
|
51
|
-
"chrome-remote-interface": "^0.34.0",
|
|
52
|
-
"express": "^5.2.1",
|
|
53
|
-
"node-pty": "^1.1.0",
|
|
54
|
-
"ws": "^8.19.0"
|
|
55
|
-
},
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"@playwright/test": "^1.58.2",
|
|
58
|
-
"@xterm/addon-fit": "^0.11.0",
|
|
59
|
-
"@xterm/addon-web-links": "^0.12.0",
|
|
60
|
-
"@xterm/xterm": "^6.0.0",
|
|
61
|
-
"ffmpeg-static": "^5.3.0",
|
|
62
|
-
"sharp": "^0.34.5"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "myrlin-workbook",
|
|
3
|
+
"version": "0.9.9",
|
|
4
|
+
"description": "Browser-based project manager for Claude Code sessions - session discovery, multi-terminal, cost tracking, docs, and kanban board",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"myrlin-workbook": "./src/gui.js",
|
|
8
|
+
"myrlin": "./src/gui.js",
|
|
9
|
+
"myrlin-tui": "./src/index.js",
|
|
10
|
+
"cwm": "./src/index.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"start": "node src/index.js",
|
|
14
|
+
"demo": "node src/demo.js",
|
|
15
|
+
"gui": "node src/supervisor.js",
|
|
16
|
+
"gui:bare": "node src/gui.js",
|
|
17
|
+
"gui:demo": "node src/supervisor.js --demo",
|
|
18
|
+
"test": "node test/run.js",
|
|
19
|
+
"mcp:visual-qa": "node src/mcp/visual-qa.js",
|
|
20
|
+
"gui:cdp": "node src/supervisor.js --cdp",
|
|
21
|
+
"postinstall": "node scripts/postinstall.js",
|
|
22
|
+
"restart": "bash scripts/restart-gui.sh"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/therealarthur/myrlin-workbook.git"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/therealarthur/myrlin-workbook",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"claude",
|
|
34
|
+
"workspace",
|
|
35
|
+
"manager",
|
|
36
|
+
"terminal",
|
|
37
|
+
"tui",
|
|
38
|
+
"ai",
|
|
39
|
+
"coding-assistant",
|
|
40
|
+
"session-manager",
|
|
41
|
+
"developer-tools",
|
|
42
|
+
"xterm",
|
|
43
|
+
"myrlin"
|
|
44
|
+
],
|
|
45
|
+
"author": "Arthur",
|
|
46
|
+
"license": "AGPL-3.0-only",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"blessed": "^0.1.81",
|
|
49
|
+
"blessed-contrib": "^4.11.0",
|
|
50
|
+
"chalk": "^5.6.2",
|
|
51
|
+
"chrome-remote-interface": "^0.34.0",
|
|
52
|
+
"express": "^5.2.1",
|
|
53
|
+
"node-pty": "^1.1.0",
|
|
54
|
+
"ws": "^8.19.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@playwright/test": "^1.58.2",
|
|
58
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
59
|
+
"@xterm/addon-web-links": "^0.12.0",
|
|
60
|
+
"@xterm/xterm": "^6.0.0",
|
|
61
|
+
"ffmpeg-static": "^5.3.0",
|
|
62
|
+
"sharp": "^0.34.5"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* One-time script to rebuild sessions from layout.json data.
|
|
4
|
+
* Reads layout.json, maps tab groups to workspace IDs, creates sessions via API.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const http = require('http');
|
|
8
|
+
|
|
9
|
+
const BASE = 'http://127.0.0.1:3456';
|
|
10
|
+
const PASSWORD = 'Sparktech123!';
|
|
11
|
+
|
|
12
|
+
function apiCall(method, path, body) {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const url = new URL(path, BASE);
|
|
15
|
+
const data = body ? JSON.stringify(body) : null;
|
|
16
|
+
const opts = {
|
|
17
|
+
hostname: url.hostname,
|
|
18
|
+
port: url.port,
|
|
19
|
+
path: url.pathname + url.search,
|
|
20
|
+
method,
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(apiCall._token ? { 'Authorization': 'Bearer ' + apiCall._token } : {}),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
const req = http.request(opts, (res) => {
|
|
27
|
+
let chunks = '';
|
|
28
|
+
res.on('data', c => chunks += c);
|
|
29
|
+
res.on('end', () => {
|
|
30
|
+
try { resolve(JSON.parse(chunks)); } catch { resolve(chunks); }
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
req.on('error', reject);
|
|
34
|
+
if (data) req.write(data);
|
|
35
|
+
req.end();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function main() {
|
|
40
|
+
// Auth
|
|
41
|
+
const auth = await apiCall('POST', '/api/auth/login', { password: PASSWORD });
|
|
42
|
+
apiCall._token = auth.token;
|
|
43
|
+
console.log('Authenticated');
|
|
44
|
+
|
|
45
|
+
// Get workspace map
|
|
46
|
+
const wsResp = await apiCall('GET', '/api/workspaces');
|
|
47
|
+
const wsMap = {};
|
|
48
|
+
for (const ws of wsResp.workspaces) {
|
|
49
|
+
wsMap[ws.name] = ws.id;
|
|
50
|
+
}
|
|
51
|
+
console.log('Workspaces:', Object.keys(wsMap).join(', '));
|
|
52
|
+
|
|
53
|
+
// Session definitions from layout.json
|
|
54
|
+
const sessions = [
|
|
55
|
+
// Pantex
|
|
56
|
+
{ name: 'pantex main', ws: 'Pantex', cwd: 'C:\\Users\\Arthur\\Desktop\\Desktop\\work\\pantex', resume: '01ec027f-d5ba-42db-ae3e-1337d204da7b' },
|
|
57
|
+
{ name: 'pantex', ws: 'Pantex', cwd: 'C:\\Users\\Arthur\\Desktop\\Desktop\\work\\pantex' },
|
|
58
|
+
{ name: 'pantex 3', ws: 'Pantex', cwd: 'C:\\Users\\Arthur\\Desktop\\Desktop\\work\\pantex' },
|
|
59
|
+
{ name: 'pantex (fbc77065)', ws: 'Pantex', cwd: 'C:\\Users\\Arthur\\Desktop\\Desktop\\work\\pantex', resume: 'fbc77065-760d-4834-876c-57aef851f51b' },
|
|
60
|
+
|
|
61
|
+
// Myrlin Research
|
|
62
|
+
{ name: 'Big ML Study', ws: 'Myrlin Research', cwd: 'C:\\Users\\Arthur\\Desktop\\claude-workspace-manager' },
|
|
63
|
+
{ name: 'Modding code focus', ws: 'Myrlin Research', cwd: 'C:\\Users\\Arthur\\hytale-asset-factory', resume: '2d1047c7-42ea-4bf8-a17e-1e4d3e448582' },
|
|
64
|
+
{ name: 'hytale-asset-factory - new', ws: 'Myrlin Research', cwd: 'C:\\Users\\Arthur\\hytale-asset-factory' },
|
|
65
|
+
{ name: 'Main Myrlin Debug', ws: 'Myrlin Research', cwd: 'C:\\Users\\Arthur\\hytale-asset-factory', resume: 'c0d5a3a3-9963-49c6-9de3-185b47034260' },
|
|
66
|
+
|
|
67
|
+
// Workbook
|
|
68
|
+
{ name: 'Workbook main', ws: 'Workbook', cwd: 'C:\\Users\\Arthur\\Desktop\\claude-workspace-manager', resume: '4271e03d-7295-40e4-bb35-0fd887c39461' },
|
|
69
|
+
{ name: 'refactor/optimization', ws: 'Workbook', cwd: 'C:\\Users\\Arthur\\Desktop\\claude-workspace-manager', resume: '4ece62ba-44db-49a2-8af5-4c44f85a1514' },
|
|
70
|
+
|
|
71
|
+
// Myrlin Debug/General
|
|
72
|
+
{ name: 'Main Myrlin Debug', ws: 'Myrlin Debug/General', cwd: 'C:\\Users\\Arthur\\hytale-asset-factory', resume: 'c0d5a3a3-9963-49c6-9de3-185b47034260' },
|
|
73
|
+
{ name: 'reddit conversation', ws: 'Myrlin Debug/General', cwd: 'C:\\Users\\Arthur\\hytale-asset-factory', resume: '9af8b4ef-b5d4-4a69-a004-62755e612e39' },
|
|
74
|
+
|
|
75
|
+
// Loussine
|
|
76
|
+
{ name: 'Loussines stuff', ws: 'Loussine', cwd: 'C:\\Users\\Arthur' },
|
|
77
|
+
|
|
78
|
+
// Onnik
|
|
79
|
+
{ name: 'filepro_ai (36b04d1d)', ws: 'Onnik', cwd: 'C:\\Users\\Arthur\\Desktop\\filepro_ai', resume: '36b04d1d-4260-4630-aa1c-283f822dba0e' },
|
|
80
|
+
{ name: 'filepro_ai (4d9d0d40)', ws: 'Onnik', cwd: 'C:\\Users\\Arthur\\Desktop\\filepro_ai', resume: '4d9d0d40-df32-4fb3-bd45-b755ca5618fc' },
|
|
81
|
+
|
|
82
|
+
// Myrlin Platform
|
|
83
|
+
{ name: 'Adidas bot', ws: 'Myrlin Platform', cwd: 'C:\\Users\\Arthur' },
|
|
84
|
+
{ name: 'myrlin portal', ws: 'Myrlin Platform', cwd: 'C:\\Users\\Arthur', resume: 'c0df573d-78ce-40a7-9033-eb392e87395c' },
|
|
85
|
+
|
|
86
|
+
// AI incubator
|
|
87
|
+
{ name: 'M&H Billing Dev', ws: 'AI incubator', cwd: 'C:\\Users\\Arthur\\Desktop\\Work AI Project' },
|
|
88
|
+
{ name: 'Q&A', ws: 'AI incubator', cwd: 'C:\\Users\\Arthur\\Desktop\\Work AI Project', resume: '20553635-833e-4a24-af3b-8cbee03c2d65' },
|
|
89
|
+
{ name: 'random tasking 1', ws: 'AI incubator', cwd: 'C:\\Users\\Arthur\\Desktop\\Work AI Project', resume: 'e964d01e-031d-460a-8988-e9bff6efb949' },
|
|
90
|
+
{ name: 'random tasking 2', ws: 'AI incubator', cwd: 'C:\\Users\\Arthur\\Desktop\\Work AI Project', resume: '00964339-f945-4ba0-aa7f-e1bcb47be118' },
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
let created = 0;
|
|
94
|
+
for (const s of sessions) {
|
|
95
|
+
const wsId = wsMap[s.ws];
|
|
96
|
+
if (!wsId) {
|
|
97
|
+
console.error(' SKIP: no workspace found for', s.ws);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const body = {
|
|
101
|
+
name: s.name,
|
|
102
|
+
workspaceId: wsId,
|
|
103
|
+
workingDir: s.cwd,
|
|
104
|
+
command: 'claude',
|
|
105
|
+
topic: s.name,
|
|
106
|
+
};
|
|
107
|
+
if (s.resume) body.resumeSessionId = s.resume;
|
|
108
|
+
|
|
109
|
+
const result = await apiCall('POST', '/api/sessions', body);
|
|
110
|
+
if (result.session) {
|
|
111
|
+
console.log(' Created:', s.name, '->', s.ws);
|
|
112
|
+
created++;
|
|
113
|
+
} else {
|
|
114
|
+
console.error(' FAILED:', s.name, result.error || JSON.stringify(result));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log('\nDone:', created, 'sessions created');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
main().catch(err => { console.error(err); process.exit(1); });
|
package/src/index.js
CHANGED
|
@@ -1,176 +1,177 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Claude Workspace Manager (CWM)
|
|
4
|
-
* Lightweight terminal workspace manager for Claude Code sessions.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* node src/index.js Launch the TUI
|
|
8
|
-
* node src/index.js --demo Launch with sample demo data
|
|
9
|
-
* node src/index.js --reset Clear all state and start fresh
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const { getStore } = require('./state/store');
|
|
13
|
-
const { getNotificationManager } = require('./core/notifications');
|
|
14
|
-
const { markStaleSessionsStopped } = require('./core/recovery');
|
|
15
|
-
const { createApp } = require('./ui/app');
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
store.
|
|
113
|
-
store.addSessionLog(s1.id, '
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
store.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
store.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
store.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
store.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
notifications.notify('
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Workspace Manager (CWM)
|
|
4
|
+
* Lightweight terminal workspace manager for Claude Code sessions.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node src/index.js Launch the TUI
|
|
8
|
+
* node src/index.js --demo Launch with sample demo data
|
|
9
|
+
* node src/index.js --reset Clear all state and start fresh
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { getStore } = require('./state/store');
|
|
13
|
+
const { getNotificationManager } = require('./core/notifications');
|
|
14
|
+
const { markStaleSessionsStopped } = require('./core/recovery');
|
|
15
|
+
const { createApp } = require('./ui/app');
|
|
16
|
+
const { getDataDir } = require('./utils/data-dir');
|
|
17
|
+
|
|
18
|
+
function main() {
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const isDemo = args.includes('--demo');
|
|
21
|
+
const isReset = args.includes('--reset');
|
|
22
|
+
|
|
23
|
+
// Initialize store
|
|
24
|
+
const store = getStore();
|
|
25
|
+
|
|
26
|
+
// Handle --reset
|
|
27
|
+
if (isReset) {
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
const stateFile = path.join(getDataDir(), 'workspaces.json');
|
|
31
|
+
if (fs.existsSync(stateFile)) {
|
|
32
|
+
fs.unlinkSync(stateFile);
|
|
33
|
+
console.log('State cleared. Restart without --reset.');
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
console.log('No state file found.');
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Initialize notification manager (attaches to store events)
|
|
41
|
+
const notifications = getNotificationManager();
|
|
42
|
+
|
|
43
|
+
// Run recovery check - mark stale sessions as stopped
|
|
44
|
+
const staleIds = markStaleSessionsStopped();
|
|
45
|
+
if (staleIds.length > 0) {
|
|
46
|
+
notifications.notify('warning', 'Recovery',
|
|
47
|
+
`${staleIds.length} session(s) were found stale and marked stopped`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Populate demo data if --demo and no workspaces exist
|
|
51
|
+
if (isDemo && Object.keys(store.workspaces).length === 0) {
|
|
52
|
+
seedDemoData(store, notifications);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Launch the TUI
|
|
56
|
+
const app = createApp(store, notifications.getRecent(5));
|
|
57
|
+
|
|
58
|
+
// Graceful shutdown
|
|
59
|
+
process.on('SIGINT', () => {
|
|
60
|
+
app.destroy();
|
|
61
|
+
process.exit(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
process.on('SIGTERM', () => {
|
|
65
|
+
app.destroy();
|
|
66
|
+
process.exit(0);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
process.on('uncaughtException', (err) => {
|
|
70
|
+
store.save();
|
|
71
|
+
console.error('Uncaught exception:', err.message);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Seed the store with realistic demo data for showcasing the UI
|
|
78
|
+
*/
|
|
79
|
+
function seedDemoData(store, notifications) {
|
|
80
|
+
// Create workspaces
|
|
81
|
+
const ws1 = store.createWorkspace({
|
|
82
|
+
name: 'Project Alpha',
|
|
83
|
+
description: 'Frontend application and components',
|
|
84
|
+
color: 'cyan',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const ws2 = store.createWorkspace({
|
|
88
|
+
name: 'Backend API',
|
|
89
|
+
description: 'Backend API for data processing',
|
|
90
|
+
color: 'magenta',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const ws3 = store.createWorkspace({
|
|
94
|
+
name: 'Documentation',
|
|
95
|
+
description: 'Technical docs and guides',
|
|
96
|
+
color: 'yellow',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Use platform-appropriate demo paths
|
|
100
|
+
const path = require('path');
|
|
101
|
+
const home = require('os').homedir();
|
|
102
|
+
const demoBase = path.join(home, 'Projects');
|
|
103
|
+
|
|
104
|
+
// Create sessions for Project Alpha
|
|
105
|
+
const s1 = store.createSession({
|
|
106
|
+
name: 'ui-components',
|
|
107
|
+
workspaceId: ws1.id,
|
|
108
|
+
workingDir: path.join(demoBase, 'project-alpha', 'src'),
|
|
109
|
+
topic: 'React component library',
|
|
110
|
+
command: 'claude',
|
|
111
|
+
});
|
|
112
|
+
store.updateSession(s1.id, { status: 'running', pid: 12340 });
|
|
113
|
+
store.addSessionLog(s1.id, 'Session launched with PID 12340');
|
|
114
|
+
store.addSessionLog(s1.id, 'Working on data table component');
|
|
115
|
+
|
|
116
|
+
const s2 = store.createSession({
|
|
117
|
+
name: 'perf-analysis',
|
|
118
|
+
workspaceId: ws1.id,
|
|
119
|
+
workingDir: path.join(demoBase, 'project-alpha', 'perf'),
|
|
120
|
+
topic: 'Performance profiling and optimization',
|
|
121
|
+
command: 'claude',
|
|
122
|
+
});
|
|
123
|
+
store.updateSession(s2.id, { status: 'idle', pid: 12341 });
|
|
124
|
+
store.addSessionLog(s2.id, 'Analyzing render performance');
|
|
125
|
+
|
|
126
|
+
const s3 = store.createSession({
|
|
127
|
+
name: 'test-runner',
|
|
128
|
+
workspaceId: ws1.id,
|
|
129
|
+
workingDir: path.join(demoBase, 'project-alpha', 'test'),
|
|
130
|
+
topic: 'Integration tests for UI components',
|
|
131
|
+
command: 'claude',
|
|
132
|
+
});
|
|
133
|
+
store.updateSession(s3.id, { status: 'stopped' });
|
|
134
|
+
store.addSessionLog(s3.id, 'Tests completed: 47/48 passed');
|
|
135
|
+
|
|
136
|
+
// Create sessions for Backend API
|
|
137
|
+
const s4 = store.createSession({
|
|
138
|
+
name: 'api-endpoints',
|
|
139
|
+
workspaceId: ws2.id,
|
|
140
|
+
workingDir: path.join(demoBase, 'backend-api', 'src'),
|
|
141
|
+
topic: 'REST API for resource management',
|
|
142
|
+
command: 'claude',
|
|
143
|
+
});
|
|
144
|
+
store.updateSession(s4.id, { status: 'running', pid: 12345 });
|
|
145
|
+
store.addSessionLog(s4.id, 'Implementing /api/v1/resources endpoint');
|
|
146
|
+
|
|
147
|
+
const s5 = store.createSession({
|
|
148
|
+
name: 'db-migrations',
|
|
149
|
+
workspaceId: ws2.id,
|
|
150
|
+
workingDir: path.join(demoBase, 'backend-api', 'db'),
|
|
151
|
+
topic: 'Database schema and migrations',
|
|
152
|
+
command: 'claude',
|
|
153
|
+
});
|
|
154
|
+
store.updateSession(s5.id, { status: 'error' });
|
|
155
|
+
store.addSessionLog(s5.id, 'Migration failed: FK constraint violation');
|
|
156
|
+
|
|
157
|
+
// Create sessions for Documentation
|
|
158
|
+
const s6 = store.createSession({
|
|
159
|
+
name: 'architecture-docs',
|
|
160
|
+
workspaceId: ws3.id,
|
|
161
|
+
workingDir: path.join(demoBase, 'docs'),
|
|
162
|
+
topic: 'System architecture documentation',
|
|
163
|
+
command: 'claude',
|
|
164
|
+
});
|
|
165
|
+
store.updateSession(s6.id, { status: 'stopped' });
|
|
166
|
+
|
|
167
|
+
// Set Project Alpha as active
|
|
168
|
+
store.setActiveWorkspace(ws1.id);
|
|
169
|
+
|
|
170
|
+
// Add some startup notifications
|
|
171
|
+
notifications.notify('success', 'Demo', 'Demo workspace data loaded');
|
|
172
|
+
notifications.notify('info', 'Welcome', 'Press ? for keyboard shortcuts');
|
|
173
|
+
|
|
174
|
+
store.save();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
main();
|