loadtoagent 1.3.3 → 1.3.5
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.
- package/main.js +53 -8
- package/package.json +5 -2
- package/renderer/app-agent-actions.js +172 -66
- package/renderer/app-bootstrap.js +3 -1
- package/renderer/app-dashboard.js +36 -7
- package/renderer/app-drawer-content.js +177 -59
- package/renderer/app-drawer-data.js +7 -3
- package/renderer/app-drawer.js +72 -33
- package/renderer/app-events-dialogs.js +8 -1
- package/renderer/app-events-navigation.js +7 -0
- package/renderer/app-events-sessions.js +136 -13
- package/renderer/app-graph-model.js +2 -5
- package/renderer/app-graph-orchestration.js +7 -18
- package/renderer/app-graph-view.js +194 -48
- package/renderer/app-management.js +330 -35
- package/renderer/app-quality.js +5 -0
- package/renderer/app-session-render.js +20 -83
- package/renderer/app.js +5 -1
- package/renderer/i18n-messages.js +232 -21
- package/renderer/index.html +9 -6
- package/renderer/styles-components.css +140 -0
- package/renderer/styles-control-room.css +1439 -0
- package/renderer/styles-management.css +390 -3
- package/renderer/styles-responsive-shell.css +5 -0
- package/renderer/styles-runtime-overview.css +20 -0
- package/renderer/terminal-agent.js +31 -7
- package/renderer/terminal.js +4 -1
- package/src/agentMonitor/claudeParser.js +8 -4
- package/src/agentMonitor/codexParser.js +5 -4
- package/src/agentMonitor/genericParser.js +7 -6
- package/src/agentMonitor.js +44 -4
- package/src/attentionNotifier.js +3 -0
- package/src/ipc/registerTerminalIpc.js +2 -2
- package/src/monitorWorker.js +1 -1
- package/src/nodePtyRuntime.js +58 -0
- package/src/processMonitor.js +68 -7
- package/src/terminalHost.js +104 -5
- package/src/terminalManager.js +21 -3
|
@@ -65,14 +65,24 @@
|
|
|
65
65
|
flex: 0 0 36px;
|
|
66
66
|
display: grid;
|
|
67
67
|
place-items: center;
|
|
68
|
-
border: 1px solid rgba(
|
|
68
|
+
border: 1px solid rgba(89, 216, 255, .28);
|
|
69
69
|
border-radius: 11px;
|
|
70
|
-
background: rgba(
|
|
71
|
-
color: #
|
|
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
|
}
|
|
@@ -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
|
-
|
|
48
|
-
|
|
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();
|
package/renderer/terminal.js
CHANGED
|
@@ -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);
|