loadtoagent 1.3.2 → 1.3.4

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 (37) hide show
  1. package/main.js +53 -8
  2. package/package.json +2 -1
  3. package/renderer/app-agent-actions.js +172 -66
  4. package/renderer/app-bootstrap.js +3 -1
  5. package/renderer/app-dashboard.js +36 -7
  6. package/renderer/app-drawer-content.js +177 -59
  7. package/renderer/app-drawer-data.js +7 -3
  8. package/renderer/app-drawer.js +72 -33
  9. package/renderer/app-events-dialogs.js +8 -1
  10. package/renderer/app-events-navigation.js +7 -0
  11. package/renderer/app-events-sessions.js +136 -13
  12. package/renderer/app-graph-model.js +2 -5
  13. package/renderer/app-graph-orchestration.js +7 -18
  14. package/renderer/app-graph-view.js +194 -48
  15. package/renderer/app-management.js +330 -35
  16. package/renderer/app-quality.js +5 -0
  17. package/renderer/app-session-render.js +20 -83
  18. package/renderer/app.js +5 -1
  19. package/renderer/i18n-messages.js +232 -21
  20. package/renderer/index.html +9 -6
  21. package/renderer/styles-components.css +140 -0
  22. package/renderer/styles-control-room.css +1439 -0
  23. package/renderer/styles-management.css +390 -3
  24. package/renderer/styles-responsive-shell.css +5 -0
  25. package/renderer/styles-runtime-overview.css +20 -0
  26. package/renderer/terminal-agent.js +31 -7
  27. package/renderer/terminal.js +4 -1
  28. package/src/agentMonitor/claudeParser.js +8 -4
  29. package/src/agentMonitor/codexParser.js +5 -4
  30. package/src/agentMonitor/genericParser.js +7 -6
  31. package/src/agentMonitor.js +44 -4
  32. package/src/attentionNotifier.js +3 -0
  33. package/src/ipc/registerTerminalIpc.js +2 -2
  34. package/src/monitorWorker.js +1 -1
  35. package/src/processMonitor.js +68 -7
  36. package/src/terminalHost.js +6 -4
  37. package/src/terminalManager.js +16 -2
@@ -65,14 +65,24 @@
65
65
  flex: 0 0 36px;
66
66
  display: grid;
67
67
  place-items: center;
68
- border: 1px solid rgba(246, 189, 85, .28);
68
+ border: 1px solid rgba(89, 216, 255, .28);
69
69
  border-radius: 11px;
70
- background: rgba(246, 189, 85, .08);
71
- color: #f3c66f;
70
+ background: rgba(89, 216, 255, .08);
71
+ color: #79ddf6;
72
72
  font-size: 15px;
73
73
  font-weight: 800;
74
74
  }
75
75
 
76
+ .operations-signal i {
77
+ width: 3px;
78
+ border-radius: 99px;
79
+ background: currentColor;
80
+ box-shadow: 0 0 8px rgba(89, 216, 255, .58);
81
+ }
82
+ .operations-signal i:nth-child(1) { height: 8px; opacity: .62; }
83
+ .operations-signal i:nth-child(2) { height: 19px; }
84
+ .operations-signal i:nth-child(3) { height: 12px; opacity: .82; }
85
+
76
86
  .operations-heading-copy { min-width: 0; }
77
87
  .operations-heading-copy p,
78
88
  .attention-inbox-head p { margin: 0 0 5px; color: var(--green); font-size: 12px; font-weight: 800; letter-spacing: .12em; }
@@ -92,7 +102,11 @@
92
102
  border: 1px solid #2a3a48;
93
103
  border-radius: 10px;
94
104
  background: #101a26;
105
+ color: inherit;
106
+ cursor: pointer;
95
107
  }
108
+ .operations-review-total:hover { border-color: #48738c; background: #122230; }
109
+ .operations-review-total i { color: #75d8ee; font-style: normal; }
96
110
  .operations-review-total strong { color: #f4f8fa; font-size: 21px; font-variant-numeric: tabular-nums; line-height: 1; }
97
111
  .operations-review-total span { color: #a7b6c2; font-size: 12px; white-space: nowrap; }
98
112
  .attention-inbox-head strong { color: var(--text); font-size: 36px; }
@@ -149,6 +163,231 @@
149
163
  .operations-more button i { font-style: normal; }
150
164
  .operations-clear { margin: 0; padding: 13px 18px; color: #8edab7; font-size: 12px; }
151
165
 
166
+ /* The home surface is an operator console first. Alerts remain available in a
167
+ compact secondary rail instead of deciding the visual hierarchy. */
168
+ .supervision-metrics {
169
+ display: grid;
170
+ grid-template-columns: repeat(4, minmax(0, 1fr));
171
+ border-bottom: 1px solid var(--line-soft);
172
+ background: linear-gradient(90deg, rgba(22, 41, 54, .42), rgba(10, 17, 26, .2));
173
+ }
174
+
175
+ .supervision-metrics > div {
176
+ display: flex;
177
+ align-items: baseline;
178
+ justify-content: space-between;
179
+ gap: 10px;
180
+ min-width: 0;
181
+ padding: 11px 16px;
182
+ border-right: 1px solid var(--line-soft);
183
+ }
184
+ .supervision-metrics > div:last-child { border-right: 0; }
185
+ .supervision-metrics span { color: #b8c7d1; font-size: 12px; }
186
+ .supervision-metrics b { color: #84ddf2; font-size: 18px; font-variant-numeric: tabular-nums; }
187
+
188
+ .supervision-console {
189
+ display: grid;
190
+ grid-template-columns: minmax(250px, .68fr) minmax(0, 1.55fr);
191
+ min-height: 392px;
192
+ background: #080f18;
193
+ }
194
+
195
+ .supervision-queue {
196
+ min-width: 0;
197
+ border-right: 1px solid var(--line-soft);
198
+ background: #09111a;
199
+ }
200
+ .supervision-queue > header {
201
+ display: flex;
202
+ align-items: center;
203
+ justify-content: space-between;
204
+ gap: 12px;
205
+ min-height: 58px;
206
+ padding: 10px 13px;
207
+ border-bottom: 1px solid var(--line-soft);
208
+ }
209
+ .supervision-queue > header span,
210
+ .supervision-queue > header b { display: block; }
211
+ .supervision-queue > header span { color: #75d8ee; font-size: 12px; font-weight: 800; letter-spacing: .08em; }
212
+ .supervision-queue > header b { margin-top: 2px; color: #aab8c2; font-size: 12px; font-weight: 550; }
213
+ .supervision-queue > header strong { min-width: 30px; color: #e8f4f8; font-size: 20px; text-align: right; }
214
+ .supervision-queue > div { display: grid; max-height: 590px; overflow-y: auto; }
215
+
216
+ .supervision-queue-item {
217
+ display: grid;
218
+ grid-template-columns: 22px 30px minmax(0, 1fr) auto;
219
+ align-items: center;
220
+ gap: 9px;
221
+ min-width: 0;
222
+ min-height: 76px;
223
+ padding: 10px 12px;
224
+ border: 0;
225
+ border-bottom: 1px solid var(--line-soft);
226
+ color: var(--text);
227
+ background: transparent;
228
+ text-align: left;
229
+ cursor: pointer;
230
+ }
231
+ .supervision-queue-item:hover { background: rgba(89, 216, 255, .055); }
232
+ .supervision-queue-item.selected {
233
+ background: linear-gradient(90deg, color-mix(in srgb, var(--management-provider) 12%, transparent), rgba(20, 36, 48, .74));
234
+ box-shadow: inset 3px 0 var(--management-provider);
235
+ }
236
+ .supervision-rank { color: #748795; font-size: 12px; font-weight: 800; text-align: center; }
237
+ .supervision-queue-item.selected .supervision-rank { color: #d9f6fc; }
238
+ .supervision-queue-item .provider-mark { width: 30px; height: 30px; font-size: 12px; }
239
+ .supervision-queue-copy { min-width: 0; }
240
+ .supervision-queue-copy > * { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
241
+ .supervision-queue-copy small { color: var(--management-provider); font-size: 12px; }
242
+ .supervision-queue-copy b { margin-top: 2px; font-size: 13px; }
243
+ .supervision-queue-copy em { margin-top: 3px; color: #d3dde4; font-size: 12px; font-style: normal; }
244
+ .supervision-queue-copy i { margin-top: 2px; color: #8ea0ac; font-size: 12px; font-style: normal; }
245
+ .supervision-queue-meta { display: grid; justify-items: end; gap: 6px; }
246
+ .supervision-queue-meta b { padding: 3px 6px; border-radius: 6px; color: #7fdda9; background: rgba(76, 227, 154, .08); font-size: 12px; white-space: nowrap; }
247
+ .supervision-queue-meta b.recover { color: #8fdcec; background: rgba(89, 216, 255, .08); }
248
+ .supervision-queue-meta b.observe { color: #afbdc7; background: #17212c; }
249
+ .supervision-queue-meta small { color: #8fa1ae; font-size: 12px; white-space: nowrap; }
250
+
251
+ .supervision-primary {
252
+ min-width: 0;
253
+ display: flex;
254
+ flex-direction: column;
255
+ padding: 15px;
256
+ background:
257
+ radial-gradient(circle at 100% 0, color-mix(in srgb, var(--management-provider) 9%, transparent), transparent 34%),
258
+ #0a121c;
259
+ }
260
+ .supervision-primary-head {
261
+ display: grid;
262
+ grid-template-columns: 38px minmax(0, 1fr) auto;
263
+ align-items: center;
264
+ gap: 11px;
265
+ }
266
+ .supervision-primary-head > div { min-width: 0; }
267
+ .supervision-primary-head small { color: var(--management-provider); font-size: 12px; }
268
+ .supervision-primary-head h3 { margin: 3px 0 0; overflow: hidden; font-size: 17px; text-overflow: ellipsis; white-space: nowrap; }
269
+ .supervision-primary-head p { margin: 4px 0 0; overflow: hidden; color: #9eafbb; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
270
+ .supervision-mobile-now { display: none; }
271
+ .supervision-status { display: inline-flex; align-items: center; gap: 6px; padding: 6px 9px; border: 1px solid #315064; border-radius: 999px; color: #9de8f8; background: rgba(89, 216, 255, .07); font-size: 12px; font-weight: 750; }
272
+ .supervision-status i { width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 9px currentColor; }
273
+ .supervision-status.paused,
274
+ .supervision-status.waiting { color: #f0c76b; border-color: rgba(233, 185, 73, .34); background: rgba(233, 185, 73, .07); }
275
+
276
+ .supervision-watch-reason {
277
+ display: grid;
278
+ grid-template-columns: auto minmax(0, 1fr) auto;
279
+ align-items: center;
280
+ gap: 9px;
281
+ margin-top: 13px;
282
+ padding: 9px 11px;
283
+ border: 1px solid rgba(89, 216, 255, .18);
284
+ border-radius: 9px;
285
+ background: rgba(89, 216, 255, .045);
286
+ }
287
+ .supervision-watch-reason span { color: #76d9ee; font-size: 12px; font-weight: 800; }
288
+ .supervision-watch-reason b { min-width: 0; color: #dae7ed; font-size: 12px; }
289
+ .supervision-watch-reason small { color: #8fa0ab; font-size: 12px; white-space: nowrap; }
290
+
291
+ .supervision-behavior {
292
+ display: grid;
293
+ grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1.12fr) 24px minmax(0, 1fr);
294
+ align-items: stretch;
295
+ gap: 5px;
296
+ margin-top: 12px;
297
+ }
298
+ .supervision-behavior section {
299
+ min-width: 0;
300
+ min-height: 122px;
301
+ padding: 11px;
302
+ border: 1px solid #243341;
303
+ border-radius: 10px;
304
+ background: rgba(8, 15, 24, .82);
305
+ }
306
+ .supervision-behavior section.current { border-color: rgba(89, 216, 255, .36); background: rgba(25, 50, 63, .33); }
307
+ .supervision-behavior section > span { display: flex; align-items: center; gap: 6px; color: #9babb6; font-size: 12px; font-weight: 800; }
308
+ .supervision-behavior section > span i { width: 20px; height: 20px; display: grid; place-items: center; border-radius: 6px; color: #82deef; background: #142b37; font-style: normal; }
309
+ .supervision-behavior section > b,
310
+ .supervision-behavior section > small { display: -webkit-box; overflow: hidden; overflow-wrap: anywhere; -webkit-box-orient: vertical; }
311
+ .supervision-behavior section > b { margin-top: 10px; color: #e2ebef; font-size: 13px; line-height: 1.48; -webkit-line-clamp: 2; }
312
+ .supervision-behavior section > small { margin-top: 6px; color: #9cacb7; font-size: 12px; line-height: 1.45; -webkit-line-clamp: 2; }
313
+ .supervision-flow-arrow { align-self: center; color: #4f778b; font-size: 17px; font-style: normal; text-align: center; }
314
+
315
+ .supervision-control-strip {
316
+ display: flex;
317
+ align-items: center;
318
+ justify-content: space-between;
319
+ gap: 15px;
320
+ margin-top: 12px;
321
+ padding: 10px 11px;
322
+ border: 1px solid #263746;
323
+ border-radius: 10px;
324
+ background: #0b1621;
325
+ }
326
+ .supervision-control-strip > div:first-child { min-width: 0; display: grid; grid-template-columns: auto auto; align-items: center; justify-content: start; gap: 3px 9px; }
327
+ .supervision-control-strip span { color: #96a7b2; font-size: 12px; }
328
+ .supervision-control-strip b { display: inline-flex; align-items: center; gap: 5px; color: #7fdda9; font-size: 12px; }
329
+ .supervision-control-strip b.recover { color: #8fdcec; }
330
+ .supervision-control-strip b.observe { color: #b3c0c9; }
331
+ .supervision-control-strip b i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
332
+ .supervision-control-strip small { grid-column: 1 / -1; overflow: hidden; color: #9dabb5; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
333
+ .supervision-control-actions { display: flex; flex: 0 0 auto; gap: 7px; }
334
+ .supervision-control-actions button,
335
+ .supervision-intervention > summary {
336
+ min-height: 44px;
337
+ border: 1px solid #315064;
338
+ border-radius: 9px;
339
+ color: #cce7ee;
340
+ background: #10212d;
341
+ cursor: pointer;
342
+ }
343
+ .supervision-control-actions button { padding: 0 11px; font-size: 12px; font-weight: 750; }
344
+ .supervision-control-actions button:hover { border-color: #5ac4dd; color: #fff; }
345
+ .supervision-primary > .management-control-buttons { margin-top: 9px; }
346
+
347
+ .supervision-intervention { margin-top: 10px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
348
+ .supervision-intervention > summary {
349
+ display: flex;
350
+ align-items: center;
351
+ justify-content: space-between;
352
+ gap: 12px;
353
+ padding: 7px 11px;
354
+ list-style: none;
355
+ }
356
+ .supervision-intervention > summary::-webkit-details-marker { display: none; }
357
+ .supervision-intervention > summary span > * { display: block; }
358
+ .supervision-intervention > summary b { font-size: 12px; }
359
+ .supervision-intervention > summary small { margin-top: 2px; color: #9caeb9; font-size: 12px; }
360
+ .supervision-intervention > summary i { font-style: normal; transition: transform .18s ease; }
361
+ .supervision-intervention[open] > summary i { transform: rotate(180deg); }
362
+ .supervision-intervention > .agent-command-panel { margin-top: 8px; }
363
+
364
+ .supervision-attention-bar {
365
+ display: flex;
366
+ align-items: center;
367
+ justify-content: flex-end;
368
+ gap: 7px;
369
+ min-height: 48px;
370
+ padding: 7px 12px;
371
+ border-top: 1px solid var(--line-soft);
372
+ background: #09111a;
373
+ }
374
+ .supervision-attention-bar > span:first-child { margin-right: auto; color: #8596a2; font-size: 12px; }
375
+ .supervision-attention-bar button,
376
+ .supervision-clear { min-height: 32px; display: inline-flex; align-items: center; gap: 6px; padding: 0 9px; border: 1px solid #263746; border-radius: 8px; color: #b7c4cd; background: #0e1823; font-size: 12px; }
377
+ .supervision-attention-bar button { cursor: pointer; }
378
+ .supervision-attention-bar button:hover { border-color: #466376; color: #edf6f8; }
379
+ .supervision-attention-bar button i { width: 6px; height: 6px; border-radius: 50%; background: #6ad0e7; }
380
+ .supervision-attention-bar [data-management-filter="critical"] i { background: #ff6b76; }
381
+ .supervision-attention-bar [data-management-filter="warning"] i { background: #e9b949; }
382
+ .supervision-attention-bar b,
383
+ .supervision-clear b { color: #edf5f8; font-variant-numeric: tabular-nums; }
384
+ .supervision-clear { color: #82cfa9; }
385
+
386
+ .supervision-empty { display: grid; justify-items: center; gap: 6px; padding: 36px 20px; text-align: center; }
387
+ .supervision-empty span { color: #66d3ea; font-size: 27px; }
388
+ .supervision-empty b { color: #e3edf1; font-size: 16px; }
389
+ .supervision-empty small { color: #92a2ad; }
390
+
152
391
  .attention-inbox-summary { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; padding: 12px 20px; border-bottom: 1px solid var(--line-soft); }
153
392
  .management-filter-all,
154
393
  .management-filter-group { display: flex; align-items: center; gap: 6px; }
@@ -176,6 +415,95 @@
176
415
  .attention-reason span { color: #e9b949; font-size: 12px; font-weight: 800; }
177
416
  .attention-reason p { margin: 0; color: #e7edf6; line-height: 1.55; }
178
417
  .attention-reason small { color: var(--muted); }
418
+ .attention-decision-flow {
419
+ display: grid;
420
+ grid-template-columns: minmax(0, 1.08fr) 28px minmax(0, .96fr) 28px minmax(0, 1.08fr);
421
+ align-items: stretch;
422
+ gap: 8px;
423
+ }
424
+ .attention-decision-flow > section {
425
+ min-width: 0;
426
+ display: flex;
427
+ flex-direction: column;
428
+ gap: 9px;
429
+ padding: 14px;
430
+ border: 1px solid rgba(107, 151, 181, .22);
431
+ border-radius: 13px;
432
+ background: rgba(16, 27, 40, .76);
433
+ }
434
+ .attention-decision-flow > section > span {
435
+ display: flex;
436
+ align-items: center;
437
+ gap: 8px;
438
+ color: #8ca0b1;
439
+ font-size: 12px;
440
+ font-weight: 800;
441
+ letter-spacing: .025em;
442
+ }
443
+ .attention-decision-flow > section > span i {
444
+ width: 22px;
445
+ height: 22px;
446
+ display: inline-grid;
447
+ place-items: center;
448
+ border: 1px solid currentColor;
449
+ border-radius: 50%;
450
+ font-size: 11px;
451
+ font-style: normal;
452
+ }
453
+ .attention-decision-flow .agent-reply { border-color: rgba(100, 203, 229, .28); background: linear-gradient(145deg, rgba(22, 48, 61, .72), rgba(12, 22, 34, .86)); }
454
+ .attention-decision-flow .agent-reply > span { color: #79d5e8; }
455
+ .attention-decision-flow blockquote {
456
+ display: -webkit-box;
457
+ margin: 0;
458
+ overflow: hidden;
459
+ color: #e5edf5;
460
+ font-size: 14px;
461
+ line-height: 1.58;
462
+ overflow-wrap: anywhere;
463
+ -webkit-box-orient: vertical;
464
+ -webkit-line-clamp: 6;
465
+ }
466
+ .attention-decision-flow .agent-reply small,
467
+ .attention-decision-flow .agent-next small {
468
+ display: block;
469
+ margin-top: auto;
470
+ padding-top: 9px;
471
+ border-top: 1px solid rgba(125, 151, 170, .15);
472
+ color: #8fa0af;
473
+ font-size: 12px;
474
+ line-height: 1.5;
475
+ }
476
+ .attention-decision-flow .agent-reply small b,
477
+ .attention-decision-flow .agent-next small strong { color: #b9c7d2; font-weight: 750; }
478
+ .attention-decision-flow .user-decision { border-color: rgba(233, 185, 73, .28); background: linear-gradient(145deg, rgba(54, 42, 19, .46), rgba(18, 24, 32, .88)); }
479
+ .attention-decision-flow .user-decision > span { color: #efc966; }
480
+ .attention-decision-flow .user-decision > b,
481
+ .attention-decision-flow .agent-next > b { color: #edf2f7; font-size: 14px; line-height: 1.55; overflow-wrap: anywhere; }
482
+ .attention-decision-flow .user-decision > p { margin: 0; color: #b8c4cf; font-size: 13px; line-height: 1.55; }
483
+ .attention-decision-flow .agent-next { border-color: rgba(76, 227, 154, .25); background: linear-gradient(145deg, rgba(18, 55, 42, .46), rgba(14, 24, 31, .88)); }
484
+ .attention-decision-flow .agent-next > span { color: #72dfaa; }
485
+ .attention-flow-arrow { align-self: center; color: #5d7485; font-size: 20px; font-style: normal; text-align: center; }
486
+ .attention-draft-action {
487
+ min-height: 34px;
488
+ margin-top: 2px;
489
+ padding: 7px 10px;
490
+ border: 1px solid rgba(76, 227, 154, .34);
491
+ border-radius: 9px;
492
+ color: #8ce6b9;
493
+ background: rgba(76, 227, 154, .08);
494
+ font-size: 12px;
495
+ font-weight: 750;
496
+ cursor: pointer;
497
+ }
498
+ .attention-draft-action:hover { border-color: #72dfaa; color: #dff9ec; background: rgba(76, 227, 154, .14); }
499
+ .attention-evidence-details { border: 1px solid var(--line-soft); border-radius: 12px; background: rgba(9, 15, 24, .52); overflow: hidden; }
500
+ .attention-evidence-details > summary { display: flex; align-items: center; gap: 10px; padding: 11px 13px; cursor: pointer; list-style: none; }
501
+ .attention-evidence-details > summary::-webkit-details-marker { display: none; }
502
+ .attention-evidence-details > summary span { color: #b8c5d0; font-size: 12px; font-weight: 750; }
503
+ .attention-evidence-details > summary small { color: #7f909f; font-size: 12px; }
504
+ .attention-evidence-details > summary i { margin-left: auto; color: #7c91a1; font-style: normal; transition: transform .16s ease; }
505
+ .attention-evidence-details[open] > summary i { transform: rotate(180deg); }
506
+ .attention-evidence-details > div { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 0 10px 10px; }
179
507
  .management-quick-actions,
180
508
  .management-control-buttons { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 7px; }
181
509
  .management-quick-actions button,
@@ -341,14 +669,25 @@
341
669
  .operations-metrics { grid-template-columns: repeat(4, minmax(0, 1fr)); }
342
670
  .operations-metrics > * { min-width: 0; padding-inline: 9px; }
343
671
  .operations-priority { grid-template-columns: 1fr; }
672
+ .supervision-console { grid-template-columns: 1fr; }
673
+ .supervision-queue { border-right: 0; border-bottom: 1px solid var(--line-soft); }
674
+ .supervision-queue > div { grid-template-columns: repeat(2, minmax(0, 1fr)); max-height: 260px; }
675
+ .supervision-queue-item:nth-child(odd) { border-right: 1px solid var(--line-soft); }
344
676
  .attention-card > header { grid-template-columns: 38px 1fr; }
345
677
  .attention-card > header .confidence { grid-column: 2; justify-self: start; }
346
678
  .attention-reason { grid-template-columns: 1fr; }
679
+ .attention-decision-flow { grid-template-columns: 1fr; }
680
+ .attention-flow-arrow { transform: rotate(90deg); }
347
681
  .management-evidence dl { grid-template-columns: 1fr; }
348
682
  .management-evidence dl div { border-right: 0; border-bottom: 1px solid var(--line-soft); }
349
683
  }
350
684
 
351
685
  @media (max-width: 640px) {
686
+ .operations-overview { display: flex; flex-direction: column; }
687
+ .operations-overview > header { order: 0; }
688
+ .supervision-console { order: 1; }
689
+ .supervision-metrics { order: 2; }
690
+ .supervision-attention-bar { order: 3; }
352
691
  .operations-overview > header,
353
692
  .attention-inbox-head { align-items: flex-start; flex-direction: column; padding: 18px; }
354
693
  .operations-review-total { align-self: stretch; justify-content: space-between; }
@@ -360,5 +699,53 @@
360
699
  .management-filter-group { width: 100%; }
361
700
  .management-filter-all button { width: 100%; justify-content: center; }
362
701
  .attention-card { padding: 13px; }
702
+ .attention-decision-flow > section { padding: 12px; }
703
+ .attention-decision-flow blockquote { -webkit-line-clamp: 8; }
704
+ .attention-evidence-details > summary { align-items: flex-start; }
705
+ .attention-evidence-details > summary small { display: none; }
706
+ .attention-evidence-details > div { grid-template-columns: 1fr; }
363
707
  .management-progress > p { align-items: flex-start; flex-direction: column; }
708
+ .supervision-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
709
+ .supervision-metrics > div:nth-child(2) { border-right: 0; }
710
+ .supervision-metrics > div:nth-child(-n+2) { border-bottom: 1px solid var(--line-soft); }
711
+ .supervision-queue > div { display: block; max-height: 245px; }
712
+ .supervision-queue-item:nth-child(odd) { border-right: 0; }
713
+ .operations-heading-copy > span {
714
+ display: -webkit-box;
715
+ overflow: hidden;
716
+ -webkit-box-orient: vertical;
717
+ -webkit-line-clamp: 3;
718
+ }
719
+ .supervision-primary { order: 1; padding: 12px; }
720
+ .supervision-queue { order: 2; }
721
+ .supervision-primary-head { grid-template-columns: 34px minmax(0, 1fr); }
722
+ .supervision-status { grid-column: 2; justify-self: start; }
723
+ .supervision-mobile-now {
724
+ display: grid;
725
+ grid-template-columns: minmax(0, 1fr) auto;
726
+ align-items: center;
727
+ gap: 10px;
728
+ margin-top: 12px;
729
+ padding: 11px;
730
+ border: 1px solid rgba(89, 216, 255, .32);
731
+ border-radius: 10px;
732
+ background: rgba(25, 50, 63, .34);
733
+ }
734
+ .supervision-mobile-now > div { min-width: 0; }
735
+ .supervision-mobile-now span,
736
+ .supervision-mobile-now b,
737
+ .supervision-mobile-now small { display: block; }
738
+ .supervision-mobile-now span { color: #83deef; font-size: 12px; font-weight: 800; }
739
+ .supervision-mobile-now b { margin-top: 4px; overflow: hidden; color: #edf6f8; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
740
+ .supervision-mobile-now small { margin-top: 3px; overflow: hidden; color: #a8b8c2; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
741
+ .supervision-mobile-now button { min-height: 44px; padding: 0 10px; border: 1px solid #3c667b; border-radius: 9px; color: #d9f5fa; background: #102633; font-size: 12px; font-weight: 750; }
742
+ .supervision-watch-reason { grid-template-columns: 1fr; }
743
+ .supervision-behavior { grid-template-columns: 1fr; }
744
+ .supervision-behavior section.current,
745
+ .supervision-flow-arrow { display: none; }
746
+ .supervision-control-strip { align-items: stretch; flex-direction: column; }
747
+ .supervision-control-actions { display: grid; grid-template-columns: 1fr 1fr; }
748
+ .supervision-attention-bar { align-items: stretch; flex-wrap: wrap; justify-content: flex-start; }
749
+ .supervision-attention-bar > span:first-child { width: 100%; margin: 0; }
750
+ .supervision-clear { margin-left: 0; }
364
751
  }
@@ -398,6 +398,11 @@
398
398
  align-items: flex-start;
399
399
  }
400
400
 
401
+ .chat-progress-updates,
402
+ .chat-turn-waiting {
403
+ margin-left: 0;
404
+ }
405
+
401
406
  .json-object>div {
402
407
  grid-template-columns: 1fr;
403
408
  }
@@ -279,6 +279,26 @@ body[data-current-view="runtime"] .automation-overview { max-width: 1640px; marg
279
279
  .runtime-loop-footer dl { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 8px; }
280
280
  }
281
281
 
282
+ @media (max-width:480px) {
283
+ .runtime-loop-lane-head,
284
+ .runtime-loop-lane-head > div,
285
+ .runtime-loop-detail > header,
286
+ .runtime-loop-detail > header > div,
287
+ .runtime-current-signal,
288
+ .runtime-current-signal > div { min-width: 0; max-width: 100%; }
289
+ .runtime-loop-lane-head > div > small { white-space: normal; overflow-wrap: anywhere; }
290
+ .runtime-loop-tabs { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); width: 100%; overflow: visible; }
291
+ .runtime-loop-tab { grid-template-columns: 26px minmax(0,1fr) 5px; min-width: 0; padding-inline: 7px; }
292
+ .runtime-loop-tab-mark { width: 26px; height: 26px; }
293
+ .runtime-loop-detail > header { flex-direction: column; }
294
+ .runtime-loop-detail h3 { white-space: normal; overflow-wrap: anywhere; }
295
+ .runtime-loop-header-actions { width: 100%; align-items: stretch; }
296
+ .runtime-open-task,
297
+ .runtime-active-phase { min-width: 0; width: 100%; }
298
+ .runtime-current-signal b,
299
+ .runtime-current-signal p { max-width: 100%; }
300
+ }
301
+
282
302
  @media (prefers-reduced-motion:reduce) {
283
303
  .runtime-loop-kicker i { animation: none; }
284
304
  .runtime-schedule-card { transition: none; }
@@ -24,6 +24,10 @@ window.LoadToAgentTerminalAgentActions = function createModule(context) {
24
24
  if (!agentSession || !agentSession.id) return [];
25
25
  const targets = [];
26
26
  const presence = Array.isArray(agentSession.runtimePresence) ? agentSession.runtimePresence : [];
27
+ const blockedTerminalIds = new Set(state.sessions
28
+ .filter(terminal => agentSession.parentId && (terminal.type === 'agent'
29
+ || /sub-agent is controlled by its parent|direct input is disabled/i.test(String(terminal.replay || ''))))
30
+ .map(terminal => terminal.id));
27
31
  const tmuxPresence = presence.filter(item => item.kind === 'tmux');
28
32
  for (const row of tmuxRows()) {
29
33
  const pane = row.pane || {};
@@ -44,9 +48,12 @@ window.LoadToAgentTerminalAgentActions = function createModule(context) {
44
48
  }
45
49
  for (const terminal of state.sessions) {
46
50
  if (terminal.status !== 'running') continue;
47
- const matched = terminal.bridgeId === agentSession.id || presence.some(item => item.terminalId === terminal.id
48
- || Number(item.pid || 0) === Number(terminal.pid || -1)
51
+ if (blockedTerminalIds.has(terminal.id)) continue;
52
+ const exactBridge = terminal.bridgeId === agentSession.id;
53
+ const exactPresence = presence.some(item => item.terminalId === terminal.id);
54
+ const processPresence = !agentSession.parentId && presence.some(item => Number(item.pid || 0) === Number(terminal.pid || -1)
49
55
  || Number(item.parentPid || 0) === Number(terminal.pid || -1));
56
+ const matched = exactBridge || exactPresence || processPresence;
50
57
  if (!matched) continue;
51
58
  targets.push({
52
59
  id: terminal.id,
@@ -56,6 +63,21 @@ window.LoadToAgentTerminalAgentActions = function createModule(context) {
56
63
  terminalId: terminal.id,
57
64
  });
58
65
  }
66
+ // The control-room composer is available before the terminal workbench has
67
+ // necessarily loaded its own session list. Runtime presence already carries
68
+ // the stable terminal id, so keep direct participation available from home.
69
+ for (const item of presence.filter(entry => entry.kind === 'terminal' && entry.terminalId && !blockedTerminalIds.has(entry.terminalId)
70
+ && (!agentSession.parentId || state.sessions.some(terminal => terminal.id === entry.terminalId && terminal.type !== 'agent')))) {
71
+ if (targets.some(target => target.id === item.terminalId)) continue;
72
+ const runtime = String(item.runtime || item.shell || 'PowerShell');
73
+ targets.push({
74
+ id: item.terminalId,
75
+ kind: 'terminal',
76
+ label: String(item.label || runtime),
77
+ detail: `${runtime.toUpperCase()} · PID ${item.pid || '--'}`,
78
+ terminalId: item.terminalId,
79
+ });
80
+ }
59
81
  return [...new Map(targets.map(target => [target.id, target])).values()];
60
82
  }
61
83
 
@@ -104,7 +126,7 @@ window.LoadToAgentTerminalAgentActions = function createModule(context) {
104
126
  return target;
105
127
  }
106
128
 
107
- async function resumeForAgent(agentSession, draft = '', sendDraft = false) {
129
+ async function resumeForAgent(agentSession, draft = '', sendDraft = false, options = {}) {
108
130
  await init();
109
131
  const support = resumeSupport(agentSession);
110
132
  if (!support.supported) throw new Error(support.reason);
@@ -118,18 +140,16 @@ window.LoadToAgentTerminalAgentActions = function createModule(context) {
118
140
  const created = await window.loadtoagent.terminalCreate({
119
141
  type: 'agent',
120
142
  provider: support.provider,
121
- args: resumeLaunchArgs(support, sendDraft ? prompt : ''),
143
+ args: resumeLaunchArgs(support, sendDraft ? prompt : '', { background: options.focus === false }),
122
144
  cwd,
123
145
  bridgeId: agentSession.id,
124
146
  title,
147
+ transient: options.focus === false,
125
148
  cols: 120,
126
149
  rows: 32,
127
150
  });
128
151
  if (!created || !created.id) throw new Error(t('terminal.agent.resume_terminal_failed'));
129
- state.mode = 'general';
130
- moveWorkbench('general');
131
152
  await refreshSessions();
132
- await selectSession(created.id);
133
153
  const target = {
134
154
  id: created.id,
135
155
  kind: 'terminal',
@@ -137,6 +157,10 @@ window.LoadToAgentTerminalAgentActions = function createModule(context) {
137
157
  detail: `${String(created.type || 'agent').toUpperCase()} · PID ${created.pid || '--'}`,
138
158
  terminalId: created.id,
139
159
  };
160
+ if (options.focus === false) return { ...target, promptSent: Boolean(sendDraft && prompt), background: true };
161
+ state.mode = 'general';
162
+ moveWorkbench('general');
163
+ await selectSession(created.id);
140
164
  bindAgent(agentSession, target);
141
165
  queueHistoryRefresh(agentSession);
142
166
  renderTarget();
@@ -168,6 +168,7 @@
168
168
 
169
169
  function resumeSupport(agentSession) {
170
170
  if (!agentSession) return { supported: false, reason: t('terminal.resume.no_session_info') };
171
+ if (agentSession.parentId) return { supported: false, parentControlled: true, reason: t('terminal.resume.parent_controlled') };
171
172
  const sessionId = String(agentSession.externalId || '').trim();
172
173
  if (!sessionId) return { supported: false, reason: t('terminal.resume.no_session_id') };
173
174
  const provider = String(agentSession.provider || '').toLowerCase();
@@ -178,9 +179,11 @@
178
179
  return { supported: true, provider, sessionId, args };
179
180
  }
180
181
 
181
- function resumeLaunchArgs(support, prompt = '') {
182
+ function resumeLaunchArgs(support, prompt = '', options = {}) {
182
183
  const args = [...support.args];
183
184
  const text = String(prompt || '').trim();
185
+ if (options.background && text && support.provider === 'codex') return ['exec', 'resume', support.sessionId, text];
186
+ if (options.background && text && support.provider === 'claude') return ['--resume', support.sessionId, '--print', text];
184
187
  if (text) args.push(text);
185
188
  return args;
186
189
  }
@@ -112,17 +112,21 @@ function createClaudeParser(dependencies) {
112
112
  }
113
113
  }
114
114
 
115
- function initializeSession(fileInfo, parsed) {
115
+ function initializeSession(fileInfo, parsed, options = {}) {
116
116
  const basename = path.basename(fileInfo.file, '.jsonl');
117
117
  const subMatch = fileInfo.file.match(/[\\/]([^\\/]+)[\\/]subagents[\\/]agent-([^\\/]+)\.jsonl$/i);
118
118
  const externalId = subMatch ? subMatch[2] : basename;
119
119
  const session = baseSession('claude', externalId, fileInfo.file, fileInfo);
120
+ session.fullHistory = Boolean(options.fullHistory);
120
121
  session.truncated = parsed.truncated;
121
122
  session.parentId = subMatch ? `claude:${subMatch[1]}` : null;
122
123
  session.depth = subMatch ? 1 : 0;
123
124
  session.agentName = subMatch ? `agent-${subMatch[2].slice(0, 8)}` : '';
124
125
  const desktopSignals = new Set(parsed.rows.map(row => String(row && row.type || '')).filter(Boolean));
126
+ const entrypoints = new Set(parsed.rows.map(row => String(row && row.entrypoint || '').toLowerCase()).filter(Boolean));
127
+ const cliEntrypoint = [...entrypoints].some(value => /^(?:sdk-)?cli$/.test(value));
125
128
  const isDesktop = !subMatch
129
+ && !cliEntrypoint
126
130
  && (desktopSignals.has('queue-operation') || desktopSignals.has('last-prompt') || desktopSignals.has('ai-title'));
127
131
  session.clientKind = isDesktop ? 'claude-desktop' : 'claude-cli';
128
132
  if (isDesktop) session.sourceLabel = 'Claude 데스크톱 앱';
@@ -274,10 +278,10 @@ function createClaudeParser(dependencies) {
274
278
  return session;
275
279
  }
276
280
 
277
- return function parseClaude(fileInfo) {
278
- const parsed = readJsonLines(fileInfo.file);
281
+ return function parseClaude(fileInfo, options = {}) {
282
+ const parsed = readJsonLines(fileInfo.file, options.fullHistory ? Math.max(1, Number(fileInfo.size || 0) + 1) : undefined);
279
283
  if (!parsed.rows.length) return null;
280
- const session = initializeSession(fileInfo, parsed);
284
+ const session = initializeSession(fileInfo, parsed, options);
281
285
  const state = processRows(session, parsed.rows);
282
286
  return finalizeSession(session, state, parsed, fileInfo);
283
287
  };
@@ -46,13 +46,14 @@ function createCodexParser(dependencies) {
46
46
  timeOps: { timestamp },
47
47
  } = dependencies;
48
48
 
49
- function initializeSession(fileInfo, parsed) {
49
+ function initializeSession(fileInfo, parsed, options = {}) {
50
50
  const metaRow = parsed.rows.find(row => row.type === 'session_meta');
51
51
  const meta = (metaRow && metaRow.payload) || {};
52
52
  const externalId = meta.id
53
53
  || meta.session_id
54
54
  || path.basename(fileInfo.file, '.jsonl').split('-').slice(-5).join('-');
55
55
  const session = baseSession('codex', externalId, fileInfo.file, fileInfo);
56
+ session.fullHistory = Boolean(options.fullHistory);
56
57
  session.truncated = parsed.truncated;
57
58
  session.cwd = meta.cwd || '';
58
59
  session.originCwd = meta.cwd || '';
@@ -489,10 +490,10 @@ function createCodexParser(dependencies) {
489
490
  return session;
490
491
  }
491
492
 
492
- return function parseCodex(fileInfo) {
493
- const parsed = readJsonLines(fileInfo.file);
493
+ return function parseCodex(fileInfo, options = {}) {
494
+ const parsed = readJsonLines(fileInfo.file, options.fullHistory ? Math.max(1, Number(fileInfo.size || 0) + 1) : undefined);
494
495
  if (!parsed.rows.length) return null;
495
- const { session, meta } = initializeSession(fileInfo, parsed);
496
+ const { session, meta } = initializeSession(fileInfo, parsed, options);
496
497
  const state = createParseState(session, meta);
497
498
  for (const row of parsed.rows) processRow(session, state, row);
498
499
  return finalizeSession(session, state, fileInfo);