opencroc 1.8.1 → 1.8.2

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 (71) hide show
  1. package/dist/cli/index.js +755 -8
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.d.ts +128 -1
  4. package/dist/index.js +548 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/web/dist/assets/main-Ccg3eDNK.js +1 -0
  7. package/dist/web/dist/assets/office-runtime-B3iNctxE.css +1 -0
  8. package/dist/web/dist/assets/office-runtime-BsCh82Pj.js +183 -0
  9. package/dist/web/dist/assets/pixel-page-3BYGm7dH.js +470 -0
  10. package/dist/web/dist/assets/react-vendor-C8RhVn0h.js +49 -0
  11. package/dist/web/dist/assets/studio-page-BInoyoV2.css +1 -0
  12. package/dist/web/dist/assets/studio-page-o3SCvE_v.js +351 -0
  13. package/dist/web/dist/assets/three-addons-BdrPp04O.js +470 -0
  14. package/dist/web/dist/assets/three-core-CsxM1PCY.js +4057 -0
  15. package/dist/web/dist/index.html +15 -0
  16. package/dist/web/index.html +11 -572
  17. package/dist/web/public/botreview/char_0.png +0 -0
  18. package/dist/web/public/botreview/char_1.png +0 -0
  19. package/dist/web/public/botreview/char_2.png +0 -0
  20. package/dist/web/public/botreview/coffee-machine.gif +0 -0
  21. package/dist/web/public/botreview/server.gif +0 -0
  22. package/dist/web/public/botreview/walls.png +0 -0
  23. package/dist/web/public/star/desk-v3.webp +0 -0
  24. package/dist/web/public/star/office_bg_small.webp +0 -0
  25. package/dist/web/public/star/star-idle-v5.png +0 -0
  26. package/dist/web/public/star/star-working-spritesheet-grid.webp +0 -0
  27. package/dist/web/src/app/AppLayout.tsx +34 -0
  28. package/dist/web/src/app/AppRouter.tsx +46 -0
  29. package/dist/web/src/app/bootstrap.tsx +22 -0
  30. package/dist/web/src/app/routes.tsx +52 -0
  31. package/dist/web/src/features/office/runtime/index.ts +1 -0
  32. package/dist/web/src/features/office/runtime/mount.ts +809 -0
  33. package/dist/web/src/features/pixel/runtime/index.ts +1 -0
  34. package/dist/web/src/features/pixel/runtime/mount.ts +728 -0
  35. package/dist/web/src/features/studio/runtime/index.ts +1 -0
  36. package/dist/web/src/features/studio/runtime/mount.ts +664 -0
  37. package/dist/web/src/features/three/engine/index.ts +1 -0
  38. package/dist/web/src/main.tsx +7 -0
  39. package/dist/web/src/pages/office/index.ts +1 -0
  40. package/dist/web/src/pages/office/page.tsx +283 -0
  41. package/dist/web/src/pages/pixel/index.ts +1 -0
  42. package/dist/web/src/pages/pixel/page.tsx +564 -0
  43. package/dist/web/src/pages/studio/index.ts +1 -0
  44. package/dist/web/src/pages/studio/page.tsx +446 -0
  45. package/dist/web/{js/agents.js → src/runtime/agents.ts} +304 -31
  46. package/dist/web/{js/camera.js → src/runtime/camera.ts} +12 -5
  47. package/dist/web/{js/dataviz.js → src/runtime/dataviz.ts} +38 -14
  48. package/dist/web/{js/effects.js → src/runtime/effects.ts} +139 -2
  49. package/dist/web/{js/engine.js → src/runtime/engine.ts} +45 -6
  50. package/dist/web/{js/office.js → src/runtime/office.ts} +136 -20
  51. package/dist/web/{js/ui.js → src/runtime/ui.ts} +11 -7
  52. package/dist/web/src/shared/assets.ts +4 -0
  53. package/dist/web/src/shared/navigation.ts +47 -0
  54. package/dist/web/src/styles/app-layout.css +19 -0
  55. package/dist/web/src/styles/office.css +268 -0
  56. package/dist/web/tsconfig.json +28 -0
  57. package/dist/web/vite.config.ts +93 -0
  58. package/package.json +11 -2
  59. package/dist/web/index-studio.html +0 -1644
  60. package/dist/web/index-v2-pixel.html +0 -1571
  61. /package/dist/web/{assets → dist}/botreview/char_0.png +0 -0
  62. /package/dist/web/{assets → dist}/botreview/char_1.png +0 -0
  63. /package/dist/web/{assets → dist}/botreview/char_2.png +0 -0
  64. /package/dist/web/{assets → dist}/botreview/coffee-machine.gif +0 -0
  65. /package/dist/web/{assets → dist}/botreview/server.gif +0 -0
  66. /package/dist/web/{assets → dist}/botreview/walls.png +0 -0
  67. /package/dist/web/{assets → dist}/star/desk-v3.webp +0 -0
  68. /package/dist/web/{assets → dist}/star/office_bg_small.webp +0 -0
  69. /package/dist/web/{assets → dist}/star/star-idle-v5.png +0 -0
  70. /package/dist/web/{assets → dist}/star/star-working-spritesheet-grid.webp +0 -0
  71. /package/dist/web/{js/state.js → src/runtime/state.ts} +0 -0
@@ -0,0 +1,268 @@
1
+ /* OpenCroc Studio 3D - Glassmorphism design system */
2
+
3
+ /* CSS reset */
4
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
5
+ html,body{width:100%;height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans SC","Helvetica Neue",Arial,sans-serif}
6
+ body{background:#000;color:var(--text)}
7
+ #root{width:100%;height:100%}
8
+ ::-webkit-scrollbar{width:6px;height:6px}
9
+ ::-webkit-scrollbar-track{background:transparent}
10
+ ::-webkit-scrollbar-thumb{background:var(--text-subtle);border-radius:3px}
11
+ ::-webkit-scrollbar-thumb:hover{background:var(--text-dim)}
12
+ ::selection{background:var(--accent);color:#000}
13
+
14
+ /* Design tokens: dark */
15
+ :root{
16
+ --bg-void:#050510;--bg-deep:#0a0f1e;
17
+ --bg-panel:rgba(12,18,36,0.75);--bg-panel-solid:#0c1224;
18
+ --bg-card:rgba(18,26,50,0.6);--bg-hover:rgba(30,42,72,0.5);
19
+ --bg-glass:rgba(15,22,42,0.55);--bg-glass-strong:rgba(15,22,42,0.8);
20
+ --bg-frosted:rgba(20,28,52,0.45);--bg-input:rgba(15,22,44,0.6);
21
+ --accent:#34d399;--accent-rgb:52,211,153;--accent-dim:#059669;
22
+ --accent-glow:rgba(52,211,153,0.4);--accent-bg:rgba(52,211,153,0.1);
23
+ --red:#f87171;--red-rgb:248,113,113;--red-glow:rgba(248,113,113,0.35);--red-bg:rgba(248,113,113,0.1);
24
+ --orange:#fbbf24;--orange-rgb:251,191,36;--orange-glow:rgba(251,191,36,0.35);--orange-bg:rgba(251,191,36,0.1);
25
+ --blue:#60a5fa;--blue-rgb:96,165,250;--blue-glow:rgba(96,165,250,0.35);--blue-bg:rgba(96,165,250,0.1);
26
+ --purple:#a78bfa;--purple-rgb:167,139,250;--purple-glow:rgba(167,139,250,0.35);--purple-bg:rgba(167,139,250,0.1);
27
+ --cyan:#22d3ee;--cyan-rgb:34,211,238;--cyan-glow:rgba(34,211,238,0.35);--cyan-bg:rgba(34,211,238,0.1);
28
+ --pink:#f472b6;--pink-rgb:244,114,182;
29
+ --text:#f1f5f9;--text-dim:#94a3b8;--text-subtle:#4a5568;--text-muted:#2d3748;
30
+ --border:rgba(148,163,184,0.12);--border-accent:rgba(52,211,153,0.25);--border-glass:rgba(255,255,255,0.06);
31
+ --shadow-xl:0 25px 50px -12px rgba(0,0,0,0.6);--shadow-lg:0 20px 40px rgba(0,0,0,0.4);
32
+ --shadow-md:0 8px 24px rgba(0,0,0,0.3);--shadow-sm:0 2px 8px rgba(0,0,0,0.2);
33
+ --shadow-glow:0 0 30px rgba(52,211,153,0.15);--shadow-inset:inset 0 1px 0 rgba(255,255,255,0.05);
34
+ --blur-lg:blur(24px);--blur-md:blur(16px);--blur-sm:blur(8px);--blur-xs:blur(4px);
35
+ --radius-xl:20px;--radius-lg:14px;--radius-md:10px;--radius-sm:6px;--radius-xs:4px;--radius-full:9999px;
36
+ --ease-out-expo:cubic-bezier(0.16,1,0.3,1);--ease-spring:cubic-bezier(0.175,0.885,0.32,1.275);
37
+ --transition-fast:0.15s var(--ease-out-expo);--transition:0.25s var(--ease-out-expo);
38
+ --transition-slow:0.4s var(--ease-out-expo);--transition-spring:0.5s var(--ease-spring);
39
+ --z-canvas:0;--z-overlay:10;--z-panel:20;--z-header:30;--z-modal:40;--z-tooltip:50;--z-notify:60;
40
+ }
41
+
42
+ /* Design tokens: light */
43
+ [data-theme="light"]{
44
+ --bg-void:#e8ecf4;--bg-deep:#f0f4fa;
45
+ --bg-panel:rgba(255,255,255,0.78);--bg-panel-solid:#ffffff;
46
+ --bg-card:rgba(248,250,255,0.7);--bg-hover:rgba(226,232,240,0.6);
47
+ --bg-glass:rgba(255,255,255,0.6);--bg-glass-strong:rgba(255,255,255,0.85);
48
+ --bg-frosted:rgba(255,255,255,0.5);--bg-input:rgba(241,245,249,0.8);
49
+ --accent:#059669;--accent-rgb:5,150,105;--accent-dim:#047857;
50
+ --accent-glow:rgba(5,150,105,0.25);--accent-bg:rgba(5,150,105,0.08);
51
+ --red:#dc2626;--red-rgb:220,38,38;--red-glow:rgba(220,38,38,0.2);--red-bg:rgba(220,38,38,0.06);
52
+ --orange:#d97706;--orange-rgb:217,119,6;--orange-glow:rgba(217,119,6,0.2);--orange-bg:rgba(217,119,6,0.06);
53
+ --blue:#2563eb;--blue-rgb:37,99,235;--blue-glow:rgba(37,99,235,0.2);--blue-bg:rgba(37,99,235,0.06);
54
+ --purple:#7c3aed;--purple-rgb:124,58,237;--purple-glow:rgba(124,58,237,0.2);--purple-bg:rgba(124,58,237,0.06);
55
+ --cyan:#0891b2;--cyan-rgb:8,145,178;--cyan-glow:rgba(8,145,178,0.2);--cyan-bg:rgba(8,145,178,0.06);
56
+ --pink:#db2777;--pink-rgb:219,39,119;
57
+ --text:#0f172a;--text-dim:#475569;--text-subtle:#94a3b8;--text-muted:#cbd5e1;
58
+ --border:rgba(100,116,139,0.15);--border-accent:rgba(5,150,105,0.3);--border-glass:rgba(0,0,0,0.04);
59
+ --shadow-xl:0 25px 50px -12px rgba(0,0,0,0.12);--shadow-lg:0 20px 40px rgba(0,0,0,0.06);
60
+ --shadow-md:0 8px 24px rgba(0,0,0,0.05);--shadow-sm:0 2px 8px rgba(0,0,0,0.03);
61
+ --shadow-glow:0 0 30px rgba(5,150,105,0.08);--shadow-inset:inset 0 1px 0 rgba(255,255,255,0.8);
62
+ }
63
+
64
+ /* 3D canvas */
65
+ #three-canvas{position:fixed;inset:0;width:100%;height:100%;z-index:var(--z-canvas);display:block}
66
+
67
+ /* Glass panel base */
68
+ .glass{background:var(--bg-glass);backdrop-filter:var(--blur-md);-webkit-backdrop-filter:var(--blur-md);border:1px solid var(--border-glass);box-shadow:var(--shadow-md),var(--shadow-inset);border-radius:var(--radius-lg);transition:background var(--transition),border-color var(--transition),box-shadow var(--transition)}
69
+ .glass:hover{background:var(--bg-glass-strong);border-color:var(--border);box-shadow:var(--shadow-lg),var(--shadow-inset)}
70
+ .glass-strong{background:var(--bg-glass-strong);backdrop-filter:var(--blur-lg);-webkit-backdrop-filter:var(--blur-lg);border:1px solid var(--border);box-shadow:var(--shadow-lg),var(--shadow-inset);border-radius:var(--radius-lg)}
71
+
72
+ /* Header */
73
+ .header{position:fixed;top:12px;left:12px;right:12px;height:52px;z-index:var(--z-header);display:flex;align-items:center;gap:8px;padding:0 16px;background:var(--bg-glass-strong);backdrop-filter:var(--blur-lg);-webkit-backdrop-filter:var(--blur-lg);border:1px solid var(--border-glass);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg),var(--shadow-inset);transition:all var(--transition)}
74
+ .header::before{content:'';position:absolute;inset:0;border-radius:var(--radius-xl);background:linear-gradient(135deg,rgba(var(--accent-rgb),0.05),transparent 60%);pointer-events:none}
75
+ .logo{width:32px;height:32px;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--accent-bg);border:1px solid var(--border-accent);border-radius:var(--radius-md);transition:all var(--transition)}
76
+ .logo:hover{transform:scale(1.08) rotate(-3deg);box-shadow:var(--shadow-glow)}
77
+ .logo svg{width:20px;height:20px}
78
+ .title-wrap{display:flex;flex-direction:column;gap:0;margin-right:16px;min-width:0}
79
+ .title-wrap h1{font-size:14px;font-weight:700;letter-spacing:-0.02em;color:var(--text);line-height:1.2;white-space:nowrap}
80
+ .title-wrap .subtitle{font-size:10px;color:var(--text-subtle);letter-spacing:0.05em;text-transform:uppercase;line-height:1}
81
+ .h-divider{width:1px;height:28px;flex-shrink:0;background:var(--border);margin:0 4px}
82
+
83
+ /* View Switch */
84
+ .view-switch{display:flex;gap:2px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-md);padding:2px}
85
+ .view-switch button{display:flex;align-items:center;gap:5px;padding:5px 12px;border:none;border-radius:var(--radius-sm);font-size:12px;font-weight:500;color:var(--text-dim);cursor:pointer;background:transparent;transition:all var(--transition);white-space:nowrap}
86
+ .view-switch button:hover{color:var(--text);background:var(--bg-hover)}
87
+ .view-switch button.active{color:var(--text);background:var(--bg-panel);box-shadow:var(--shadow-sm)}
88
+ .view-switch button svg{width:14px;height:14px;flex-shrink:0}
89
+
90
+ /* Actions */
91
+ .actions{display:flex;gap:4px;align-items:center;flex-shrink:0}
92
+ .btn{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border:1px solid var(--border);border-radius:var(--radius-sm);cursor:pointer;font-size:12px;font-weight:600;transition:all var(--transition);white-space:nowrap;position:relative;overflow:hidden}
93
+ .btn::before{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(255,255,255,0.06),transparent);pointer-events:none}
94
+ .btn-primary{background:var(--accent);color:#000;border-color:var(--accent-dim)}
95
+ .btn-primary:hover{background:var(--accent-dim);transform:translateY(-1px);box-shadow:0 4px 16px var(--accent-glow)}
96
+ .btn-danger{background:var(--red-bg);color:var(--red);border-color:rgba(var(--red-rgb),0.25)}
97
+ .btn-danger:hover{background:rgba(var(--red-rgb),0.18);transform:translateY(-1px);box-shadow:0 4px 16px var(--red-glow)}
98
+ .btn-secondary{background:var(--bg-card);color:var(--text-dim)}
99
+ .btn-secondary:hover{background:var(--bg-hover);color:var(--text);transform:translateY(-1px)}
100
+ .btn:disabled{opacity:0.4;cursor:not-allowed;transform:none!important;box-shadow:none!important}
101
+ .btn svg{width:14px;height:14px;flex-shrink:0}
102
+ .btn:active{transform:translateY(0)}
103
+
104
+ /* Run Mode */
105
+ .run-mode-wrap{position:relative}
106
+ .run-mode-wrap select{appearance:none;background:var(--bg-card);color:var(--text-dim);border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 28px 5px 10px;font-size:12px;font-weight:500;cursor:pointer;transition:all var(--transition);outline:none}
107
+ .run-mode-wrap select:hover{border-color:var(--border-accent);color:var(--text)}
108
+ .run-mode-wrap::after{content:'>';position:absolute;right:8px;top:50%;transform:translateY(-50%) rotate(90deg);color:var(--text-subtle);font-size:10px;pointer-events:none}
109
+
110
+ /* Stats */
111
+ .stats{display:flex;gap:2px;margin-left:auto;flex-shrink:0}
112
+ .stat-box{display:flex;flex-direction:column;align-items:center;padding:4px 12px;min-width:56px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-sm);transition:all var(--transition)}
113
+ .stat-box:first-child{border-radius:var(--radius-sm) var(--radius-xs) var(--radius-xs) var(--radius-sm)}
114
+ .stat-box:last-child{border-radius:var(--radius-xs) var(--radius-sm) var(--radius-sm) var(--radius-xs)}
115
+ .stat-box:hover{background:var(--bg-hover);border-color:var(--border-accent)}
116
+ .stat-label{font-size:9px;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-subtle);line-height:1}
117
+ .stat-value{font-size:16px;font-weight:700;color:var(--accent);line-height:1.3;font-variant-numeric:tabular-nums}
118
+
119
+ /* Header end */
120
+ .header-end{display:flex;align-items:center;gap:6px;margin-left:8px}
121
+ #theme-toggle{width:32px;height:32px;border:none;background:var(--bg-card);border-radius:var(--radius-sm);cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-dim);transition:all var(--transition);border:1px solid var(--border)}
122
+ #theme-toggle:hover{background:var(--bg-hover);color:var(--text);transform:scale(1.05)}
123
+ #theme-toggle svg{width:16px;height:16px}
124
+ #conn-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:var(--text-subtle);transition:background 0.3s}
125
+ #conn-dot.connected{background:var(--accent);box-shadow:0 0 8px var(--accent-glow);animation:conn-pulse 2s infinite}
126
+
127
+ /* Sidebar */
128
+ .sidebar{position:fixed;top:76px;left:12px;bottom:240px;width:220px;z-index:var(--z-panel);display:flex;flex-direction:column;overflow:hidden;background:var(--bg-glass);backdrop-filter:var(--blur-md);-webkit-backdrop-filter:var(--blur-md);border:1px solid var(--border-glass);border-radius:var(--radius-lg);box-shadow:var(--shadow-md),var(--shadow-inset);transition:all var(--transition-slow)}
129
+ .sidebar.collapsed{width:48px}
130
+ .sidebar.collapsed .sidebar-content{opacity:0;pointer-events:none}
131
+ .sidebar.collapsed .sidebar-toggle svg{transform:rotate(180deg)}
132
+ .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:12px 14px 8px;flex-shrink:0}
133
+ .sidebar-header h3{font-size:11px;text-transform:uppercase;letter-spacing:0.08em;color:var(--text-subtle);font-weight:600}
134
+ .sidebar-toggle{width:24px;height:24px;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-subtle);border-radius:var(--radius-xs);transition:all var(--transition)}
135
+ .sidebar-toggle:hover{background:var(--bg-hover);color:var(--text)}
136
+ .sidebar-toggle svg{width:14px;height:14px;transition:transform var(--transition)}
137
+ .sidebar-content{flex:1;overflow-y:auto;padding:0 8px 8px;transition:opacity var(--transition)}
138
+ .mod-item{display:flex;align-items:center;gap:8px;padding:7px 10px;margin-bottom:2px;border-radius:var(--radius-sm);cursor:pointer;transition:all var(--transition)}
139
+ .mod-item:hover{background:var(--bg-hover)}
140
+ .mod-item.active{background:var(--accent-bg);color:var(--accent)}
141
+ .mod-item .dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;background:var(--accent);opacity:0.6;transition:all var(--transition)}
142
+ .mod-item:hover .dot{opacity:1;transform:scale(1.3)}
143
+ .mod-item .name{flex:1;font-size:12px;font-weight:500;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:color var(--transition)}
144
+ .mod-item:hover .name{color:var(--text)}
145
+ .mod-item .count{font-size:11px;color:var(--text-subtle);font-variant-numeric:tabular-nums;padding:1px 6px;background:var(--bg-card);border-radius:var(--radius-xs);font-weight:500;transition:all var(--transition)}
146
+ .mod-item:hover .count{background:var(--bg-hover);color:var(--text-dim)}
147
+ .agent-item{display:flex;align-items:center;gap:8px;padding:8px 10px;margin-bottom:2px;border-radius:var(--radius-sm);transition:all var(--transition)}
148
+ .agent-item .status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;transition:all 0.3s}
149
+ .agent-item .status-dot.working{background:var(--accent);box-shadow:0 0 6px var(--accent-glow);animation:dot-pulse 1s infinite}
150
+ .agent-item .status-dot.testing{background:var(--blue);box-shadow:0 0 6px var(--blue-glow);animation:dot-pulse 1s infinite}
151
+ .agent-item .status-dot.thinking{background:var(--purple);box-shadow:0 0 6px var(--purple-glow);animation:dot-pulse 1.2s infinite}
152
+ .agent-item .status-dot.error,.agent-item .status-dot.failed{background:var(--red);box-shadow:0 0 6px var(--red-glow);animation:dot-shake 0.3s infinite}
153
+ .agent-item .status-dot.done,.agent-item .status-dot.passed{background:var(--accent);box-shadow:0 0 6px var(--accent-glow)}
154
+ .agent-item .status-dot.idle{background:var(--text-subtle)}
155
+ .agent-item .agent-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
156
+ .agent-item .agent-name{font-size:12px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
157
+ .agent-item .agent-role{font-size:10px;color:var(--text-subtle);text-transform:uppercase;letter-spacing:0.04em}
158
+
159
+ /* Right panel */
160
+ .right-panel{position:fixed;top:76px;right:12px;bottom:240px;width:320px;z-index:var(--z-panel);display:flex;flex-direction:column;background:var(--bg-glass);backdrop-filter:var(--blur-md);-webkit-backdrop-filter:var(--blur-md);border:1px solid var(--border-glass);border-radius:var(--radius-lg);box-shadow:var(--shadow-md),var(--shadow-inset);overflow:hidden;transition:all var(--transition-slow)}
161
+ .panel-tabs{display:flex;gap:0;padding:6px 6px 0;flex-shrink:0;border-bottom:1px solid var(--border)}
162
+ .tab{flex:1;display:flex;align-items:center;justify-content:center;gap:5px;padding:8px 4px;border:none;background:transparent;font-size:12px;font-weight:500;color:var(--text-subtle);cursor:pointer;position:relative;border-radius:var(--radius-sm) var(--radius-sm) 0 0;transition:all var(--transition);white-space:nowrap}
163
+ .tab:hover{color:var(--text-dim);background:var(--bg-hover)}
164
+ .tab.active{color:var(--accent);background:var(--bg-card)}
165
+ .tab.active::after{content:'';position:absolute;bottom:0;left:20%;right:20%;height:2px;background:var(--accent);border-radius:1px}
166
+ .tab svg{width:13px;height:13px;flex-shrink:0}
167
+ .tab-badge{font-size:9px;font-weight:700;min-width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;background:var(--accent-bg);color:var(--accent);border-radius:var(--radius-full);padding:0 4px;font-variant-numeric:tabular-nums}
168
+ .tab-badge.alert{background:var(--red-bg);color:var(--red)}
169
+ .panel-content{flex:1;overflow-y:auto;padding:8px}
170
+ .panel-content.hidden{display:none}
171
+
172
+ /* Log */
173
+ .log-entry{padding:5px 10px;margin-bottom:2px;border-radius:var(--radius-xs);font-size:12px;line-height:1.5;font-family:"SF Mono","Fira Code","Cascadia Code",Consolas,monospace;transition:background var(--transition);display:flex;gap:8px;align-items:flex-start}
174
+ .log-entry:hover{background:var(--bg-hover)}
175
+ .log-entry .timestamp{color:var(--text-subtle);font-size:10px;flex-shrink:0;font-variant-numeric:tabular-nums;padding-top:1px}
176
+ .log-entry .message{color:var(--text-dim);word-break:break-word;flex:1}
177
+ .log-entry.warn .message{color:var(--orange)}
178
+ .log-entry.error .message{color:var(--red)}
179
+ .log-entry.success .message{color:var(--accent)}
180
+ .tw-cursor{display:inline-block;width:2px;height:1em;background:var(--accent);margin-left:2px;vertical-align:text-bottom;animation:tw-blink 0.6s step-end infinite}
181
+ @keyframes tw-blink{0%,100%{opacity:1}50%{opacity:0}}
182
+
183
+ /* Files */
184
+ .file-item{display:flex;align-items:center;gap:8px;padding:8px 10px;margin-bottom:2px;border-radius:var(--radius-sm);cursor:pointer;transition:all var(--transition)}
185
+ .file-item:hover{background:var(--bg-hover)}
186
+ .file-item svg{width:14px;height:14px;flex-shrink:0;color:var(--text-subtle)}
187
+ .file-item .file-name{flex:1;font-size:12px;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
188
+ .file-item:hover .file-name{color:var(--text)}
189
+
190
+ /* Results */
191
+ .results-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:4px}
192
+ .result-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-md);padding:12px;display:flex;flex-direction:column;gap:4px;transition:all var(--transition)}
193
+ .result-card:hover{border-color:var(--border-accent);background:var(--bg-hover)}
194
+ .result-card .label{font-size:10px;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-subtle)}
195
+ .result-card .value{font-size:24px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1}
196
+ .result-card.passed .value{color:var(--accent)}
197
+ .result-card.failed .value{color:var(--red)}
198
+ .result-card.skipped .value{color:var(--orange)}
199
+ .result-card.timeout .value{color:var(--purple)}
200
+ .pass-rate-bar{height:6px;background:var(--bg-card);border-radius:3px;overflow:hidden;margin:8px 4px;border:1px solid var(--border)}
201
+ .pass-rate-bar .fill{height:100%;border-radius:3px;background:linear-gradient(90deg,var(--accent),var(--cyan));transition:width 0.8s var(--ease-out-expo)}
202
+ .quality-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px;padding:4px}
203
+ .quality-item{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px;text-align:center;transition:all var(--transition)}
204
+ .quality-item:hover{border-color:var(--border-accent)}
205
+ .quality-item .q-label{font-size:9px;text-transform:uppercase;letter-spacing:0.04em;color:var(--text-subtle)}
206
+ .quality-item .q-value{font-size:14px;font-weight:700;color:var(--blue);margin-top:2px}
207
+
208
+ /* File preview modal */
209
+ .file-preview{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--transition)}
210
+ .file-preview.visible{opacity:1;pointer-events:auto}
211
+ .file-preview .backdrop{position:absolute;inset:0;background:rgba(0,0,0,0.5);backdrop-filter:var(--blur-sm)}
212
+ .file-preview .fp-dialog{position:relative;width:min(800px,90vw);height:min(600px,80vh);background:var(--bg-glass-strong);backdrop-filter:var(--blur-lg);border:1px solid var(--border);border-radius:var(--radius-xl);box-shadow:var(--shadow-xl);display:flex;flex-direction:column;overflow:hidden;transform:scale(0.95) translateY(10px);transition:transform var(--transition-spring)}
213
+ .file-preview.visible .fp-dialog{transform:scale(1) translateY(0)}
214
+ .fp-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);flex-shrink:0}
215
+ .fp-header .fp-title{font-size:13px;font-weight:600;color:var(--text)}
216
+ .fp-header .fp-close{width:28px;height:28px;border:none;background:var(--bg-card);border-radius:var(--radius-sm);cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-dim);transition:all var(--transition);border:1px solid var(--border)}
217
+ .fp-header .fp-close:hover{background:var(--red-bg);color:var(--red);border-color:rgba(var(--red-rgb),0.25)}
218
+ .fp-code{flex:1;overflow:auto;padding:16px;font-family:"SF Mono","Fira Code","Cascadia Code",Consolas,monospace;font-size:12px;line-height:1.6;color:var(--text-dim);white-space:pre-wrap;word-break:break-all;tab-size:2}
219
+
220
+ /* Tooltip */
221
+ .tooltip{position:fixed;z-index:var(--z-tooltip);padding:6px 10px;background:var(--bg-glass-strong);backdrop-filter:var(--blur-md);border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);font-size:11px;color:var(--text);pointer-events:none;opacity:0;transition:opacity 0.15s;max-width:280px}
222
+ .tooltip.visible{opacity:1}
223
+
224
+ /* Shortcut legend */
225
+ .shortcut-legend{position:fixed;bottom:240px;right:12px;z-index:var(--z-notify);display:grid;grid-template-columns:auto 1fr;gap:4px 10px;padding:12px 16px;background:var(--bg-glass-strong);backdrop-filter:var(--blur-lg);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);opacity:0;transform:translateY(8px) scale(0.96);pointer-events:none;transition:all var(--transition-spring)}
226
+ .shortcut-legend.visible{opacity:1;transform:translateY(0) scale(1);pointer-events:auto}
227
+ .shortcut-legend kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 6px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:11px;font-weight:600;color:var(--text);font-family:inherit;box-shadow:0 1px 2px rgba(0,0,0,0.15)}
228
+ .shortcut-legend span{font-size:12px;color:var(--text-dim);display:flex;align-items:center}
229
+
230
+ /* Loading */
231
+ .loading-overlay{position:fixed;inset:0;z-index:100;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;background:var(--bg-void);transition:opacity 0.8s var(--ease-out-expo)}
232
+ .loading-overlay.hidden{opacity:0;pointer-events:none}
233
+ .loading-bar{width:200px;height:3px;background:var(--bg-card);border-radius:2px;overflow:hidden}
234
+ .loading-bar .fill{width:0%;height:100%;background:linear-gradient(90deg,var(--accent),var(--cyan));border-radius:2px;transition:width 0.3s var(--ease-out-expo)}
235
+ .loading-text{font-size:12px;color:var(--text-subtle);letter-spacing:0.04em}
236
+
237
+ /* Toast */
238
+ .toast-container{position:fixed;top:76px;right:12px;z-index:var(--z-notify);display:flex;flex-direction:column;gap:8px;pointer-events:none}
239
+ .toast{display:flex;align-items:center;gap:8px;padding:10px 16px;background:var(--bg-glass-strong);backdrop-filter:var(--blur-md);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);font-size:12px;color:var(--text);pointer-events:auto;animation:toast-in 0.4s var(--ease-spring),toast-out 0.3s ease-in 3.7s forwards;max-width:320px}
240
+ .toast.success{border-left:3px solid var(--accent)}
241
+ .toast.error{border-left:3px solid var(--red)}
242
+ .toast.warning{border-left:3px solid var(--orange)}
243
+ .toast.info{border-left:3px solid var(--blue)}
244
+
245
+ /* 3D HUD */
246
+ .bubble-3d{padding:6px 12px;background:var(--bg-glass-strong);backdrop-filter:var(--blur-sm);border:1px solid var(--border-accent);border-radius:12px 12px 12px 2px;font-size:12px;color:var(--text);box-shadow:var(--shadow-sm);animation:bubble-3d-in 0.3s var(--ease-spring);pointer-events:none;white-space:nowrap}
247
+ .agent-label-3d{padding:3px 8px;background:var(--bg-glass);backdrop-filter:var(--blur-xs);border:1px solid var(--border-glass);border-radius:var(--radius-sm);font-size:10px;font-weight:600;color:var(--text);text-align:center;pointer-events:none;box-shadow:var(--shadow-sm);white-space:nowrap}
248
+ .agent-label-3d .role{display:block;font-size:8px;font-weight:400;color:var(--text-subtle);text-transform:uppercase;letter-spacing:0.04em}
249
+
250
+ /* Animations */
251
+ @keyframes conn-pulse{0%{box-shadow:0 0 0 0 var(--accent-glow)}70%{box-shadow:0 0 0 6px transparent}100%{box-shadow:0 0 0 0 transparent}}
252
+ @keyframes dot-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:0.5;transform:scale(0.85)}}
253
+ @keyframes dot-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-1px)}75%{transform:translateX(1px)}}
254
+ @keyframes toast-in{from{opacity:0;transform:translateX(40px) scale(0.9)}to{opacity:1;transform:translateX(0) scale(1)}}
255
+ @keyframes toast-out{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(40px)}}
256
+ @keyframes bubble-3d-in{from{opacity:0;transform:translateY(6px) scale(0.9)}to{opacity:1;transform:translateY(0) scale(1)}}
257
+ @keyframes skeleton-pulse{0%{background-position:200% 0}100%{background-position:-200% 0}}
258
+ @keyframes float-gentle{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
259
+ @keyframes rotate-slow{from{transform:rotate(0)}to{transform:rotate(360deg)}}
260
+ @keyframes glow-pulse{0%,100%{opacity:0.6}50%{opacity:1}}
261
+ .skeleton{background:linear-gradient(90deg,var(--bg-card) 25%,var(--bg-hover) 50%,var(--bg-card) 75%);background-size:200% 100%;animation:skeleton-pulse 1.5s ease infinite;border-radius:var(--radius-sm)}
262
+
263
+ /* Responsive */
264
+ @media(max-width:1200px){.sidebar{width:180px}.right-panel{width:280px}.stats{display:none}}
265
+ @media(max-width:960px){.sidebar{display:none}.right-panel{width:260px}}
266
+ @media(max-width:768px){.header{padding:0 10px;gap:4px}.right-panel{display:none}}
267
+ @media print{.header,.sidebar,.right-panel,.shortcut-legend,.tooltip,.file-preview,.loading-overlay,.toast-container{display:none!important}#three-canvas{position:static;width:100%;height:auto}}
268
+
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": true,
5
+ "baseUrl": ".",
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
9
+ "jsx": "react-jsx",
10
+ "strict": false,
11
+ "noImplicitAny": false,
12
+ "noCheck": true,
13
+ "noEmit": true,
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "skipLibCheck": true,
17
+ "types": ["vite/client"],
18
+ "paths": {
19
+ "@app/*": ["src/app/*"],
20
+ "@pages/*": ["src/pages/*"],
21
+ "@features/*": ["src/features/*"],
22
+ "@shared/*": ["src/shared/*"],
23
+ "@runtime/*": ["src/runtime/*"],
24
+ "@styles/*": ["src/styles/*"]
25
+ }
26
+ },
27
+ "include": ["src/**/*", "vite.config.ts"]
28
+ }
@@ -0,0 +1,93 @@
1
+ import { resolve } from 'node:path';
2
+ import react from '@vitejs/plugin-react';
3
+ import { defineConfig } from 'vite';
4
+
5
+ const webRoot = __dirname;
6
+ const appRoot = resolve(__dirname, 'src');
7
+
8
+ export default defineConfig({
9
+ root: webRoot,
10
+ base: '/dist/',
11
+ publicDir: resolve(webRoot, 'public'),
12
+ plugins: [react()],
13
+ resolve: {
14
+ alias: {
15
+ '@app': resolve(appRoot, 'app'),
16
+ '@pages': resolve(appRoot, 'pages'),
17
+ '@features': resolve(appRoot, 'features'),
18
+ '@shared': resolve(appRoot, 'shared'),
19
+ '@runtime': resolve(appRoot, 'runtime'),
20
+ '@styles': resolve(appRoot, 'styles'),
21
+ },
22
+ },
23
+ server: {
24
+ host: 'localhost',
25
+ port: 5173,
26
+ },
27
+ build: {
28
+ outDir: resolve(__dirname, 'dist'),
29
+ emptyOutDir: true,
30
+ chunkSizeWarningLimit: 520,
31
+ rollupOptions: {
32
+ input: {
33
+ main: resolve(webRoot, 'index.html'),
34
+ },
35
+ output: {
36
+ manualChunks(id) {
37
+ const normalizedId = id.split('\\').join('/');
38
+
39
+ if (normalizedId.includes('/node_modules/')) {
40
+ if (
41
+ normalizedId.includes('/node_modules/react/') ||
42
+ normalizedId.includes('/node_modules/react-dom/') ||
43
+ normalizedId.includes('/node_modules/scheduler/')
44
+ ) {
45
+ return 'react-vendor';
46
+ }
47
+ if (normalizedId.includes('/node_modules/three/')) {
48
+ if (normalizedId.includes('/node_modules/three/examples/')) {
49
+ return 'three-addons';
50
+ }
51
+ if (
52
+ normalizedId.includes('/node_modules/three/build/') ||
53
+ normalizedId.includes('/node_modules/three/src/')
54
+ ) {
55
+ return 'three-core';
56
+ }
57
+ return 'three-vendor';
58
+ }
59
+ return 'vendor';
60
+ }
61
+
62
+ if (
63
+ normalizedId.includes('/src/web/src/features/office/') ||
64
+ normalizedId.includes('/src/web/src/features/three/') ||
65
+ normalizedId.includes('/src/web/src/pages/office/') ||
66
+ normalizedId.includes('/src/web/src/runtime/')
67
+ ) {
68
+ return 'office-runtime';
69
+ }
70
+
71
+ if (
72
+ normalizedId.includes('/src/web/src/app/routes') ||
73
+ normalizedId.includes('/src/web/src/app/AppRouter') ||
74
+ normalizedId.includes('/src/web/src/pages/studio/') ||
75
+ normalizedId.includes('/src/web/src/features/studio/runtime/')
76
+ ) {
77
+ return 'studio-page';
78
+ }
79
+
80
+ if (
81
+ normalizedId.includes('/src/web/src/app/routes') ||
82
+ normalizedId.includes('/src/web/src/pages/pixel/') ||
83
+ normalizedId.includes('/src/web/src/features/pixel/runtime/')
84
+ ) {
85
+ return 'pixel-page';
86
+ }
87
+
88
+ return undefined;
89
+ },
90
+ },
91
+ },
92
+ },
93
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencroc",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "AI-native project intelligence platform — universal scanner, knowledge graph, risk analysis, multi-perspective reports, and E2E testing",
5
5
  "keywords": [
6
6
  "project-intelligence",
@@ -39,9 +39,11 @@
39
39
  "LICENSE"
40
40
  ],
41
41
  "scripts": {
42
- "build": "tsup",
42
+ "build": "npm run web:build && tsup",
43
43
  "dev": "tsup --watch",
44
44
  "serve": "node dist/cli/index.js serve",
45
+ "web:build": "vite build --config src/web/vite.config.ts",
46
+ "web:dev": "vite --config src/web/vite.config.ts",
45
47
  "lint": "eslint src/",
46
48
  "lint:fix": "eslint src/ --fix",
47
49
  "test": "vitest run --config vitest.config.ts",
@@ -59,17 +61,24 @@
59
61
  "cosmiconfig": "^9.0.0",
60
62
  "fastify": "^5.8.2",
61
63
  "glob": "^10.3.10",
64
+ "react": "^19.2.4",
65
+ "react-dom": "^19.2.4",
66
+ "three": "^0.183.2",
62
67
  "ts-morph": "^22.0.0"
63
68
  },
64
69
  "devDependencies": {
65
70
  "@eslint/js": "^10.0.1",
66
71
  "@types/node": "^20.11.0",
72
+ "@types/react": "^19.2.14",
73
+ "@types/react-dom": "^19.2.3",
67
74
  "@types/ws": "^8.18.1",
75
+ "@vitejs/plugin-react": "^4.3.4",
68
76
  "eslint": "^10.0.3",
69
77
  "globals": "^17.4.0",
70
78
  "tsup": "^8.0.0",
71
79
  "typescript": "^5.4.0",
72
80
  "typescript-eslint": "^8.57.0",
81
+ "vite": "^5.4.21",
73
82
  "vitest": "^1.6.0"
74
83
  },
75
84
  "peerDependencies": {