ai-agent-session-center 1.0.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.
Files changed (41) hide show
  1. package/README.md +618 -0
  2. package/bin/cli.js +20 -0
  3. package/hooks/dashboard-hook-codex.sh +67 -0
  4. package/hooks/dashboard-hook-gemini.sh +102 -0
  5. package/hooks/dashboard-hook.ps1 +147 -0
  6. package/hooks/dashboard-hook.sh +142 -0
  7. package/hooks/dashboard-hooks-backup.json +103 -0
  8. package/hooks/install-hooks.js +543 -0
  9. package/hooks/reset.js +357 -0
  10. package/hooks/setup-wizard.js +156 -0
  11. package/package.json +52 -0
  12. package/public/css/dashboard.css +10200 -0
  13. package/public/index.html +915 -0
  14. package/public/js/analyticsPanel.js +467 -0
  15. package/public/js/app.js +1148 -0
  16. package/public/js/browserDb.js +806 -0
  17. package/public/js/chartUtils.js +383 -0
  18. package/public/js/historyPanel.js +298 -0
  19. package/public/js/movementManager.js +155 -0
  20. package/public/js/navController.js +32 -0
  21. package/public/js/robotManager.js +526 -0
  22. package/public/js/sceneManager.js +7 -0
  23. package/public/js/sessionPanel.js +2477 -0
  24. package/public/js/settingsManager.js +924 -0
  25. package/public/js/soundManager.js +249 -0
  26. package/public/js/statsPanel.js +118 -0
  27. package/public/js/terminalManager.js +391 -0
  28. package/public/js/timelinePanel.js +278 -0
  29. package/public/js/wsClient.js +88 -0
  30. package/server/apiRouter.js +321 -0
  31. package/server/config.js +120 -0
  32. package/server/hookProcessor.js +55 -0
  33. package/server/hookRouter.js +18 -0
  34. package/server/hookStats.js +107 -0
  35. package/server/index.js +314 -0
  36. package/server/logger.js +67 -0
  37. package/server/mqReader.js +218 -0
  38. package/server/serverConfig.js +27 -0
  39. package/server/sessionStore.js +1049 -0
  40. package/server/sshManager.js +339 -0
  41. package/server/wsManager.js +83 -0
@@ -0,0 +1,526 @@
1
+ // robotManager.js — CSS animated character system (multiple character models)
2
+ import * as settingsManager from './settingsManager.js';
3
+
4
+ const COLOR_PALETTE = [
5
+ '#00e5ff', '#ff9100', '#00ff88', '#ff3355',
6
+ '#aa66ff', '#ffdd00', '#ff66aa', '#66ffdd'
7
+ ];
8
+
9
+ const robots = new Map(); // sessionId -> { el, status, colorIndex, model }
10
+ let colorIndex = 0;
11
+
12
+ // ---- Character Templates ----
13
+
14
+ const CHARACTER_TEMPLATES = {
15
+ robot(color) {
16
+ return `
17
+ <div class="robot-shadow"></div>
18
+ <div class="robot-body-wrap">
19
+ <div class="robot-antenna">
20
+ <div class="robot-antenna-stick"></div>
21
+ <div class="robot-antenna-ball"></div>
22
+ </div>
23
+ <div class="robot-head">
24
+ <div class="robot-eye robot-eye-left"></div>
25
+ <div class="robot-eye robot-eye-right"></div>
26
+ <div class="robot-mouth"></div>
27
+ </div>
28
+ <div class="robot-neck"></div>
29
+ <div class="robot-torso">
30
+ <div class="robot-chest-light"></div>
31
+ <div class="robot-typing-dots">
32
+ <span></span><span></span><span></span>
33
+ </div>
34
+ </div>
35
+ </div>`;
36
+ },
37
+
38
+ cat(color) {
39
+ return `
40
+ <div class="robot-shadow"></div>
41
+ <div class="robot-body-wrap">
42
+ <div class="cat-head">
43
+ <div class="cat-ear cat-ear-left"></div>
44
+ <div class="cat-ear cat-ear-right"></div>
45
+ <div class="cat-eye cat-eye-left"></div>
46
+ <div class="cat-eye cat-eye-right"></div>
47
+ <div class="cat-nose"></div>
48
+ <div class="cat-whisker cat-whisker-left"></div>
49
+ <div class="cat-whisker cat-whisker-right"></div>
50
+ <div class="cat-mouth"></div>
51
+ </div>
52
+ <div class="cat-body">
53
+ <div class="cat-chest-spot"></div>
54
+ </div>
55
+ <div class="cat-tail"></div>
56
+ </div>`;
57
+ },
58
+
59
+ alien(color) {
60
+ return `
61
+ <div class="robot-shadow"></div>
62
+ <div class="robot-body-wrap">
63
+ <div class="alien-dome">
64
+ <div class="alien-eye"></div>
65
+ <div class="alien-eye"></div>
66
+ <div class="alien-eye"></div>
67
+ <div class="alien-comm-dots">
68
+ <span></span><span></span><span></span>
69
+ </div>
70
+ </div>
71
+ <div class="alien-neck"></div>
72
+ <div class="alien-body">
73
+ <div class="alien-core"></div>
74
+ <div class="alien-tentacle alien-tentacle-left"></div>
75
+ <div class="alien-tentacle alien-tentacle-right"></div>
76
+ </div>
77
+ </div>`;
78
+ },
79
+
80
+ ghost(color) {
81
+ return `
82
+ <div class="robot-shadow"></div>
83
+ <div class="robot-body-wrap">
84
+ <div class="ghost-body">
85
+ <div class="ghost-eye ghost-eye-left"></div>
86
+ <div class="ghost-eye ghost-eye-right"></div>
87
+ <div class="ghost-mouth"></div>
88
+ <div class="ghost-blush ghost-blush-left"></div>
89
+ <div class="ghost-blush ghost-blush-right"></div>
90
+ </div>
91
+ <div class="ghost-tail"></div>
92
+ </div>`;
93
+ },
94
+
95
+ orb(color) {
96
+ return `
97
+ <div class="robot-shadow"></div>
98
+ <div class="robot-body-wrap">
99
+ <div class="orb-core"></div>
100
+ <div class="orb-ring orb-ring-1"></div>
101
+ <div class="orb-ring orb-ring-2"></div>
102
+ <div class="orb-particles">
103
+ <span></span><span></span><span></span><span></span>
104
+ </div>
105
+ </div>`;
106
+ },
107
+
108
+ dragon(color) {
109
+ return `
110
+ <div class="robot-shadow"></div>
111
+ <div class="robot-body-wrap">
112
+ <div class="dragon-head">
113
+ <div class="dragon-horn dragon-horn-left"></div>
114
+ <div class="dragon-horn dragon-horn-right"></div>
115
+ <div class="dragon-eye dragon-eye-left"></div>
116
+ <div class="dragon-eye dragon-eye-right"></div>
117
+ <div class="dragon-nostril dragon-nostril-left"></div>
118
+ <div class="dragon-nostril dragon-nostril-right"></div>
119
+ <div class="dragon-mouth"></div>
120
+ </div>
121
+ <div class="dragon-neck"></div>
122
+ <div class="dragon-body">
123
+ <div class="dragon-belly"></div>
124
+ <div class="dragon-wing dragon-wing-left"></div>
125
+ <div class="dragon-wing dragon-wing-right"></div>
126
+ </div>
127
+ <div class="dragon-fire">
128
+ <span></span><span></span><span></span>
129
+ </div>
130
+ </div>`;
131
+ },
132
+
133
+ penguin(color) {
134
+ return `
135
+ <div class="robot-shadow"></div>
136
+ <div class="robot-body-wrap">
137
+ <div class="penguin-head">
138
+ <div class="penguin-eye penguin-eye-left"></div>
139
+ <div class="penguin-eye penguin-eye-right"></div>
140
+ <div class="penguin-beak"></div>
141
+ </div>
142
+ <div class="penguin-body">
143
+ <div class="penguin-belly"></div>
144
+ <div class="penguin-flipper penguin-flipper-left"></div>
145
+ <div class="penguin-flipper penguin-flipper-right"></div>
146
+ <div class="penguin-feet"></div>
147
+ </div>
148
+ </div>`;
149
+ },
150
+
151
+ octopus(color) {
152
+ return `
153
+ <div class="robot-shadow"></div>
154
+ <div class="robot-body-wrap">
155
+ <div class="octo-head">
156
+ <div class="octo-eye octo-eye-left"></div>
157
+ <div class="octo-eye octo-eye-right"></div>
158
+ <div class="octo-mouth"></div>
159
+ </div>
160
+ <div class="octo-tentacles">
161
+ <div class="octo-tent octo-tent-1"></div>
162
+ <div class="octo-tent octo-tent-2"></div>
163
+ <div class="octo-tent octo-tent-3"></div>
164
+ <div class="octo-tent octo-tent-4"></div>
165
+ </div>
166
+ </div>`;
167
+ },
168
+
169
+ mushroom(color) {
170
+ return `
171
+ <div class="robot-shadow"></div>
172
+ <div class="robot-body-wrap">
173
+ <div class="mush-cap">
174
+ <div class="mush-spot mush-spot-1"></div>
175
+ <div class="mush-spot mush-spot-2"></div>
176
+ <div class="mush-spot mush-spot-3"></div>
177
+ </div>
178
+ <div class="mush-face">
179
+ <div class="mush-eye mush-eye-left"></div>
180
+ <div class="mush-eye mush-eye-right"></div>
181
+ <div class="mush-mouth"></div>
182
+ </div>
183
+ <div class="mush-stem"></div>
184
+ </div>`;
185
+ },
186
+
187
+ fox(color) {
188
+ return `
189
+ <div class="robot-shadow"></div>
190
+ <div class="robot-body-wrap">
191
+ <div class="fox-head">
192
+ <div class="fox-ear fox-ear-left"></div>
193
+ <div class="fox-ear fox-ear-right"></div>
194
+ <div class="fox-eye fox-eye-left"></div>
195
+ <div class="fox-eye fox-eye-right"></div>
196
+ <div class="fox-snout"></div>
197
+ <div class="fox-nose"></div>
198
+ </div>
199
+ <div class="fox-body">
200
+ <div class="fox-chest"></div>
201
+ </div>
202
+ <div class="fox-tail"></div>
203
+ </div>`;
204
+ },
205
+
206
+ unicorn(color) {
207
+ return `
208
+ <div class="robot-shadow"></div>
209
+ <div class="robot-body-wrap">
210
+ <div class="unicorn-head">
211
+ <div class="unicorn-horn"></div>
212
+ <div class="unicorn-eye unicorn-eye-left"></div>
213
+ <div class="unicorn-eye unicorn-eye-right"></div>
214
+ <div class="unicorn-mane"></div>
215
+ </div>
216
+ <div class="unicorn-body">
217
+ <div class="unicorn-chest"></div>
218
+ </div>
219
+ </div>`;
220
+ },
221
+
222
+ jellyfish(color) {
223
+ return `
224
+ <div class="robot-shadow"></div>
225
+ <div class="robot-body-wrap">
226
+ <div class="jelly-bell">
227
+ <div class="jelly-eye jelly-eye-left"></div>
228
+ <div class="jelly-eye jelly-eye-right"></div>
229
+ <div class="jelly-mouth"></div>
230
+ </div>
231
+ <div class="jelly-tentacles">
232
+ <div class="jelly-tent jelly-tent-1"></div>
233
+ <div class="jelly-tent jelly-tent-2"></div>
234
+ <div class="jelly-tent jelly-tent-3"></div>
235
+ <div class="jelly-tent jelly-tent-4"></div>
236
+ <div class="jelly-tent jelly-tent-5"></div>
237
+ </div>
238
+ </div>`;
239
+ },
240
+
241
+ owl(color) {
242
+ return `
243
+ <div class="robot-shadow"></div>
244
+ <div class="robot-body-wrap">
245
+ <div class="owl-head">
246
+ <div class="owl-tuft owl-tuft-left"></div>
247
+ <div class="owl-tuft owl-tuft-right"></div>
248
+ <div class="owl-eye owl-eye-left"><div class="owl-pupil"></div></div>
249
+ <div class="owl-eye owl-eye-right"><div class="owl-pupil"></div></div>
250
+ <div class="owl-beak"></div>
251
+ </div>
252
+ <div class="owl-body">
253
+ <div class="owl-wing owl-wing-left"></div>
254
+ <div class="owl-wing owl-wing-right"></div>
255
+ <div class="owl-chest"></div>
256
+ </div>
257
+ </div>`;
258
+ },
259
+
260
+ bat(color) {
261
+ return `
262
+ <div class="robot-shadow"></div>
263
+ <div class="robot-body-wrap">
264
+ <div class="bat-head">
265
+ <div class="bat-ear bat-ear-left"></div>
266
+ <div class="bat-ear bat-ear-right"></div>
267
+ <div class="bat-eye bat-eye-left"></div>
268
+ <div class="bat-eye bat-eye-right"></div>
269
+ <div class="bat-fang bat-fang-left"></div>
270
+ <div class="bat-fang bat-fang-right"></div>
271
+ </div>
272
+ <div class="bat-body">
273
+ <div class="bat-wing bat-wing-left"></div>
274
+ <div class="bat-wing bat-wing-right"></div>
275
+ </div>
276
+ </div>`;
277
+ },
278
+
279
+ cactus(color) {
280
+ return `
281
+ <div class="robot-shadow"></div>
282
+ <div class="robot-body-wrap">
283
+ <div class="cactus-flower"></div>
284
+ <div class="cactus-body">
285
+ <div class="cactus-eye cactus-eye-left"></div>
286
+ <div class="cactus-eye cactus-eye-right"></div>
287
+ <div class="cactus-mouth"></div>
288
+ <div class="cactus-arm cactus-arm-left"></div>
289
+ <div class="cactus-arm cactus-arm-right"></div>
290
+ </div>
291
+ </div>`;
292
+ },
293
+
294
+ slime(color) {
295
+ return `
296
+ <div class="robot-shadow"></div>
297
+ <div class="robot-body-wrap">
298
+ <div class="slime-body">
299
+ <div class="slime-eye slime-eye-left"></div>
300
+ <div class="slime-eye slime-eye-right"></div>
301
+ <div class="slime-mouth"></div>
302
+ <div class="slime-shine"></div>
303
+ </div>
304
+ </div>`;
305
+ },
306
+
307
+ pumpkin(color) {
308
+ return `
309
+ <div class="robot-shadow"></div>
310
+ <div class="robot-body-wrap">
311
+ <div class="pumpkin-stem"></div>
312
+ <div class="pumpkin-body">
313
+ <div class="pumpkin-eye pumpkin-eye-left"></div>
314
+ <div class="pumpkin-eye pumpkin-eye-right"></div>
315
+ <div class="pumpkin-mouth"></div>
316
+ <div class="pumpkin-groove pumpkin-groove-left"></div>
317
+ <div class="pumpkin-groove pumpkin-groove-right"></div>
318
+ </div>
319
+ </div>`;
320
+ },
321
+
322
+ yeti(color) {
323
+ return `
324
+ <div class="robot-shadow"></div>
325
+ <div class="robot-body-wrap">
326
+ <div class="yeti-head">
327
+ <div class="yeti-horn yeti-horn-left"></div>
328
+ <div class="yeti-horn yeti-horn-right"></div>
329
+ <div class="yeti-eye yeti-eye-left"></div>
330
+ <div class="yeti-eye yeti-eye-right"></div>
331
+ <div class="yeti-mouth"></div>
332
+ </div>
333
+ <div class="yeti-body">
334
+ <div class="yeti-belly"></div>
335
+ <div class="yeti-fur"></div>
336
+ </div>
337
+ </div>`;
338
+ },
339
+
340
+ crystal(color) {
341
+ return `
342
+ <div class="robot-shadow"></div>
343
+ <div class="robot-body-wrap">
344
+ <div class="crystal-body">
345
+ <div class="crystal-facet crystal-facet-left"></div>
346
+ <div class="crystal-facet crystal-facet-right"></div>
347
+ <div class="crystal-eye crystal-eye-left"></div>
348
+ <div class="crystal-eye crystal-eye-right"></div>
349
+ <div class="crystal-core"></div>
350
+ </div>
351
+ </div>`;
352
+ },
353
+
354
+ bee(color) {
355
+ return `
356
+ <div class="robot-shadow"></div>
357
+ <div class="robot-body-wrap">
358
+ <div class="bee-antenna bee-antenna-left"></div>
359
+ <div class="bee-antenna bee-antenna-right"></div>
360
+ <div class="bee-head">
361
+ <div class="bee-eye bee-eye-left"></div>
362
+ <div class="bee-eye bee-eye-right"></div>
363
+ </div>
364
+ <div class="bee-body">
365
+ <div class="bee-stripe bee-stripe-1"></div>
366
+ <div class="bee-stripe bee-stripe-2"></div>
367
+ <div class="bee-wing bee-wing-left"></div>
368
+ <div class="bee-wing bee-wing-right"></div>
369
+ <div class="bee-stinger"></div>
370
+ </div>
371
+ </div>`;
372
+ }
373
+ };
374
+
375
+ function getCurrentModel() {
376
+ return settingsManager.get('characterModel') || 'robot';
377
+ }
378
+
379
+ export async function loadTemplate() {
380
+ // No-op: CSS characters need no model loading
381
+ }
382
+
383
+ export async function switchModel() {
384
+ // No-op: CSS characters have no 3D model
385
+ }
386
+
387
+ export function createRobot(sessionId, sessionCharModel, sessionColor) {
388
+ const viewport = document.querySelector(
389
+ `.session-card[data-session-id="${sessionId}"] .robot-viewport`
390
+ );
391
+ if (!viewport) return null;
392
+
393
+ // Don't create duplicate
394
+ if (viewport.querySelector('.css-robot')) return robots.get(sessionId) || null;
395
+
396
+ // Use stored color if available, otherwise assign from palette
397
+ let color;
398
+ if (sessionColor) {
399
+ color = sessionColor;
400
+ } else {
401
+ color = COLOR_PALETTE[colorIndex % COLOR_PALETTE.length];
402
+ colorIndex++;
403
+ // Fire-and-forget save color to server
404
+ fetch(`/api/sessions/${sessionId}/accent-color`, {
405
+ method: 'PUT',
406
+ headers: { 'Content-Type': 'application/json' },
407
+ body: JSON.stringify({ color })
408
+ }).catch(() => {});
409
+ }
410
+
411
+ const model = sessionCharModel || getCurrentModel();
412
+ const templateFn = CHARACTER_TEMPLATES[model] || CHARACTER_TEMPLATES.robot;
413
+
414
+ const robot = document.createElement('div');
415
+ robot.className = `css-robot char-${model}`;
416
+ robot.dataset.status = 'idle';
417
+ robot.style.setProperty('--robot-color', color);
418
+
419
+ robot.innerHTML = templateFn(color);
420
+
421
+ viewport.appendChild(robot);
422
+
423
+ const robotData = {
424
+ el: robot,
425
+ status: 'idle',
426
+ color,
427
+ model,
428
+ emoteTimeout: null,
429
+ playEmote() {
430
+ robot.classList.add('robot-emote');
431
+ if (this.emoteTimeout) clearTimeout(this.emoteTimeout);
432
+ this.emoteTimeout = setTimeout(() => {
433
+ robot.classList.remove('robot-emote');
434
+ }, 600);
435
+ }
436
+ };
437
+
438
+ robots.set(sessionId, robotData);
439
+ return robotData;
440
+ }
441
+
442
+ // Get the accent color for a session
443
+ export function getSessionColor(sessionId) {
444
+ const robotData = robots.get(sessionId);
445
+ return robotData ? robotData.color : null;
446
+ }
447
+
448
+ export function updateRobot(session) {
449
+ let robot = robots.get(session.sessionId);
450
+ if (!robot) {
451
+ robot = createRobot(session.sessionId, session.characterModel || null, session.accentColor || null);
452
+ if (!robot) return;
453
+ }
454
+
455
+ // If session has a per-session character model, switch to it
456
+ if (session.characterModel && robot.model !== session.characterModel) {
457
+ switchSessionCharacter(session.sessionId, session.characterModel);
458
+ robot = robots.get(session.sessionId);
459
+ }
460
+
461
+ // Update status
462
+ const newStatus = session.status || 'idle';
463
+ if (robot.status !== newStatus) {
464
+ robot.status = newStatus;
465
+ robot.el.dataset.status = newStatus;
466
+ }
467
+
468
+ // Play emote if requested
469
+ if (session.emote) {
470
+ robot.playEmote(session.emote);
471
+ }
472
+ }
473
+
474
+ export function removeRobot(sessionId) {
475
+ const robot = robots.get(sessionId);
476
+ if (robot && robot.el && robot.el.parentNode) {
477
+ robot.el.remove();
478
+ }
479
+ robots.delete(sessionId);
480
+ }
481
+
482
+ export function updateAll() {
483
+ // No-op: CSS animations are handled by the browser
484
+ }
485
+
486
+ export function getRobots() {
487
+ return robots;
488
+ }
489
+
490
+ // Expose templates for mini previews
491
+ export function _getTemplates() {
492
+ return CHARACTER_TEMPLATES;
493
+ }
494
+
495
+ // Switch a single session's character to a specific model
496
+ export function switchSessionCharacter(sessionId, modelName) {
497
+ const robotData = robots.get(sessionId);
498
+ if (!robotData) return;
499
+ const model = modelName || getCurrentModel();
500
+ const templateFn = CHARACTER_TEMPLATES[model] || CHARACTER_TEMPLATES.robot;
501
+ const el = robotData.el;
502
+ el.className = `css-robot char-${model}`;
503
+ if (robotData.status) el.dataset.status = robotData.status;
504
+ el.innerHTML = templateFn(robotData.color);
505
+ robotData.model = model;
506
+ robotData.perSession = !!modelName;
507
+ }
508
+
509
+ // Switch all existing characters to a new model (skips sessions with per-session override)
510
+ function switchAllCharacters(modelName) {
511
+ const templateFn = CHARACTER_TEMPLATES[modelName] || CHARACTER_TEMPLATES.robot;
512
+ for (const [sessionId, robotData] of robots) {
513
+ // Skip sessions with a per-session character model override
514
+ if (robotData.perSession) continue;
515
+ const el = robotData.el;
516
+ el.className = `css-robot char-${modelName}`;
517
+ if (robotData.status) el.dataset.status = robotData.status;
518
+ el.innerHTML = templateFn(robotData.color);
519
+ robotData.model = modelName;
520
+ }
521
+ }
522
+
523
+ // Listen for setting changes
524
+ settingsManager.onChange('characterModel', (model) => {
525
+ switchAllCharacters(model);
526
+ });
@@ -0,0 +1,7 @@
1
+ // sceneManager.js — Stub (Three.js removed, replaced by CSS robot)
2
+
3
+ export function init() {}
4
+ export function createSessionView() { return {}; }
5
+ export function removeSessionView() {}
6
+ export function getSessionView() { return null; }
7
+ export function render() {}