@virtengine/openfleet 0.25.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 (120) hide show
  1. package/.env.example +914 -0
  2. package/LICENSE +190 -0
  3. package/README.md +500 -0
  4. package/agent-endpoint.mjs +918 -0
  5. package/agent-hook-bridge.mjs +230 -0
  6. package/agent-hooks.mjs +1188 -0
  7. package/agent-pool.mjs +2403 -0
  8. package/agent-prompts.mjs +689 -0
  9. package/agent-sdk.mjs +141 -0
  10. package/anomaly-detector.mjs +1195 -0
  11. package/autofix.mjs +1294 -0
  12. package/claude-shell.mjs +708 -0
  13. package/cli.mjs +906 -0
  14. package/codex-config.mjs +1274 -0
  15. package/codex-model-profiles.mjs +135 -0
  16. package/codex-shell.mjs +762 -0
  17. package/config-doctor.mjs +613 -0
  18. package/config.mjs +1720 -0
  19. package/conflict-resolver.mjs +248 -0
  20. package/container-runner.mjs +450 -0
  21. package/copilot-shell.mjs +827 -0
  22. package/daemon-restart-policy.mjs +56 -0
  23. package/diff-stats.mjs +282 -0
  24. package/error-detector.mjs +829 -0
  25. package/fetch-runtime.mjs +34 -0
  26. package/fleet-coordinator.mjs +838 -0
  27. package/get-telegram-chat-id.mjs +71 -0
  28. package/git-safety.mjs +170 -0
  29. package/github-reconciler.mjs +403 -0
  30. package/hook-profiles.mjs +651 -0
  31. package/kanban-adapter.mjs +4491 -0
  32. package/lib/logger.mjs +645 -0
  33. package/maintenance.mjs +828 -0
  34. package/merge-strategy.mjs +1171 -0
  35. package/monitor.mjs +12207 -0
  36. package/openfleet.config.example.json +115 -0
  37. package/openfleet.schema.json +465 -0
  38. package/package.json +203 -0
  39. package/postinstall.mjs +187 -0
  40. package/pr-cleanup-daemon.mjs +978 -0
  41. package/preflight.mjs +408 -0
  42. package/prepublish-check.mjs +90 -0
  43. package/presence.mjs +328 -0
  44. package/primary-agent.mjs +282 -0
  45. package/publish.mjs +151 -0
  46. package/repo-root.mjs +29 -0
  47. package/restart-controller.mjs +100 -0
  48. package/review-agent.mjs +557 -0
  49. package/rotate-agent-logs.sh +133 -0
  50. package/sdk-conflict-resolver.mjs +973 -0
  51. package/session-tracker.mjs +880 -0
  52. package/setup.mjs +3937 -0
  53. package/shared-knowledge.mjs +410 -0
  54. package/shared-state-manager.mjs +841 -0
  55. package/shared-workspace-cli.mjs +199 -0
  56. package/shared-workspace-registry.mjs +537 -0
  57. package/shared-workspaces.json +18 -0
  58. package/startup-service.mjs +1070 -0
  59. package/sync-engine.mjs +1063 -0
  60. package/task-archiver.mjs +801 -0
  61. package/task-assessment.mjs +550 -0
  62. package/task-claims.mjs +924 -0
  63. package/task-complexity.mjs +581 -0
  64. package/task-executor.mjs +5111 -0
  65. package/task-store.mjs +753 -0
  66. package/telegram-bot.mjs +9281 -0
  67. package/telegram-sentinel.mjs +2010 -0
  68. package/ui/app.js +867 -0
  69. package/ui/app.legacy.js +1464 -0
  70. package/ui/app.monolith.js +2488 -0
  71. package/ui/components/charts.js +226 -0
  72. package/ui/components/chat-view.js +567 -0
  73. package/ui/components/command-palette.js +587 -0
  74. package/ui/components/diff-viewer.js +190 -0
  75. package/ui/components/forms.js +327 -0
  76. package/ui/components/kanban-board.js +451 -0
  77. package/ui/components/session-list.js +305 -0
  78. package/ui/components/shared.js +473 -0
  79. package/ui/index.html +70 -0
  80. package/ui/modules/api.js +297 -0
  81. package/ui/modules/icons.js +461 -0
  82. package/ui/modules/router.js +81 -0
  83. package/ui/modules/settings-schema.js +261 -0
  84. package/ui/modules/state.js +679 -0
  85. package/ui/modules/telegram.js +331 -0
  86. package/ui/modules/utils.js +270 -0
  87. package/ui/styles/animations.css +140 -0
  88. package/ui/styles/base.css +98 -0
  89. package/ui/styles/components.css +1915 -0
  90. package/ui/styles/kanban.css +286 -0
  91. package/ui/styles/layout.css +809 -0
  92. package/ui/styles/sessions.css +827 -0
  93. package/ui/styles/variables.css +188 -0
  94. package/ui/styles.css +141 -0
  95. package/ui/styles.monolith.css +1046 -0
  96. package/ui/tabs/agents.js +1417 -0
  97. package/ui/tabs/chat.js +74 -0
  98. package/ui/tabs/control.js +887 -0
  99. package/ui/tabs/dashboard.js +515 -0
  100. package/ui/tabs/infra.js +537 -0
  101. package/ui/tabs/logs.js +783 -0
  102. package/ui/tabs/settings.js +1487 -0
  103. package/ui/tabs/tasks.js +1385 -0
  104. package/ui-server.mjs +4073 -0
  105. package/update-check.mjs +465 -0
  106. package/utils.mjs +172 -0
  107. package/ve-kanban.mjs +654 -0
  108. package/ve-kanban.ps1 +1365 -0
  109. package/ve-kanban.sh +18 -0
  110. package/ve-orchestrator.mjs +340 -0
  111. package/ve-orchestrator.ps1 +6546 -0
  112. package/ve-orchestrator.sh +18 -0
  113. package/vibe-kanban-wrapper.mjs +41 -0
  114. package/vk-error-resolver.mjs +470 -0
  115. package/vk-log-stream.mjs +914 -0
  116. package/whatsapp-channel.mjs +520 -0
  117. package/workspace-monitor.mjs +581 -0
  118. package/workspace-reaper.mjs +405 -0
  119. package/workspace-registry.mjs +238 -0
  120. package/worktree-manager.mjs +1266 -0
@@ -0,0 +1,827 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ * Sessions — Session List, Chat View, Diff Viewer styles
3
+ * ────────────────────────────────────────────────────────────── */
4
+
5
+ /* ═══ Session Layout ═══ */
6
+ .session-panel {
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: var(--space-md);
10
+ }
11
+
12
+ @media (min-width: 769px) {
13
+ .session-split {
14
+ display: grid;
15
+ grid-template-columns: 280px 1fr;
16
+ gap: var(--space-md);
17
+ min-height: 500px;
18
+ }
19
+ }
20
+
21
+ @media (max-width: 768px) {
22
+ .session-split {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: var(--space-md);
26
+ }
27
+ .session-list {
28
+ max-height: 300px;
29
+ }
30
+ }
31
+
32
+ /* ─── Detail tabs ─── */
33
+ .session-detail-tabs {
34
+ display: flex;
35
+ gap: 2px;
36
+ background: var(--glass-bg);
37
+ border: 1px solid var(--glass-border);
38
+ border-radius: var(--radius-md);
39
+ padding: 3px;
40
+ margin-bottom: var(--space-md);
41
+ }
42
+
43
+ .session-detail-tab {
44
+ flex: 1;
45
+ padding: 8px 12px;
46
+ border: none;
47
+ background: transparent;
48
+ color: var(--text-secondary);
49
+ font-size: 13px;
50
+ font-weight: 500;
51
+ cursor: pointer;
52
+ border-radius: var(--radius-sm);
53
+ transition: all var(--transition-fast);
54
+ font-family: inherit;
55
+ }
56
+
57
+ .session-detail-tab:hover {
58
+ color: var(--text-primary);
59
+ background: var(--glass-highlight);
60
+ }
61
+
62
+ .session-detail-tab.active {
63
+ background: var(--gradient-accent);
64
+ color: var(--accent-text);
65
+ box-shadow: var(--shadow-glow-sm);
66
+ }
67
+
68
+ /* Back button (mobile) */
69
+ .session-back-btn {
70
+ display: none;
71
+ align-items: center;
72
+ gap: 4px;
73
+ background: none;
74
+ border: none;
75
+ color: var(--accent);
76
+ font-size: 14px;
77
+ cursor: pointer;
78
+ padding: 6px 0;
79
+ margin-bottom: var(--space-sm);
80
+ font-family: inherit;
81
+ }
82
+
83
+ @media (max-width: 768px) {
84
+ .session-back-btn {
85
+ display: inline-flex;
86
+ }
87
+ }
88
+
89
+ /* ═══ Session List ═══ */
90
+ .session-list {
91
+ background: var(--glass-bg);
92
+ backdrop-filter: var(--glass-blur);
93
+ -webkit-backdrop-filter: var(--glass-blur);
94
+ border: 1px solid var(--glass-border);
95
+ border-radius: var(--radius-lg);
96
+ display: flex;
97
+ flex-direction: column;
98
+ overflow: hidden;
99
+ }
100
+
101
+ .session-list-header {
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: space-between;
105
+ padding: 12px 14px;
106
+ border-bottom: 1px solid var(--glass-border);
107
+ }
108
+
109
+ .session-list-title {
110
+ font-size: 15px;
111
+ font-weight: 600;
112
+ color: var(--text-primary);
113
+ }
114
+
115
+ .session-search {
116
+ padding: 8px 10px;
117
+ border-bottom: 1px solid var(--border);
118
+ }
119
+
120
+ .session-search-input {
121
+ width: 100%;
122
+ font-size: 13px;
123
+ padding: 6px 10px;
124
+ box-sizing: border-box;
125
+ }
126
+
127
+ .session-list-scroll {
128
+ overflow-y: auto;
129
+ flex: 1;
130
+ max-height: 460px;
131
+ }
132
+
133
+ .session-group-label {
134
+ font-size: 11px;
135
+ font-weight: 600;
136
+ text-transform: uppercase;
137
+ letter-spacing: 0.5px;
138
+ color: var(--text-hint);
139
+ padding: 10px 14px 4px;
140
+ }
141
+
142
+ .session-item {
143
+ padding: 12px 14px;
144
+ cursor: pointer;
145
+ border-bottom: 1px solid var(--border);
146
+ transition: background var(--transition-fast);
147
+ }
148
+
149
+ .session-item:hover {
150
+ background: var(--bg-card-hover);
151
+ }
152
+
153
+ .session-item.active {
154
+ background: var(--accent-subtle);
155
+ border-left: 3px solid var(--accent);
156
+ padding-left: 11px;
157
+ }
158
+
159
+ .session-item-row {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 6px;
163
+ }
164
+
165
+ .session-item-icon {
166
+ font-size: 14px;
167
+ flex-shrink: 0;
168
+ }
169
+
170
+ .session-item-title {
171
+ flex: 1;
172
+ font-size: 13px;
173
+ font-weight: 500;
174
+ color: var(--text-primary);
175
+ line-height: 1.4;
176
+ white-space: nowrap;
177
+ overflow: hidden;
178
+ text-overflow: ellipsis;
179
+ }
180
+
181
+ .session-item-status {
182
+ font-size: 12px;
183
+ flex-shrink: 0;
184
+ }
185
+
186
+ .session-item-preview {
187
+ font-size: 12px;
188
+ color: var(--text-secondary);
189
+ margin-top: 3px;
190
+ line-height: 1.4;
191
+ white-space: nowrap;
192
+ overflow: hidden;
193
+ text-overflow: ellipsis;
194
+ }
195
+
196
+ .session-item-time {
197
+ font-size: 11px;
198
+ color: var(--text-hint);
199
+ margin-top: 2px;
200
+ line-height: 1.3;
201
+ }
202
+
203
+ .session-empty {
204
+ display: flex;
205
+ flex-direction: column;
206
+ align-items: center;
207
+ justify-content: center;
208
+ padding: var(--space-lg);
209
+ gap: var(--space-sm);
210
+ }
211
+
212
+ .session-empty-icon {
213
+ font-size: 32px;
214
+ opacity: 0.6;
215
+ }
216
+
217
+ .session-empty-text {
218
+ font-size: 13px;
219
+ color: var(--text-secondary);
220
+ text-align: center;
221
+ }
222
+
223
+ .session-empty-subtext {
224
+ font-size: 11px;
225
+ color: var(--text-hint);
226
+ margin-top: 4px;
227
+ }
228
+
229
+ .session-empty-actions {
230
+ display: flex;
231
+ align-items: center;
232
+ gap: 8px;
233
+ flex-wrap: wrap;
234
+ justify-content: center;
235
+ margin-top: 4px;
236
+ }
237
+
238
+ /* ═══ Chat View ═══ */
239
+ .chat-view {
240
+ display: flex;
241
+ flex-direction: column;
242
+ background: var(--glass-bg);
243
+ backdrop-filter: var(--glass-blur);
244
+ -webkit-backdrop-filter: var(--glass-blur);
245
+ border: 1px solid var(--glass-border);
246
+ border-radius: var(--radius-lg);
247
+ min-height: 400px;
248
+ max-height: 600px;
249
+ overflow: hidden;
250
+ }
251
+
252
+ @media (min-width: 1024px) {
253
+ .chat-view {
254
+ max-height: none;
255
+ min-height: 560px;
256
+ }
257
+ }
258
+
259
+ .chat-view.chat-empty-state {
260
+ align-items: center;
261
+ justify-content: center;
262
+ }
263
+
264
+ .chat-header {
265
+ padding: 12px 16px;
266
+ border-bottom: 1px solid var(--glass-border);
267
+ flex-shrink: 0;
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: space-between;
271
+ gap: 12px;
272
+ }
273
+
274
+ .chat-toolbar {
275
+ display: flex;
276
+ flex-wrap: wrap;
277
+ align-items: center;
278
+ justify-content: space-between;
279
+ gap: 10px;
280
+ padding: 10px 16px;
281
+ border-bottom: 1px solid var(--glass-border);
282
+ background: rgba(8, 14, 24, 0.3);
283
+ }
284
+
285
+ .chat-toolbar-left {
286
+ display: flex;
287
+ flex-wrap: wrap;
288
+ align-items: center;
289
+ gap: 10px;
290
+ }
291
+
292
+ .chat-toolbar-actions {
293
+ display: flex;
294
+ flex-wrap: wrap;
295
+ align-items: center;
296
+ gap: 6px;
297
+ }
298
+
299
+ .chat-filter-group {
300
+ display: flex;
301
+ flex-wrap: wrap;
302
+ gap: 6px;
303
+ }
304
+
305
+ .chat-filter-chip {
306
+ border: 1px solid var(--glass-border);
307
+ background: var(--glass-bg);
308
+ color: var(--text-secondary);
309
+ font-size: 11px;
310
+ padding: 4px 10px;
311
+ border-radius: 999px;
312
+ display: inline-flex;
313
+ align-items: center;
314
+ gap: 6px;
315
+ cursor: pointer;
316
+ transition: all var(--transition-fast);
317
+ }
318
+
319
+ .chat-filter-chip:hover {
320
+ color: var(--text-primary);
321
+ border-color: rgba(148, 163, 184, 0.4);
322
+ }
323
+
324
+ .chat-filter-chip.active {
325
+ color: var(--text-primary);
326
+ border-color: var(--accent);
327
+ background: rgba(59, 130, 246, 0.12);
328
+ }
329
+
330
+ .chat-filter-count {
331
+ font-size: 10px;
332
+ padding: 1px 6px;
333
+ border-radius: 999px;
334
+ background: rgba(148, 163, 184, 0.15);
335
+ color: var(--text-hint);
336
+ }
337
+
338
+ .chat-paused-pill {
339
+ font-size: 11px;
340
+ padding: 3px 8px;
341
+ border-radius: 999px;
342
+ border: 1px solid rgba(248, 113, 113, 0.4);
343
+ color: var(--color-error);
344
+ background: rgba(248, 113, 113, 0.12);
345
+ }
346
+
347
+ .chat-header-info {
348
+ display: flex;
349
+ flex-direction: column;
350
+ gap: 2px;
351
+ }
352
+
353
+ .chat-header-actions {
354
+ display: flex;
355
+ align-items: center;
356
+ gap: 6px;
357
+ flex-shrink: 0;
358
+ }
359
+
360
+ .chat-header-title {
361
+ font-size: 14px;
362
+ font-weight: 600;
363
+ color: var(--text-primary);
364
+ }
365
+
366
+ .chat-header-meta {
367
+ font-size: 12px;
368
+ color: var(--text-hint);
369
+ margin-top: 2px;
370
+ line-height: 1.4;
371
+ }
372
+
373
+ .chat-messages {
374
+ flex: 1;
375
+ overflow-y: auto;
376
+ padding: var(--space-md);
377
+ display: flex;
378
+ flex-direction: column;
379
+ gap: var(--space-sm);
380
+ }
381
+
382
+ .chat-empty-state-inline {
383
+ display: flex;
384
+ flex-direction: column;
385
+ align-items: center;
386
+ justify-content: center;
387
+ padding: var(--space-lg);
388
+ gap: var(--space-sm);
389
+ border: 1px dashed var(--glass-border);
390
+ border-radius: var(--radius-md);
391
+ background: rgba(8, 12, 20, 0.35);
392
+ text-align: center;
393
+ }
394
+
395
+ .chat-loading {
396
+ text-align: center;
397
+ color: var(--text-hint);
398
+ padding: var(--space-lg);
399
+ font-size: 13px;
400
+ }
401
+
402
+ /* ─── Bubbles ─── */
403
+ .chat-bubble {
404
+ max-width: 85%;
405
+ padding: 10px 14px;
406
+ border-radius: var(--radius-md);
407
+ font-size: 13px;
408
+ line-height: 1.5;
409
+ word-wrap: break-word;
410
+ }
411
+
412
+ .chat-bubble.user {
413
+ align-self: flex-end;
414
+ background: var(--gradient-accent);
415
+ color: var(--accent-text);
416
+ border-bottom-right-radius: var(--radius-sm);
417
+ box-shadow: var(--shadow-glow-sm);
418
+ }
419
+
420
+ .chat-bubble.assistant {
421
+ align-self: flex-start;
422
+ background: var(--glass-bg);
423
+ backdrop-filter: blur(8px);
424
+ -webkit-backdrop-filter: blur(8px);
425
+ color: var(--text-primary);
426
+ border: 1px solid var(--glass-border);
427
+ border-bottom-left-radius: var(--radius-sm);
428
+ }
429
+
430
+ .chat-bubble.system {
431
+ align-self: center;
432
+ max-width: 90%;
433
+ background: transparent;
434
+ padding: 6px 12px;
435
+ }
436
+
437
+ .chat-bubble.tool {
438
+ align-self: flex-start;
439
+ background: rgba(56, 189, 248, 0.08);
440
+ border: 1px dashed rgba(56, 189, 248, 0.3);
441
+ color: var(--text-primary);
442
+ font-family: var(--font-mono);
443
+ }
444
+
445
+ .chat-bubble.error {
446
+ align-self: flex-start;
447
+ background: rgba(248, 113, 113, 0.12);
448
+ border: 1px solid rgba(248, 113, 113, 0.4);
449
+ color: var(--text-primary);
450
+ }
451
+
452
+ .chat-system-text {
453
+ font-size: 12px;
454
+ color: var(--text-hint);
455
+ text-align: center;
456
+ font-style: italic;
457
+ }
458
+
459
+ .chat-bubble-label {
460
+ font-size: 10px;
461
+ font-weight: 600;
462
+ text-transform: uppercase;
463
+ letter-spacing: 0.4px;
464
+ color: var(--text-hint);
465
+ margin-bottom: 4px;
466
+ }
467
+
468
+ .chat-bubble-content {
469
+ white-space: pre-wrap;
470
+ }
471
+
472
+ .chat-bubble-time {
473
+ font-size: 10px;
474
+ opacity: 0.6;
475
+ margin-top: 4px;
476
+ }
477
+
478
+ /* ─── Code blocks ─── */
479
+ .chat-code-block {
480
+ position: relative;
481
+ background: #1e1e2e;
482
+ border-radius: var(--radius-sm);
483
+ margin: 6px 0;
484
+ overflow: hidden;
485
+ }
486
+
487
+ .chat-code-block pre {
488
+ margin: 0;
489
+ padding: 10px 12px;
490
+ overflow-x: auto;
491
+ font-size: 12px;
492
+ line-height: 1.5;
493
+ }
494
+
495
+ .chat-code-block code {
496
+ font-family: var(--font-mono);
497
+ color: #e2e8f0;
498
+ }
499
+
500
+ .chat-code-copy {
501
+ position: absolute;
502
+ top: 6px;
503
+ right: 6px;
504
+ background: rgba(255, 255, 255, 0.1);
505
+ border: none;
506
+ color: #aaa;
507
+ font-size: 12px;
508
+ cursor: pointer;
509
+ padding: 2px 6px;
510
+ border-radius: var(--radius-sm);
511
+ transition: background var(--transition-fast);
512
+ }
513
+
514
+ .chat-code-copy:hover {
515
+ background: rgba(255, 255, 255, 0.2);
516
+ }
517
+
518
+ /* ─── Markdown rendering ─── */
519
+ .md-rendered {
520
+ white-space: normal;
521
+ word-wrap: break-word;
522
+ }
523
+
524
+ .md-heading {
525
+ font-weight: 600;
526
+ margin: 4px 0;
527
+ }
528
+
529
+ .md-h1 { font-size: 1.3em; }
530
+ .md-h2 { font-size: 1.15em; }
531
+ .md-h3 { font-size: 1.05em; }
532
+
533
+ .md-blockquote {
534
+ border-left: 3px solid var(--accent);
535
+ background: var(--glass-bg);
536
+ padding: 6px 12px;
537
+ margin: 4px 0;
538
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
539
+ color: var(--text-secondary);
540
+ }
541
+
542
+ .md-list {
543
+ margin: 4px 0;
544
+ padding-left: 20px;
545
+ }
546
+
547
+ .md-list li {
548
+ margin: 2px 0;
549
+ }
550
+
551
+ ul.md-list {
552
+ list-style: none;
553
+ padding-left: 16px;
554
+ }
555
+
556
+ ul.md-list li::before {
557
+ content: "•";
558
+ color: var(--accent);
559
+ font-weight: bold;
560
+ display: inline-block;
561
+ width: 12px;
562
+ margin-left: -12px;
563
+ }
564
+
565
+ .md-link {
566
+ color: var(--accent);
567
+ text-decoration: underline;
568
+ text-underline-offset: 2px;
569
+ }
570
+
571
+ .md-link:hover {
572
+ opacity: 0.8;
573
+ }
574
+
575
+ .md-inline-code {
576
+ background: var(--glass-bg);
577
+ border: 1px solid var(--glass-border);
578
+ padding: 1px 6px;
579
+ border-radius: 10px;
580
+ font-family: "SF Mono", "Fira Code", "Consolas", monospace;
581
+ font-size: 0.9em;
582
+ }
583
+
584
+ .md-hr {
585
+ border: none;
586
+ border-top: 1px solid var(--glass-border);
587
+ margin: 8px 0;
588
+ }
589
+
590
+ /* ─── Typing indicator ─── */
591
+ .chat-typing {
592
+ display: flex;
593
+ gap: 4px;
594
+ padding: 4px 0;
595
+ }
596
+
597
+ .chat-typing-dot {
598
+ width: 7px;
599
+ height: 7px;
600
+ border-radius: 50%;
601
+ background: var(--text-hint);
602
+ animation: chat-typing-bounce 1.4s infinite ease-in-out;
603
+ }
604
+
605
+ .chat-typing-dot:nth-child(2) {
606
+ animation-delay: 0.16s;
607
+ }
608
+
609
+ .chat-typing-dot:nth-child(3) {
610
+ animation-delay: 0.32s;
611
+ }
612
+
613
+ @keyframes chat-typing-bounce {
614
+ 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
615
+ 40% { transform: scale(1); opacity: 1; }
616
+ }
617
+
618
+ /* ─── Input bar ─── */
619
+ .chat-input-bar {
620
+ border-top: 1px solid var(--border);
621
+ padding: 10px 12px;
622
+ flex-shrink: 0;
623
+ }
624
+
625
+ .chat-resume-btn {
626
+ width: 100%;
627
+ margin-bottom: var(--space-sm);
628
+ }
629
+
630
+ .chat-input-row {
631
+ display: flex;
632
+ gap: 8px;
633
+ align-items: flex-end;
634
+ }
635
+
636
+ .chat-input {
637
+ flex: 1;
638
+ resize: none;
639
+ font-size: 13px;
640
+ min-height: 36px;
641
+ max-height: 100px;
642
+ line-height: 1.4;
643
+ padding: 8px 12px;
644
+ box-sizing: border-box;
645
+ }
646
+
647
+ .chat-send-btn {
648
+ flex-shrink: 0;
649
+ width: 36px;
650
+ height: 36px;
651
+ padding: 0;
652
+ display: flex;
653
+ align-items: center;
654
+ justify-content: center;
655
+ font-size: 16px;
656
+ border-radius: var(--radius-md);
657
+ }
658
+
659
+ /* ═══ Diff Viewer ═══ */
660
+ .diff-viewer {
661
+ background: var(--glass-bg);
662
+ backdrop-filter: blur(12px);
663
+ -webkit-backdrop-filter: blur(12px);
664
+ border: 1px solid var(--glass-border);
665
+ border-radius: var(--radius-lg);
666
+ overflow: hidden;
667
+ min-height: 200px;
668
+ }
669
+
670
+ .diff-viewer.diff-empty {
671
+ display: flex;
672
+ flex-direction: column;
673
+ align-items: center;
674
+ justify-content: center;
675
+ min-height: 300px;
676
+ }
677
+
678
+ .diff-loading {
679
+ text-align: center;
680
+ color: var(--text-hint);
681
+ padding: var(--space-lg);
682
+ font-size: 13px;
683
+ }
684
+
685
+ .diff-summary {
686
+ display: flex;
687
+ align-items: center;
688
+ gap: var(--space-sm);
689
+ padding: 10px 14px;
690
+ font-size: 13px;
691
+ font-weight: 500;
692
+ color: var(--text-primary);
693
+ border-bottom: 1px solid var(--glass-border);
694
+ background: var(--glass-bg);
695
+ }
696
+
697
+ .diff-stat-add {
698
+ color: var(--color-done);
699
+ font-weight: 600;
700
+ font-size: 12px;
701
+ }
702
+
703
+ .diff-stat-del {
704
+ color: var(--color-error);
705
+ font-weight: 600;
706
+ font-size: 12px;
707
+ }
708
+
709
+ .diff-file-list {
710
+ display: flex;
711
+ flex-direction: column;
712
+ }
713
+
714
+ .diff-file-item {
715
+ border-bottom: 1px solid var(--border);
716
+ }
717
+
718
+ .diff-file-item:last-child {
719
+ border-bottom: none;
720
+ }
721
+
722
+ .diff-file-header {
723
+ display: flex;
724
+ align-items: center;
725
+ gap: 8px;
726
+ padding: 10px 14px;
727
+ cursor: pointer;
728
+ transition: background var(--transition-fast);
729
+ font-size: 13px;
730
+ }
731
+
732
+ .diff-file-header:hover {
733
+ background: var(--bg-card-hover);
734
+ }
735
+
736
+ .diff-file-header.added {
737
+ border-left: 3px solid var(--color-done);
738
+ padding-left: 11px;
739
+ }
740
+
741
+ .diff-file-header.deleted {
742
+ border-left: 3px solid var(--color-error);
743
+ padding-left: 11px;
744
+ }
745
+
746
+ .diff-file-header.modified {
747
+ border-left: 3px solid var(--color-inreview);
748
+ padding-left: 11px;
749
+ }
750
+
751
+ .diff-file-icon {
752
+ font-size: 14px;
753
+ flex-shrink: 0;
754
+ }
755
+
756
+ .diff-file-name {
757
+ flex: 1;
758
+ font-weight: 500;
759
+ color: var(--text-primary);
760
+ white-space: nowrap;
761
+ overflow: hidden;
762
+ text-overflow: ellipsis;
763
+ }
764
+
765
+ .diff-file-stats {
766
+ display: flex;
767
+ gap: 6px;
768
+ flex-shrink: 0;
769
+ }
770
+
771
+ .diff-file-toggle {
772
+ color: var(--text-hint);
773
+ font-size: 12px;
774
+ flex-shrink: 0;
775
+ }
776
+
777
+ /* ─── Diff hunks ─── */
778
+ .diff-hunk {
779
+ background: rgba(6, 8, 16, 0.9);
780
+ font-family: "SF Mono", "Fira Code", "Consolas", monospace;
781
+ font-size: 12px;
782
+ line-height: 1.6;
783
+ overflow-x: auto;
784
+ }
785
+
786
+ .diff-line {
787
+ padding: 1px 14px;
788
+ white-space: pre;
789
+ }
790
+
791
+ .diff-line.addition {
792
+ background: rgba(16, 185, 129, 0.1);
793
+ color: #6ee7b7;
794
+ }
795
+
796
+ .diff-line.deletion {
797
+ background: rgba(248, 113, 113, 0.1);
798
+ color: #fca5a5;
799
+ }
800
+
801
+ .diff-line.context {
802
+ color: #94a3b8;
803
+ }
804
+
805
+ .diff-line.hunk-header {
806
+ color: #7c3aed;
807
+ background: rgba(124, 58, 237, 0.08);
808
+ font-weight: 500;
809
+ }
810
+
811
+ .diff-line-text {
812
+ display: inline;
813
+ }
814
+
815
+ @media (min-width: 1200px) {
816
+ .app-shell[data-has-rail="true"] .session-split {
817
+ grid-template-columns: 1fr;
818
+ }
819
+
820
+ .app-shell[data-has-rail="true"] .session-split > .session-list {
821
+ display: none;
822
+ }
823
+
824
+ .app-shell[data-has-rail="true"] .session-detail {
825
+ min-height: 520px;
826
+ }
827
+ }