@archznn/crewloop-skills 0.3.0 → 0.4.1

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 (164) hide show
  1. package/package.json +16 -3
  2. package/packages/cli/README.md +55 -0
  3. package/packages/cli/bin/crewloop.js +6 -0
  4. package/packages/cli/dist/agents.d.ts +7 -0
  5. package/packages/cli/dist/agents.d.ts.map +1 -0
  6. package/packages/cli/dist/agents.js +31 -0
  7. package/packages/cli/dist/agents.js.map +1 -0
  8. package/packages/cli/dist/cli.d.ts +14 -0
  9. package/packages/cli/dist/cli.d.ts.map +1 -0
  10. package/packages/cli/dist/cli.js +255 -0
  11. package/packages/cli/dist/cli.js.map +1 -0
  12. package/packages/cli/dist/installer.d.ts +19 -0
  13. package/packages/cli/dist/installer.d.ts.map +1 -0
  14. package/packages/cli/dist/installer.js +89 -0
  15. package/packages/cli/dist/installer.js.map +1 -0
  16. package/packages/cli/dist/mcp.d.ts +20 -0
  17. package/packages/cli/dist/mcp.d.ts.map +1 -0
  18. package/packages/cli/dist/mcp.js +130 -0
  19. package/packages/cli/dist/mcp.js.map +1 -0
  20. package/packages/cli/dist/resolver.d.ts +7 -0
  21. package/packages/cli/dist/resolver.d.ts.map +1 -0
  22. package/packages/cli/dist/resolver.js +57 -0
  23. package/packages/cli/dist/resolver.js.map +1 -0
  24. package/packages/cli/dist/tests/agents.test.d.ts +2 -0
  25. package/packages/cli/dist/tests/agents.test.d.ts.map +1 -0
  26. package/packages/cli/dist/tests/agents.test.js +27 -0
  27. package/packages/cli/dist/tests/agents.test.js.map +1 -0
  28. package/packages/cli/dist/tests/cli.test.d.ts +2 -0
  29. package/packages/cli/dist/tests/cli.test.d.ts.map +1 -0
  30. package/packages/cli/dist/tests/cli.test.js +103 -0
  31. package/packages/cli/dist/tests/cli.test.js.map +1 -0
  32. package/packages/cli/dist/tests/installer.test.d.ts +2 -0
  33. package/packages/cli/dist/tests/installer.test.d.ts.map +1 -0
  34. package/packages/cli/dist/tests/installer.test.js +129 -0
  35. package/packages/cli/dist/tests/installer.test.js.map +1 -0
  36. package/packages/cli/dist/tests/mcp.test.d.ts +2 -0
  37. package/packages/cli/dist/tests/mcp.test.d.ts.map +1 -0
  38. package/packages/cli/dist/tests/mcp.test.js +153 -0
  39. package/packages/cli/dist/tests/mcp.test.js.map +1 -0
  40. package/packages/cli/dist/tests/resolver.test.d.ts +2 -0
  41. package/packages/cli/dist/tests/resolver.test.d.ts.map +1 -0
  42. package/packages/cli/dist/tests/resolver.test.js +41 -0
  43. package/packages/cli/dist/tests/resolver.test.js.map +1 -0
  44. package/servers/dashboard/README.md +87 -0
  45. package/servers/dashboard/bin/crewloop-dashboard.js +5 -0
  46. package/servers/dashboard/config-examples/codex-hooks.json +14 -0
  47. package/servers/dashboard/config-examples/kimi-code-config.toml +6 -0
  48. package/servers/dashboard/config-examples/opencode-plugin/crewloop-dashboard.js +64 -0
  49. package/servers/dashboard/dist/adapters/codex.d.ts +23 -0
  50. package/servers/dashboard/dist/adapters/codex.d.ts.map +1 -0
  51. package/servers/dashboard/dist/adapters/codex.js +28 -0
  52. package/servers/dashboard/dist/adapters/codex.js.map +1 -0
  53. package/servers/dashboard/dist/adapters/kimi.d.ts +13 -0
  54. package/servers/dashboard/dist/adapters/kimi.d.ts.map +1 -0
  55. package/servers/dashboard/dist/adapters/kimi.js +28 -0
  56. package/servers/dashboard/dist/adapters/kimi.js.map +1 -0
  57. package/servers/dashboard/dist/adapters/opencode.d.ts +9 -0
  58. package/servers/dashboard/dist/adapters/opencode.d.ts.map +1 -0
  59. package/servers/dashboard/dist/adapters/opencode.js +26 -0
  60. package/servers/dashboard/dist/adapters/opencode.js.map +1 -0
  61. package/servers/dashboard/dist/adapters/shim.d.ts +7 -0
  62. package/servers/dashboard/dist/adapters/shim.d.ts.map +1 -0
  63. package/servers/dashboard/dist/adapters/shim.js +107 -0
  64. package/servers/dashboard/dist/adapters/shim.js.map +1 -0
  65. package/servers/dashboard/dist/adapters/shim.test.d.ts +2 -0
  66. package/servers/dashboard/dist/adapters/shim.test.d.ts.map +1 -0
  67. package/servers/dashboard/dist/adapters/shim.test.js +72 -0
  68. package/servers/dashboard/dist/adapters/shim.test.js.map +1 -0
  69. package/servers/dashboard/dist/api/event.d.ts +13 -0
  70. package/servers/dashboard/dist/api/event.d.ts.map +1 -0
  71. package/servers/dashboard/dist/api/event.js +52 -0
  72. package/servers/dashboard/dist/api/event.js.map +1 -0
  73. package/servers/dashboard/dist/api/skills.d.ts +4 -0
  74. package/servers/dashboard/dist/api/skills.d.ts.map +1 -0
  75. package/servers/dashboard/dist/api/skills.js +12 -0
  76. package/servers/dashboard/dist/api/skills.js.map +1 -0
  77. package/servers/dashboard/dist/config.d.ts +11 -0
  78. package/servers/dashboard/dist/config.d.ts.map +1 -0
  79. package/servers/dashboard/dist/config.js +65 -0
  80. package/servers/dashboard/dist/config.js.map +1 -0
  81. package/servers/dashboard/dist/filters/sanitize.d.ts +14 -0
  82. package/servers/dashboard/dist/filters/sanitize.d.ts.map +1 -0
  83. package/servers/dashboard/dist/filters/sanitize.js +64 -0
  84. package/servers/dashboard/dist/filters/sanitize.js.map +1 -0
  85. package/servers/dashboard/dist/filters/sanitize.test.d.ts +2 -0
  86. package/servers/dashboard/dist/filters/sanitize.test.d.ts.map +1 -0
  87. package/servers/dashboard/dist/filters/sanitize.test.js +71 -0
  88. package/servers/dashboard/dist/filters/sanitize.test.js.map +1 -0
  89. package/servers/dashboard/dist/index.d.ts +2 -0
  90. package/servers/dashboard/dist/index.d.ts.map +1 -0
  91. package/servers/dashboard/dist/index.js +22 -0
  92. package/servers/dashboard/dist/index.js.map +1 -0
  93. package/servers/dashboard/dist/presenter.d.ts +7 -0
  94. package/servers/dashboard/dist/presenter.d.ts.map +1 -0
  95. package/servers/dashboard/dist/presenter.js +54 -0
  96. package/servers/dashboard/dist/presenter.js.map +1 -0
  97. package/servers/dashboard/dist/presenter.test.d.ts +2 -0
  98. package/servers/dashboard/dist/presenter.test.d.ts.map +1 -0
  99. package/servers/dashboard/dist/presenter.test.js +66 -0
  100. package/servers/dashboard/dist/presenter.test.js.map +1 -0
  101. package/servers/dashboard/dist/server.d.ts +13 -0
  102. package/servers/dashboard/dist/server.d.ts.map +1 -0
  103. package/servers/dashboard/dist/server.js +162 -0
  104. package/servers/dashboard/dist/server.js.map +1 -0
  105. package/servers/dashboard/dist/server.test.d.ts +2 -0
  106. package/servers/dashboard/dist/server.test.d.ts.map +1 -0
  107. package/servers/dashboard/dist/server.test.js +113 -0
  108. package/servers/dashboard/dist/server.test.js.map +1 -0
  109. package/servers/dashboard/dist/skills/infer.d.ts +8 -0
  110. package/servers/dashboard/dist/skills/infer.d.ts.map +1 -0
  111. package/servers/dashboard/dist/skills/infer.js +48 -0
  112. package/servers/dashboard/dist/skills/infer.js.map +1 -0
  113. package/servers/dashboard/dist/skills/infer.test.d.ts +2 -0
  114. package/servers/dashboard/dist/skills/infer.test.d.ts.map +1 -0
  115. package/servers/dashboard/dist/skills/infer.test.js +82 -0
  116. package/servers/dashboard/dist/skills/infer.test.js.map +1 -0
  117. package/servers/dashboard/dist/skills/mapping.d.ts +5 -0
  118. package/servers/dashboard/dist/skills/mapping.d.ts.map +1 -0
  119. package/servers/dashboard/dist/skills/mapping.js +28 -0
  120. package/servers/dashboard/dist/skills/mapping.js.map +1 -0
  121. package/servers/dashboard/dist/skills/registry.d.ts +11 -0
  122. package/servers/dashboard/dist/skills/registry.d.ts.map +1 -0
  123. package/servers/dashboard/dist/skills/registry.js +59 -0
  124. package/servers/dashboard/dist/skills/registry.js.map +1 -0
  125. package/servers/dashboard/dist/state.d.ts +18 -0
  126. package/servers/dashboard/dist/state.d.ts.map +1 -0
  127. package/servers/dashboard/dist/state.js +91 -0
  128. package/servers/dashboard/dist/state.js.map +1 -0
  129. package/servers/dashboard/dist/state.test.d.ts +2 -0
  130. package/servers/dashboard/dist/state.test.d.ts.map +1 -0
  131. package/servers/dashboard/dist/state.test.js +83 -0
  132. package/servers/dashboard/dist/state.test.js.map +1 -0
  133. package/servers/dashboard/dist/types.d.ts +86 -0
  134. package/servers/dashboard/dist/types.d.ts.map +1 -0
  135. package/servers/dashboard/dist/types.js +3 -0
  136. package/servers/dashboard/dist/types.js.map +1 -0
  137. package/servers/dashboard/package.json +46 -0
  138. package/servers/dashboard/public/app.js +447 -0
  139. package/servers/dashboard/public/index.html +96 -0
  140. package/servers/dashboard/public/styles.css +664 -0
  141. package/servers/dashboard/src/adapters/codex.ts +50 -0
  142. package/servers/dashboard/src/adapters/kimi.ts +40 -0
  143. package/servers/dashboard/src/adapters/opencode.ts +36 -0
  144. package/servers/dashboard/src/adapters/shim.test.ts +74 -0
  145. package/servers/dashboard/src/adapters/shim.ts +120 -0
  146. package/servers/dashboard/src/api/event.ts +70 -0
  147. package/servers/dashboard/src/api/skills.ts +11 -0
  148. package/servers/dashboard/src/config.ts +66 -0
  149. package/servers/dashboard/src/filters/sanitize.test.ts +94 -0
  150. package/servers/dashboard/src/filters/sanitize.ts +78 -0
  151. package/servers/dashboard/src/index.ts +24 -0
  152. package/servers/dashboard/src/presenter.test.ts +69 -0
  153. package/servers/dashboard/src/presenter.ts +56 -0
  154. package/servers/dashboard/src/server.test.ts +123 -0
  155. package/servers/dashboard/src/server.ts +191 -0
  156. package/servers/dashboard/src/skills/infer.test.ts +86 -0
  157. package/servers/dashboard/src/skills/infer.ts +53 -0
  158. package/servers/dashboard/src/skills/mapping.ts +26 -0
  159. package/servers/dashboard/src/skills/registry.ts +60 -0
  160. package/servers/dashboard/src/state.test.ts +88 -0
  161. package/servers/dashboard/src/state.ts +115 -0
  162. package/servers/dashboard/src/types.ts +110 -0
  163. package/servers/dashboard/tsconfig.json +19 -0
  164. package/skills/orchestrator/SKILL.md +1 -1
@@ -0,0 +1,664 @@
1
+ :root {
2
+ --bg-base: #09090b;
3
+ --bg-surface: #121214;
4
+ --bg-elevated: #1c1c1f;
5
+ --bg-inset: #050507;
6
+ --border-default: #27272a;
7
+ --border-strong: #3f3f46;
8
+ --text-primary: #f8fafc;
9
+ --text-secondary: #94a3b8;
10
+ --text-muted: #475569;
11
+ --accent: #22d3ee;
12
+ --accent-hover: #67e8f9;
13
+ --accent-dim: #0891b2;
14
+ --success: #4ade80;
15
+ --error: #fb7185;
16
+ --warning: #facc15;
17
+ --running: #38bdf8;
18
+
19
+ --font-display: 'Bebas Neue', 'Oswald', sans-serif;
20
+ --font-body: 'DM Sans', system-ui, sans-serif;
21
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
22
+ }
23
+
24
+ [data-theme="light"] {
25
+ --bg-base: #f8fafc;
26
+ --bg-surface: #ffffff;
27
+ --bg-elevated: #f1f5f9;
28
+ --bg-inset: #e2e8f0;
29
+ --border-default: #cbd5e1;
30
+ --border-strong: #94a3b8;
31
+ --text-primary: #0f172a;
32
+ --text-secondary: #475569;
33
+ --text-muted: #94a3b8;
34
+ --accent: #0891b2;
35
+ --accent-hover: #06b6d4;
36
+ --accent-dim: #155e75;
37
+ --success: #16a34a;
38
+ --error: #e11d48;
39
+ --warning: #ca8a04;
40
+ --running: #0284c7;
41
+ }
42
+
43
+ * {
44
+ box-sizing: border-box;
45
+ }
46
+
47
+ html, body {
48
+ margin: 0;
49
+ padding: 0;
50
+ height: 100%;
51
+ background: var(--bg-base);
52
+ color: var(--text-primary);
53
+ font-family: var(--font-body);
54
+ font-size: 14px;
55
+ line-height: 1.5;
56
+ }
57
+
58
+ .app {
59
+ display: flex;
60
+ flex-direction: column;
61
+ min-height: 100vh;
62
+ }
63
+
64
+ /* Header */
65
+ .header {
66
+ height: 56px;
67
+ background: var(--bg-surface);
68
+ border-bottom: 1px solid var(--border-default);
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: space-between;
72
+ padding: 0 24px;
73
+ flex-shrink: 0;
74
+ }
75
+
76
+ .brand {
77
+ display: flex;
78
+ align-items: baseline;
79
+ gap: 8px;
80
+ }
81
+
82
+ .brand-name {
83
+ font-family: var(--font-display);
84
+ font-size: 1.25rem;
85
+ letter-spacing: 0.12em;
86
+ color: var(--text-primary);
87
+ }
88
+
89
+ .brand-separator {
90
+ color: var(--text-muted);
91
+ }
92
+
93
+ .brand-label {
94
+ font-size: 0.75rem;
95
+ color: var(--text-muted);
96
+ letter-spacing: 0.08em;
97
+ }
98
+
99
+ .header-actions {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 12px;
103
+ }
104
+
105
+ .icon-button {
106
+ width: 36px;
107
+ height: 36px;
108
+ border-radius: 8px;
109
+ border: 1px solid var(--border-default);
110
+ background: var(--bg-elevated);
111
+ color: var(--text-secondary);
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ cursor: pointer;
116
+ transition: border-color 0.15s ease, color 0.15s ease;
117
+ }
118
+
119
+ .icon-button:hover {
120
+ border-color: var(--accent);
121
+ color: var(--accent);
122
+ }
123
+
124
+ .icon-button:focus-visible {
125
+ outline: 2px solid var(--accent);
126
+ outline-offset: 2px;
127
+ }
128
+
129
+ .icon-button i {
130
+ font-size: 1.1rem;
131
+ }
132
+
133
+ /* Session selector */
134
+ .session-selector {
135
+ position: relative;
136
+ }
137
+
138
+ .session-trigger {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 8px;
142
+ padding: 6px 12px;
143
+ border-radius: 999px;
144
+ border: 1px solid var(--border-default);
145
+ background: var(--bg-elevated);
146
+ color: var(--text-secondary);
147
+ font-family: var(--font-body);
148
+ font-size: 0.75rem;
149
+ cursor: pointer;
150
+ min-height: 36px;
151
+ transition: border-color 0.15s ease;
152
+ }
153
+
154
+ .session-trigger:hover,
155
+ .session-trigger[aria-expanded="true"] {
156
+ border-color: var(--accent);
157
+ }
158
+
159
+ .session-trigger:focus-visible {
160
+ outline: 2px solid var(--accent);
161
+ outline-offset: 2px;
162
+ }
163
+
164
+ .connection-dot {
165
+ width: 8px;
166
+ height: 8px;
167
+ border-radius: 50%;
168
+ background: var(--text-muted);
169
+ flex-shrink: 0;
170
+ }
171
+
172
+ .connection-dot.connected {
173
+ background: var(--success);
174
+ }
175
+
176
+ .connection-dot.connecting {
177
+ background: var(--warning);
178
+ }
179
+
180
+ .connection-dot.disconnected {
181
+ background: var(--error);
182
+ }
183
+
184
+ .session-list {
185
+ position: absolute;
186
+ top: calc(100% + 8px);
187
+ right: 0;
188
+ min-width: 240px;
189
+ max-height: 320px;
190
+ overflow-y: auto;
191
+ background: var(--bg-surface);
192
+ border: 1px solid var(--border-default);
193
+ border-radius: 8px;
194
+ list-style: none;
195
+ margin: 0;
196
+ padding: 6px;
197
+ display: none;
198
+ z-index: 100;
199
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
200
+ }
201
+
202
+ .session-list.open {
203
+ display: block;
204
+ }
205
+
206
+ .session-item {
207
+ display: flex;
208
+ align-items: center;
209
+ gap: 8px;
210
+ padding: 8px 10px;
211
+ border-radius: 6px;
212
+ cursor: pointer;
213
+ color: var(--text-secondary);
214
+ font-size: 0.75rem;
215
+ border-left: 2px solid transparent;
216
+ }
217
+
218
+ .session-item:hover,
219
+ .session-item:focus-visible {
220
+ background: var(--bg-elevated);
221
+ outline: none;
222
+ }
223
+
224
+ .session-item.active {
225
+ border-left-color: var(--accent);
226
+ color: var(--text-primary);
227
+ background: var(--bg-elevated);
228
+ }
229
+
230
+ .session-item-id {
231
+ font-family: var(--font-mono);
232
+ }
233
+
234
+ .session-item-source {
235
+ margin-left: auto;
236
+ color: var(--text-muted);
237
+ text-transform: uppercase;
238
+ }
239
+
240
+ /* Main layout */
241
+ .main {
242
+ display: flex;
243
+ flex: 1;
244
+ gap: 16px;
245
+ padding: 24px;
246
+ overflow: hidden;
247
+ }
248
+
249
+ .sidebar {
250
+ width: 320px;
251
+ display: flex;
252
+ flex-direction: column;
253
+ gap: 16px;
254
+ flex-shrink: 0;
255
+ }
256
+
257
+ .content {
258
+ flex: 1;
259
+ display: flex;
260
+ flex-direction: column;
261
+ gap: 16px;
262
+ min-width: 0;
263
+ }
264
+
265
+ /* Panels */
266
+ .panel {
267
+ background: var(--bg-surface);
268
+ border: 1px solid var(--border-default);
269
+ border-radius: 8px;
270
+ overflow: hidden;
271
+ position: relative;
272
+ }
273
+
274
+ .panel-title {
275
+ font-size: 0.75rem;
276
+ font-weight: 600;
277
+ text-transform: uppercase;
278
+ letter-spacing: 0.08em;
279
+ color: var(--text-muted);
280
+ margin: 0;
281
+ padding: 16px 20px;
282
+ border-bottom: 1px solid var(--border-default);
283
+ }
284
+
285
+ /* Active skill */
286
+ .active-skill-panel {
287
+ padding: 24px;
288
+ }
289
+
290
+ .panel-accent-strip {
291
+ position: absolute;
292
+ top: 0;
293
+ left: 0;
294
+ right: 0;
295
+ height: 4px;
296
+ background: var(--text-muted);
297
+ transition: background 0.2s ease;
298
+ }
299
+
300
+ .panel-accent-strip.running {
301
+ background: var(--accent);
302
+ box-shadow: 0 0 16px var(--accent-dim);
303
+ }
304
+
305
+ .active-skill-content {
306
+ display: flex;
307
+ flex-direction: column;
308
+ align-items: flex-start;
309
+ gap: 16px;
310
+ }
311
+
312
+ .active-skill-icon-wrap {
313
+ width: 64px;
314
+ height: 64px;
315
+ border-radius: 12px;
316
+ background: var(--bg-elevated);
317
+ border: 1px solid var(--border-default);
318
+ display: flex;
319
+ align-items: center;
320
+ justify-content: center;
321
+ color: var(--accent);
322
+ }
323
+
324
+ .active-skill-icon-wrap i {
325
+ font-size: 2rem;
326
+ }
327
+
328
+ .active-skill-name {
329
+ font-family: var(--font-display);
330
+ font-size: 4rem;
331
+ font-weight: 400;
332
+ line-height: 0.95;
333
+ margin: 0;
334
+ color: var(--text-primary);
335
+ }
336
+
337
+ .active-skill-meta {
338
+ display: flex;
339
+ gap: 8px;
340
+ flex-wrap: wrap;
341
+ }
342
+
343
+ .status-badge,
344
+ .confidence-badge {
345
+ display: inline-flex;
346
+ align-items: center;
347
+ gap: 6px;
348
+ padding: 4px 10px;
349
+ border-radius: 999px;
350
+ font-size: 0.75rem;
351
+ font-weight: 500;
352
+ text-transform: uppercase;
353
+ letter-spacing: 0.04em;
354
+ background: var(--bg-elevated);
355
+ border: 1px solid var(--border-default);
356
+ color: var(--text-secondary);
357
+ }
358
+
359
+ .status-dot {
360
+ width: 8px;
361
+ height: 8px;
362
+ border-radius: 50%;
363
+ background: var(--text-muted);
364
+ }
365
+
366
+ .status-dot.running {
367
+ background: var(--running);
368
+ }
369
+
370
+ .status-dot.error {
371
+ background: var(--error);
372
+ }
373
+
374
+ .status-dot.success {
375
+ background: var(--success);
376
+ }
377
+
378
+ .active-skill-source {
379
+ display: flex;
380
+ align-items: center;
381
+ gap: 8px;
382
+ color: var(--text-muted);
383
+ font-size: 0.75rem;
384
+ text-transform: uppercase;
385
+ letter-spacing: 0.04em;
386
+ }
387
+
388
+ /* Telemetry */
389
+ .telemetry-panel {
390
+ padding: 20px;
391
+ }
392
+
393
+ .telemetry-panel .panel-title {
394
+ padding: 0 0 16px;
395
+ border-bottom: 1px solid var(--border-default);
396
+ }
397
+
398
+ .telemetry-grid {
399
+ display: grid;
400
+ grid-template-columns: 1fr;
401
+ gap: 16px;
402
+ padding-top: 16px;
403
+ }
404
+
405
+ .telemetry-card {
406
+ display: flex;
407
+ flex-direction: column;
408
+ gap: 4px;
409
+ padding: 12px;
410
+ background: var(--bg-inset);
411
+ border-radius: 6px;
412
+ border: 1px solid var(--border-default);
413
+ }
414
+
415
+ .telemetry-value {
416
+ font-family: var(--font-mono);
417
+ font-size: 2rem;
418
+ font-weight: 500;
419
+ color: var(--accent);
420
+ font-variant-numeric: tabular-nums;
421
+ }
422
+
423
+ .telemetry-label {
424
+ font-size: 0.75rem;
425
+ color: var(--text-muted);
426
+ letter-spacing: 0.08em;
427
+ }
428
+
429
+ /* Activity graph */
430
+ .activity-panel {
431
+ flex: 0 0 220px;
432
+ display: flex;
433
+ flex-direction: column;
434
+ }
435
+
436
+ .activity-graph {
437
+ flex: 1;
438
+ min-height: 140px;
439
+ padding: 16px 20px;
440
+ position: relative;
441
+ }
442
+
443
+ .activity-empty {
444
+ position: absolute;
445
+ inset: 0;
446
+ display: flex;
447
+ align-items: center;
448
+ justify-content: center;
449
+ color: var(--text-muted);
450
+ font-size: 0.875rem;
451
+ }
452
+
453
+ .activity-canvas {
454
+ width: 100%;
455
+ height: 100%;
456
+ }
457
+
458
+ /* Timeline */
459
+ .timeline-panel {
460
+ flex: 1;
461
+ display: flex;
462
+ flex-direction: column;
463
+ min-height: 0;
464
+ }
465
+
466
+ .timeline {
467
+ flex: 1;
468
+ overflow-y: auto;
469
+ list-style: none;
470
+ margin: 0;
471
+ padding: 12px 20px;
472
+ position: relative;
473
+ }
474
+
475
+ .timeline::before {
476
+ content: '';
477
+ position: absolute;
478
+ top: 12px;
479
+ bottom: 12px;
480
+ left: 32px;
481
+ width: 1px;
482
+ background: var(--border-default);
483
+ }
484
+
485
+ .timeline-item {
486
+ display: grid;
487
+ grid-template-columns: 56px 16px 1fr auto;
488
+ align-items: center;
489
+ gap: 12px;
490
+ padding: 8px 0;
491
+ position: relative;
492
+ animation: slideIn 0.2s ease-out;
493
+ }
494
+
495
+ .timeline-time {
496
+ font-family: var(--font-mono);
497
+ font-size: 0.75rem;
498
+ color: var(--text-muted);
499
+ text-align: right;
500
+ font-variant-numeric: tabular-nums;
501
+ }
502
+
503
+ .timeline-dot {
504
+ width: 8px;
505
+ height: 8px;
506
+ border-radius: 50%;
507
+ background: var(--text-muted);
508
+ z-index: 1;
509
+ justify-self: center;
510
+ }
511
+
512
+ .timeline-dot.running {
513
+ background: var(--running);
514
+ }
515
+
516
+ .timeline-dot.success {
517
+ background: var(--success);
518
+ }
519
+
520
+ .timeline-dot.error {
521
+ background: var(--error);
522
+ }
523
+
524
+ .timeline-main {
525
+ display: flex;
526
+ align-items: baseline;
527
+ gap: 10px;
528
+ min-width: 0;
529
+ }
530
+
531
+ .timeline-tool {
532
+ font-family: var(--font-mono);
533
+ font-size: 0.875rem;
534
+ font-weight: 500;
535
+ color: var(--text-primary);
536
+ flex-shrink: 0;
537
+ }
538
+
539
+ .timeline-detail {
540
+ font-size: 0.875rem;
541
+ color: var(--text-secondary);
542
+ white-space: nowrap;
543
+ overflow: hidden;
544
+ text-overflow: ellipsis;
545
+ }
546
+
547
+ .timeline-outcome {
548
+ color: var(--text-muted);
549
+ font-size: 0.875rem;
550
+ }
551
+
552
+ /* Animations */
553
+ @keyframes slideIn {
554
+ from {
555
+ opacity: 0;
556
+ transform: translateX(16px);
557
+ }
558
+ to {
559
+ opacity: 1;
560
+ transform: translateX(0);
561
+ }
562
+ }
563
+
564
+ @keyframes pulse {
565
+ 0%, 100% {
566
+ opacity: 1;
567
+ transform: scale(1);
568
+ }
569
+ 50% {
570
+ opacity: 0.4;
571
+ transform: scale(1.2);
572
+ }
573
+ }
574
+
575
+ .status-dot.running {
576
+ animation: pulse 1.2s ease-in-out infinite;
577
+ }
578
+
579
+ .panel-accent-strip.running {
580
+ animation: glow 2s ease-in-out infinite;
581
+ }
582
+
583
+ @keyframes glow {
584
+ 0%, 100% {
585
+ box-shadow: 0 0 0 transparent;
586
+ }
587
+ 50% {
588
+ box-shadow: 0 0 16px var(--accent-dim);
589
+ }
590
+ }
591
+
592
+ /* Reduced motion */
593
+ @media (prefers-reduced-motion: reduce) {
594
+ *,
595
+ *::before,
596
+ *::after {
597
+ animation-duration: 0.01ms !important;
598
+ animation-iteration-count: 1 !important;
599
+ transition-duration: 0.01ms !important;
600
+ }
601
+
602
+ .timeline-item {
603
+ animation: none;
604
+ }
605
+ }
606
+
607
+ /* Responsive */
608
+ @media (max-width: 1023px) {
609
+ .main {
610
+ flex-direction: column;
611
+ overflow: auto;
612
+ }
613
+
614
+ .sidebar {
615
+ width: 100%;
616
+ flex-direction: row;
617
+ }
618
+
619
+ .active-skill-panel {
620
+ flex: 1;
621
+ }
622
+
623
+ .telemetry-panel {
624
+ flex: 1;
625
+ }
626
+
627
+ .telemetry-grid {
628
+ grid-template-columns: repeat(3, 1fr);
629
+ }
630
+
631
+ .active-skill-name {
632
+ font-size: 3rem;
633
+ }
634
+ }
635
+
636
+ @media (max-width: 767px) {
637
+ .header {
638
+ padding: 0 16px;
639
+ }
640
+
641
+ .main {
642
+ padding: 16px;
643
+ }
644
+
645
+ .sidebar {
646
+ flex-direction: column;
647
+ }
648
+
649
+ .active-skill-name {
650
+ font-size: 2.5rem;
651
+ }
652
+
653
+ .telemetry-grid {
654
+ grid-template-columns: 1fr;
655
+ }
656
+
657
+ .timeline::before {
658
+ left: 28px;
659
+ }
660
+
661
+ .timeline-item {
662
+ grid-template-columns: 48px 16px 1fr auto;
663
+ }
664
+ }
@@ -0,0 +1,50 @@
1
+ import type { AgentSource, DashboardEvent, EventType } from '../types';
2
+
3
+ export interface CodexHookPayload {
4
+ sessionId?: string;
5
+ session_id?: string;
6
+ turnId?: string;
7
+ cwd?: string;
8
+ transcriptPath?: string;
9
+ model?: string;
10
+ permissionMode?: string;
11
+ callId?: string;
12
+ toolName?: string;
13
+ toolKind?: string;
14
+ toolInput?: Record<string, unknown>;
15
+ toolResponse?: Record<string, unknown>;
16
+ hook_event_name?: string;
17
+ stop_reason?: string;
18
+ usage?: unknown;
19
+ executed?: boolean;
20
+ success?: boolean;
21
+ durationMs?: number;
22
+ }
23
+
24
+ const EVENT_MAP: Record<string, EventType> = {
25
+ PreToolUse: 'tool_start',
26
+ PostToolUse: 'tool_end',
27
+ SessionStart: 'session_start',
28
+ Stop: 'session_end',
29
+ };
30
+
31
+ export function normalizeCodex(payload: CodexHookPayload): DashboardEvent | undefined {
32
+ const eventName = payload.hook_event_name || 'PostToolUse';
33
+ const event_type = EVENT_MAP[eventName];
34
+ if (!event_type) {
35
+ return undefined;
36
+ }
37
+
38
+ return {
39
+ id: generateId(),
40
+ timestamp: Date.now(),
41
+ source: 'codex' as AgentSource,
42
+ session_id: payload.sessionId || payload.session_id || 'unknown',
43
+ event_type,
44
+ tool: payload.toolName,
45
+ };
46
+ }
47
+
48
+ function generateId(): string {
49
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
50
+ }