psyclaw 0.29.11 → 0.29.13
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/README.md +4 -4
- package/dist/apps/panel/index.html +849 -337
- package/dist/src/adapters/pi/extension.js +87 -15
- package/dist/src/adapters/pi/extension.js.map +1 -1
- package/dist/src/adapters/pi/rpc.js +1 -1
- package/dist/src/adapters/pi/rpc.js.map +1 -1
- package/dist/src/analysis/stats-router.js +1 -1
- package/dist/src/analysis/stats-router.js.map +1 -1
- package/dist/src/ars/mode-editor.d.ts +1 -5
- package/dist/src/ars/mode-editor.js +1 -9
- package/dist/src/ars/mode-editor.js.map +1 -1
- package/dist/src/branding.d.ts +4 -3
- package/dist/src/branding.js +10 -9
- package/dist/src/branding.js.map +1 -1
- package/dist/src/chat.d.ts +7 -0
- package/dist/src/chat.js +19 -1
- package/dist/src/chat.js.map +1 -1
- package/dist/src/cli-args.d.ts +1 -0
- package/dist/src/cli-args.js +1 -0
- package/dist/src/cli-args.js.map +1 -1
- package/dist/src/cli.js +39 -7
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/literature/knowledge-map.d.ts +4 -0
- package/dist/src/literature/knowledge-map.js +4 -0
- package/dist/src/literature/knowledge-map.js.map +1 -1
- package/dist/src/panel/server.js +9 -109
- package/dist/src/panel/server.js.map +1 -1
- package/dist/src/project/bootstrap.js +0 -2
- package/dist/src/project/bootstrap.js.map +1 -1
- package/dist/src/project/workspace.js +3 -3
- package/dist/src/project/workspace.js.map +1 -1
- package/dist/src/research/choice.d.ts +16 -0
- package/dist/src/research/choice.js +25 -0
- package/dist/src/research/choice.js.map +1 -0
- package/dist/src/session/continuously-work.d.ts +16 -0
- package/dist/src/session/continuously-work.js +44 -0
- package/dist/src/session/continuously-work.js.map +1 -0
- package/dist/src/session/help.d.ts +3 -0
- package/dist/src/session/help.js +68 -26
- package/dist/src/session/help.js.map +1 -1
- package/dist/src/session/modes.js +7 -7
- package/dist/src/session/modes.js.map +1 -1
- package/dist/src/style/cli-ui.d.ts +1 -0
- package/dist/src/style/cli-ui.js +26 -14
- package/dist/src/style/cli-ui.js.map +1 -1
- package/dist/src/updates/update.d.ts +8 -1
- package/dist/src/updates/update.js +68 -2
- package/dist/src/updates/update.js.map +1 -1
- package/dist/src/verify/checklist.d.ts +46 -5
- package/dist/src/verify/checklist.js +139 -24
- package/dist/src/verify/checklist.js.map +1 -1
- package/dist/src/wake-options/runtime.d.ts +1 -0
- package/dist/src/wake-options/runtime.js +12 -2
- package/dist/src/wake-options/runtime.js.map +1 -1
- package/package.json +1 -1
- package/skills/recommended/catalog.json +24 -154
- package/skills/recommended/mcp-catalog.json +16 -4
|
@@ -160,20 +160,29 @@
|
|
|
160
160
|
display: grid;
|
|
161
161
|
grid-template-columns: 210px minmax(0, 1fr);
|
|
162
162
|
min-height: 0;
|
|
163
|
+
transition: grid-template-columns 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
164
|
+
}
|
|
165
|
+
.layout.nav-collapsed {
|
|
166
|
+
grid-template-columns: 58px minmax(0, 1fr);
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
.nav {
|
|
166
|
-
padding:
|
|
170
|
+
padding: 14px 8px;
|
|
167
171
|
background: var(--bg-sidebar);
|
|
168
172
|
border-right: 1px solid var(--border-subtle);
|
|
169
173
|
display: flex;
|
|
170
174
|
flex-direction: column;
|
|
171
175
|
justify-content: space-between;
|
|
176
|
+
overflow: hidden;
|
|
177
|
+
transition: padding 0.2s ease;
|
|
178
|
+
position: relative;
|
|
172
179
|
}
|
|
173
|
-
.nav-
|
|
180
|
+
.nav-header {
|
|
174
181
|
display: flex;
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
align-items: center;
|
|
183
|
+
justify-content: space-between;
|
|
184
|
+
padding: 4px 6px 8px;
|
|
185
|
+
margin-bottom: 4px;
|
|
177
186
|
}
|
|
178
187
|
.nav-label {
|
|
179
188
|
font-size: 10.5px;
|
|
@@ -181,26 +190,67 @@
|
|
|
181
190
|
color: var(--text-tertiary);
|
|
182
191
|
letter-spacing: 0.05em;
|
|
183
192
|
text-transform: uppercase;
|
|
184
|
-
|
|
185
|
-
|
|
193
|
+
white-space: nowrap;
|
|
194
|
+
overflow: hidden;
|
|
195
|
+
text-overflow: ellipsis;
|
|
196
|
+
transition: opacity 0.15s ease;
|
|
197
|
+
}
|
|
198
|
+
.nav-toggle-btn {
|
|
199
|
+
width: 26px;
|
|
200
|
+
height: 26px;
|
|
201
|
+
display: grid;
|
|
202
|
+
place-items: center;
|
|
203
|
+
border-radius: var(--radius-sm);
|
|
204
|
+
color: var(--text-muted);
|
|
205
|
+
background: transparent;
|
|
206
|
+
cursor: pointer;
|
|
207
|
+
transition: all 0.15s ease;
|
|
208
|
+
flex-shrink: 0;
|
|
209
|
+
}
|
|
210
|
+
.nav-toggle-btn:hover {
|
|
211
|
+
background: var(--bg-surface-subtle);
|
|
212
|
+
color: var(--text-main);
|
|
213
|
+
}
|
|
214
|
+
.layout.nav-collapsed .nav-header {
|
|
215
|
+
justify-content: center;
|
|
216
|
+
padding: 2px 0 10px;
|
|
217
|
+
}
|
|
218
|
+
.layout.nav-collapsed .nav-label {
|
|
219
|
+
display: none;
|
|
220
|
+
}
|
|
221
|
+
.layout.nav-collapsed .nav-toggle-btn svg {
|
|
222
|
+
transform: rotate(180deg);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.nav-group {
|
|
226
|
+
display: flex;
|
|
227
|
+
flex-direction: column;
|
|
228
|
+
gap: 4px;
|
|
186
229
|
}
|
|
187
230
|
.nav button {
|
|
188
231
|
width: 100%;
|
|
189
232
|
display: flex;
|
|
190
233
|
align-items: center;
|
|
191
|
-
gap:
|
|
192
|
-
padding:
|
|
234
|
+
gap: 10px;
|
|
235
|
+
padding: 9px 10px;
|
|
193
236
|
border-radius: var(--radius-sm);
|
|
194
237
|
color: var(--text-secondary);
|
|
195
238
|
font-weight: 500;
|
|
196
239
|
font-size: 12.5px;
|
|
197
240
|
text-align: left;
|
|
198
|
-
transition:
|
|
241
|
+
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
199
242
|
position: relative;
|
|
243
|
+
white-space: nowrap;
|
|
244
|
+
}
|
|
245
|
+
.nav button .nav-btn-text {
|
|
246
|
+
flex: 1;
|
|
247
|
+
overflow: hidden;
|
|
248
|
+
text-overflow: ellipsis;
|
|
249
|
+
transition: opacity 0.15s ease;
|
|
200
250
|
}
|
|
201
251
|
.nav button svg {
|
|
202
|
-
width:
|
|
203
|
-
height:
|
|
252
|
+
width: 17px;
|
|
253
|
+
height: 17px;
|
|
204
254
|
color: var(--text-muted);
|
|
205
255
|
flex-shrink: 0;
|
|
206
256
|
transition: color 0.15s ease;
|
|
@@ -222,12 +272,29 @@
|
|
|
222
272
|
.nav button.active svg {
|
|
223
273
|
color: var(--brand-primary);
|
|
224
274
|
}
|
|
275
|
+
|
|
276
|
+
/* Collapsed Nav Styles */
|
|
277
|
+
.layout.nav-collapsed .nav {
|
|
278
|
+
padding: 12px 6px;
|
|
279
|
+
}
|
|
280
|
+
.layout.nav-collapsed .nav button {
|
|
281
|
+
justify-content: center;
|
|
282
|
+
padding: 9px 0;
|
|
283
|
+
}
|
|
284
|
+
.layout.nav-collapsed .nav button .nav-btn-text {
|
|
285
|
+
display: none;
|
|
286
|
+
}
|
|
287
|
+
.layout.nav-collapsed .nav-footer {
|
|
288
|
+
display: none;
|
|
289
|
+
}
|
|
290
|
+
|
|
225
291
|
.nav-footer {
|
|
226
292
|
padding: 12px 10px;
|
|
227
293
|
border-top: 1px solid var(--border-subtle);
|
|
228
294
|
font-size: 11px;
|
|
229
295
|
color: var(--text-muted);
|
|
230
296
|
line-height: 1.4;
|
|
297
|
+
transition: opacity 0.15s ease;
|
|
231
298
|
}
|
|
232
299
|
.nav-footer code {
|
|
233
300
|
font-family: var(--font-mono);
|
|
@@ -270,23 +337,41 @@
|
|
|
270
337
|
.help-grid {
|
|
271
338
|
display: grid;
|
|
272
339
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
273
|
-
gap:
|
|
274
|
-
margin-bottom:
|
|
340
|
+
gap: 14px;
|
|
341
|
+
margin-bottom: 28px;
|
|
275
342
|
}
|
|
276
343
|
.help-mode-card {
|
|
344
|
+
position: relative;
|
|
277
345
|
border: 1px solid var(--border-subtle);
|
|
278
|
-
background: var(--
|
|
279
|
-
border-radius:
|
|
280
|
-
padding:
|
|
281
|
-
|
|
346
|
+
background: linear-gradient(165deg, #ffffff 0%, var(--brand-primary-light) 140%);
|
|
347
|
+
border-radius: 14px;
|
|
348
|
+
padding: 18px 18px 16px;
|
|
349
|
+
overflow: hidden;
|
|
350
|
+
}
|
|
351
|
+
.help-mode-card::before {
|
|
352
|
+
content: "";
|
|
353
|
+
position: absolute;
|
|
354
|
+
left: 0;
|
|
355
|
+
top: 0;
|
|
356
|
+
bottom: 0;
|
|
357
|
+
width: 3px;
|
|
358
|
+
background: var(--brand-primary);
|
|
282
359
|
}
|
|
283
360
|
.help-mode-card .mode-id {
|
|
284
361
|
font-family: var(--font-mono);
|
|
285
|
-
font-size:
|
|
286
|
-
|
|
287
|
-
|
|
362
|
+
font-size: 10px;
|
|
363
|
+
font-weight: 600;
|
|
364
|
+
color: var(--brand-primary);
|
|
365
|
+
letter-spacing: 0.08em;
|
|
288
366
|
text-transform: uppercase;
|
|
289
|
-
margin-bottom:
|
|
367
|
+
margin-bottom: 8px;
|
|
368
|
+
}
|
|
369
|
+
.help-mode-card .mode-label {
|
|
370
|
+
font-size: 16px;
|
|
371
|
+
font-weight: 650;
|
|
372
|
+
color: var(--text-main);
|
|
373
|
+
letter-spacing: -0.02em;
|
|
374
|
+
margin: 0 0 8px;
|
|
290
375
|
}
|
|
291
376
|
.help-mode-card p {
|
|
292
377
|
margin: 0;
|
|
@@ -294,56 +379,164 @@
|
|
|
294
379
|
line-height: 1.55;
|
|
295
380
|
color: var(--text-secondary);
|
|
296
381
|
}
|
|
297
|
-
.help-
|
|
382
|
+
.help-hero {
|
|
383
|
+
display: flex;
|
|
384
|
+
align-items: flex-end;
|
|
385
|
+
justify-content: space-between;
|
|
386
|
+
gap: 16px;
|
|
298
387
|
margin-bottom: 22px;
|
|
388
|
+
padding: 20px 22px;
|
|
389
|
+
border-radius: 16px;
|
|
390
|
+
border: 1px solid var(--brand-primary-border);
|
|
391
|
+
background:
|
|
392
|
+
radial-gradient(120% 80% at 100% 0%, rgba(13, 118, 110, 0.10), transparent 55%),
|
|
393
|
+
linear-gradient(180deg, #ffffff, #f8fafc);
|
|
299
394
|
}
|
|
300
|
-
.help-
|
|
301
|
-
margin: 0 0
|
|
302
|
-
font-size:
|
|
303
|
-
font-weight:
|
|
395
|
+
.help-hero h1 {
|
|
396
|
+
margin: 0 0 6px;
|
|
397
|
+
font-size: 22px;
|
|
398
|
+
font-weight: 700;
|
|
399
|
+
letter-spacing: -0.03em;
|
|
304
400
|
color: var(--text-main);
|
|
305
401
|
}
|
|
402
|
+
.help-hero p {
|
|
403
|
+
margin: 0;
|
|
404
|
+
color: var(--text-muted);
|
|
405
|
+
font-size: 13px;
|
|
406
|
+
max-width: 42rem;
|
|
407
|
+
line-height: 1.5;
|
|
408
|
+
}
|
|
409
|
+
.help-kbd {
|
|
410
|
+
display: inline-flex;
|
|
411
|
+
align-items: center;
|
|
412
|
+
gap: 6px;
|
|
413
|
+
padding: 6px 10px;
|
|
414
|
+
border-radius: 999px;
|
|
415
|
+
border: 1px solid var(--border-subtle);
|
|
416
|
+
background: var(--bg-surface);
|
|
417
|
+
color: var(--text-secondary);
|
|
418
|
+
font-size: 11px;
|
|
419
|
+
font-family: var(--font-mono);
|
|
420
|
+
white-space: nowrap;
|
|
421
|
+
}
|
|
422
|
+
.help-block {
|
|
423
|
+
margin-bottom: 26px;
|
|
424
|
+
}
|
|
425
|
+
.help-block h2 {
|
|
426
|
+
margin: 0 0 12px;
|
|
427
|
+
font-size: 13px;
|
|
428
|
+
font-weight: 700;
|
|
429
|
+
letter-spacing: 0.04em;
|
|
430
|
+
text-transform: uppercase;
|
|
431
|
+
color: var(--text-muted);
|
|
432
|
+
}
|
|
306
433
|
.help-steps {
|
|
307
434
|
margin: 0;
|
|
308
|
-
padding
|
|
435
|
+
padding: 0;
|
|
436
|
+
list-style: none;
|
|
437
|
+
display: grid;
|
|
438
|
+
gap: 8px;
|
|
439
|
+
}
|
|
440
|
+
.help-steps li {
|
|
441
|
+
display: grid;
|
|
442
|
+
grid-template-columns: 28px 1fr;
|
|
443
|
+
gap: 12px;
|
|
444
|
+
align-items: start;
|
|
445
|
+
padding: 12px 14px;
|
|
446
|
+
border-radius: 12px;
|
|
447
|
+
border: 1px solid var(--border-subtle);
|
|
448
|
+
background: var(--bg-surface);
|
|
309
449
|
color: var(--text-secondary);
|
|
310
450
|
font-size: 13px;
|
|
311
|
-
line-height: 1.
|
|
451
|
+
line-height: 1.55;
|
|
452
|
+
}
|
|
453
|
+
.help-steps li::before {
|
|
454
|
+
content: attr(data-step);
|
|
455
|
+
width: 28px;
|
|
456
|
+
height: 28px;
|
|
457
|
+
border-radius: 9px;
|
|
458
|
+
display: grid;
|
|
459
|
+
place-items: center;
|
|
460
|
+
background: var(--brand-primary-light);
|
|
461
|
+
color: var(--brand-primary);
|
|
462
|
+
font-family: var(--font-mono);
|
|
463
|
+
font-size: 12px;
|
|
464
|
+
font-weight: 700;
|
|
312
465
|
}
|
|
313
466
|
.help-commands {
|
|
467
|
+
display: grid;
|
|
468
|
+
gap: 18px;
|
|
469
|
+
}
|
|
470
|
+
.help-cmd-group h3 {
|
|
471
|
+
margin: 0 0 8px;
|
|
472
|
+
font-size: 12px;
|
|
473
|
+
font-weight: 650;
|
|
474
|
+
color: var(--text-muted);
|
|
475
|
+
letter-spacing: 0.02em;
|
|
476
|
+
}
|
|
477
|
+
.help-cmd-list {
|
|
314
478
|
display: grid;
|
|
315
479
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
316
480
|
gap: 8px;
|
|
317
481
|
}
|
|
318
482
|
.help-cmd {
|
|
319
|
-
display:
|
|
320
|
-
|
|
321
|
-
|
|
483
|
+
display: grid;
|
|
484
|
+
grid-template-columns: minmax(7.5rem, auto) 1fr;
|
|
485
|
+
gap: 12px;
|
|
486
|
+
align-items: center;
|
|
322
487
|
border: 1px solid var(--border-subtle);
|
|
323
|
-
border-radius:
|
|
324
|
-
padding:
|
|
325
|
-
background: var(--bg-surface
|
|
488
|
+
border-radius: 12px;
|
|
489
|
+
padding: 11px 13px;
|
|
490
|
+
background: var(--bg-surface);
|
|
491
|
+
transition: border-color 120ms ease, background 120ms ease;
|
|
492
|
+
}
|
|
493
|
+
.help-cmd:hover {
|
|
494
|
+
border-color: var(--brand-primary-border);
|
|
495
|
+
background: var(--brand-primary-light);
|
|
326
496
|
}
|
|
327
497
|
.help-cmd code {
|
|
328
498
|
font-family: var(--font-mono);
|
|
329
499
|
font-size: 12px;
|
|
330
|
-
|
|
500
|
+
font-weight: 600;
|
|
501
|
+
color: var(--brand-primary);
|
|
331
502
|
white-space: nowrap;
|
|
332
503
|
}
|
|
333
504
|
.help-cmd span {
|
|
334
505
|
font-size: 12.5px;
|
|
335
|
-
color: var(--text-
|
|
336
|
-
line-height: 1.
|
|
506
|
+
color: var(--text-secondary);
|
|
507
|
+
line-height: 1.4;
|
|
337
508
|
}
|
|
338
509
|
.help-notes {
|
|
339
510
|
margin: 0;
|
|
340
|
-
padding
|
|
511
|
+
padding: 14px 16px;
|
|
512
|
+
list-style: none;
|
|
513
|
+
display: grid;
|
|
514
|
+
gap: 8px;
|
|
515
|
+
border-radius: 14px;
|
|
516
|
+
border: 1px solid var(--border-subtle);
|
|
517
|
+
background: var(--bg-surface-subtle);
|
|
518
|
+
}
|
|
519
|
+
.help-notes li {
|
|
520
|
+
position: relative;
|
|
521
|
+
padding-left: 14px;
|
|
341
522
|
color: var(--text-muted);
|
|
342
523
|
font-size: 12.5px;
|
|
343
|
-
line-height: 1.
|
|
524
|
+
line-height: 1.55;
|
|
525
|
+
}
|
|
526
|
+
.help-notes li::before {
|
|
527
|
+
content: "";
|
|
528
|
+
position: absolute;
|
|
529
|
+
left: 0;
|
|
530
|
+
top: 0.55em;
|
|
531
|
+
width: 6px;
|
|
532
|
+
height: 6px;
|
|
533
|
+
border-radius: 50%;
|
|
534
|
+
background: var(--brand-primary);
|
|
535
|
+
opacity: 0.55;
|
|
344
536
|
}
|
|
345
537
|
@media (max-width: 960px) {
|
|
346
|
-
.help-grid, .help-
|
|
538
|
+
.help-grid, .help-cmd-list { grid-template-columns: 1fr; }
|
|
539
|
+
.help-hero { flex-direction: column; align-items: flex-start; }
|
|
347
540
|
}
|
|
348
541
|
|
|
349
542
|
.button {
|
|
@@ -939,234 +1132,424 @@
|
|
|
939
1132
|
background: var(--brand-primary-hover);
|
|
940
1133
|
}
|
|
941
1134
|
|
|
942
|
-
/*
|
|
943
|
-
.console-
|
|
944
|
-
position:
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1135
|
+
/* In-page chat: Modern Codex / Gemini style */
|
|
1136
|
+
.console-drawer {
|
|
1137
|
+
position: relative;
|
|
1138
|
+
width: 100%;
|
|
1139
|
+
height: 100%;
|
|
1140
|
+
min-height: 72vh;
|
|
1141
|
+
flex: 1;
|
|
1142
|
+
background: var(--bg-surface);
|
|
1143
|
+
color: var(--text-main);
|
|
1144
|
+
border: none;
|
|
1145
|
+
display: flex;
|
|
1146
|
+
flex-direction: column;
|
|
1147
|
+
font-family: var(--font-sans);
|
|
1148
|
+
}
|
|
1149
|
+
.console-header {
|
|
948
1150
|
display: flex;
|
|
949
1151
|
align-items: center;
|
|
950
|
-
|
|
951
|
-
padding:
|
|
1152
|
+
justify-content: space-between;
|
|
1153
|
+
padding: 12px 20px;
|
|
1154
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
952
1155
|
background: var(--bg-surface);
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
font-
|
|
1156
|
+
}
|
|
1157
|
+
.console-title {
|
|
1158
|
+
font-size: 13.5px;
|
|
1159
|
+
font-weight: 650;
|
|
1160
|
+
color: var(--text-main);
|
|
1161
|
+
display: flex;
|
|
1162
|
+
align-items: center;
|
|
1163
|
+
gap: 9px;
|
|
1164
|
+
}
|
|
1165
|
+
.console-status-tag {
|
|
1166
|
+
font-size: 10.5px;
|
|
957
1167
|
font-weight: 600;
|
|
1168
|
+
padding: 1px 7px;
|
|
1169
|
+
border-radius: 999px;
|
|
1170
|
+
background: var(--ok-bg);
|
|
1171
|
+
color: var(--ok-text);
|
|
1172
|
+
border: 1px solid var(--ok-border);
|
|
1173
|
+
display: inline-flex;
|
|
1174
|
+
align-items: center;
|
|
1175
|
+
gap: 4px;
|
|
1176
|
+
}
|
|
1177
|
+
.console-actions {
|
|
1178
|
+
display: flex;
|
|
1179
|
+
align-items: center;
|
|
1180
|
+
gap: 8px;
|
|
1181
|
+
}
|
|
1182
|
+
.console-btn-icon {
|
|
1183
|
+
background: transparent;
|
|
1184
|
+
border: none;
|
|
1185
|
+
color: var(--text-muted);
|
|
958
1186
|
cursor: pointer;
|
|
959
|
-
|
|
960
|
-
|
|
1187
|
+
padding: 5px;
|
|
1188
|
+
border-radius: var(--radius-sm);
|
|
1189
|
+
display: flex;
|
|
1190
|
+
align-items: center;
|
|
1191
|
+
justify-content: center;
|
|
1192
|
+
transition: all 0.15s ease;
|
|
1193
|
+
}
|
|
1194
|
+
.console-btn-icon:hover {
|
|
1195
|
+
color: var(--text-main);
|
|
1196
|
+
background: var(--bg-surface-subtle);
|
|
961
1197
|
}
|
|
962
|
-
|
|
1198
|
+
|
|
1199
|
+
.console-log {
|
|
1200
|
+
flex: 1;
|
|
1201
|
+
overflow-y: auto;
|
|
1202
|
+
padding: 24px 20px;
|
|
1203
|
+
font-family: var(--font-sans);
|
|
1204
|
+
font-size: 13.5px;
|
|
1205
|
+
line-height: 1.6;
|
|
1206
|
+
display: flex;
|
|
1207
|
+
flex-direction: column;
|
|
1208
|
+
gap: 18px;
|
|
1209
|
+
background: var(--bg-app);
|
|
1210
|
+
scroll-behavior: smooth;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/* Message Rows */
|
|
1214
|
+
.log-entry {
|
|
1215
|
+
display: flex;
|
|
1216
|
+
width: 100%;
|
|
1217
|
+
max-width: 860px;
|
|
1218
|
+
margin: 0 auto;
|
|
1219
|
+
gap: 12px;
|
|
1220
|
+
animation: fadeIn 0.18s ease;
|
|
1221
|
+
}
|
|
1222
|
+
.log-entry.user {
|
|
1223
|
+
justify-content: flex-end;
|
|
1224
|
+
}
|
|
1225
|
+
.log-entry.agent,
|
|
1226
|
+
.log-entry.sys {
|
|
1227
|
+
justify-content: flex-start;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/* User Message Bubble */
|
|
1231
|
+
.log-user-wrap {
|
|
1232
|
+
max-width: 82%;
|
|
1233
|
+
display: flex;
|
|
1234
|
+
flex-direction: column;
|
|
1235
|
+
align-items: flex-end;
|
|
1236
|
+
gap: 4px;
|
|
1237
|
+
}
|
|
1238
|
+
.log-user {
|
|
1239
|
+
color: #ffffff;
|
|
1240
|
+
font-weight: 450;
|
|
1241
|
+
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
1242
|
+
padding: 10px 15px;
|
|
1243
|
+
border-radius: 16px 16px 4px 16px;
|
|
1244
|
+
white-space: pre-wrap;
|
|
1245
|
+
word-break: break-word;
|
|
1246
|
+
box-shadow: var(--shadow-sm);
|
|
1247
|
+
line-height: 1.55;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
/* Agent Message: Codex/Gemini open conversational layout */
|
|
1251
|
+
.agent-avatar {
|
|
1252
|
+
width: 32px;
|
|
1253
|
+
height: 32px;
|
|
1254
|
+
border-radius: 50%;
|
|
1255
|
+
background: linear-gradient(135deg, #0d766e 0%, #0284c7 100%);
|
|
1256
|
+
color: #ffffff;
|
|
1257
|
+
display: grid;
|
|
1258
|
+
place-items: center;
|
|
1259
|
+
font-weight: 700;
|
|
1260
|
+
font-size: 15px;
|
|
1261
|
+
flex-shrink: 0;
|
|
1262
|
+
box-shadow: 0 2px 4px rgba(13, 118, 110, 0.2);
|
|
1263
|
+
}
|
|
1264
|
+
.agent-content-wrap {
|
|
1265
|
+
flex: 1;
|
|
1266
|
+
min-width: 0;
|
|
1267
|
+
display: flex;
|
|
1268
|
+
flex-direction: column;
|
|
1269
|
+
gap: 5px;
|
|
1270
|
+
}
|
|
1271
|
+
.agent-meta {
|
|
1272
|
+
display: flex;
|
|
1273
|
+
align-items: center;
|
|
1274
|
+
gap: 8px;
|
|
1275
|
+
font-size: 12px;
|
|
1276
|
+
font-weight: 600;
|
|
1277
|
+
color: var(--text-secondary);
|
|
1278
|
+
}
|
|
1279
|
+
.agent-role-pill {
|
|
1280
|
+
font-size: 10px;
|
|
1281
|
+
font-weight: 550;
|
|
963
1282
|
background: var(--brand-primary-light);
|
|
964
|
-
|
|
965
|
-
|
|
1283
|
+
color: var(--brand-primary);
|
|
1284
|
+
border: 1px solid var(--brand-primary-border);
|
|
1285
|
+
padding: 0 5px;
|
|
1286
|
+
border-radius: 4px;
|
|
966
1287
|
}
|
|
967
|
-
.
|
|
968
|
-
|
|
969
|
-
bottom: 0;
|
|
970
|
-
right: 28px;
|
|
971
|
-
width: 480px;
|
|
972
|
-
max-width: calc(100vw - 40px);
|
|
973
|
-
height: 560px;
|
|
974
|
-
max-height: calc(100vh - 80px);
|
|
1288
|
+
.log-agent {
|
|
1289
|
+
color: var(--text-main);
|
|
975
1290
|
background: var(--bg-surface);
|
|
1291
|
+
padding: 14px 18px;
|
|
1292
|
+
border-radius: 4px 16px 16px 16px;
|
|
1293
|
+
border: 1px solid var(--border-subtle);
|
|
1294
|
+
word-break: break-word;
|
|
1295
|
+
box-shadow: var(--shadow-card);
|
|
1296
|
+
line-height: 1.65;
|
|
1297
|
+
}
|
|
1298
|
+
.log-agent > :first-child { margin-top: 0; }
|
|
1299
|
+
.log-agent > :last-child { margin-bottom: 0; }
|
|
1300
|
+
.log-agent p { margin: 8px 0; }
|
|
1301
|
+
.log-agent h1, .log-agent h2, .log-agent h3 {
|
|
1302
|
+
margin: 14px 0 6px;
|
|
976
1303
|
color: var(--text-main);
|
|
1304
|
+
font-weight: 650;
|
|
1305
|
+
}
|
|
1306
|
+
.log-agent h1 { font-size: 16px; }
|
|
1307
|
+
.log-agent h2 { font-size: 14.5px; }
|
|
1308
|
+
.log-agent h3 { font-size: 13.5px; }
|
|
1309
|
+
.log-agent ul, .log-agent ol {
|
|
1310
|
+
margin: 6px 0 6px 20px;
|
|
1311
|
+
padding: 0;
|
|
1312
|
+
}
|
|
1313
|
+
.log-agent li { margin: 3px 0; }
|
|
1314
|
+
.log-agent blockquote {
|
|
1315
|
+
border-left: 3px solid var(--brand-primary);
|
|
1316
|
+
background: var(--brand-primary-light);
|
|
1317
|
+
padding: 6px 12px;
|
|
1318
|
+
margin: 8px 0;
|
|
1319
|
+
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
1320
|
+
color: var(--text-secondary);
|
|
1321
|
+
}
|
|
1322
|
+
.log-agent table {
|
|
1323
|
+
width: 100%;
|
|
1324
|
+
border-collapse: collapse;
|
|
1325
|
+
margin: 10px 0;
|
|
1326
|
+
font-size: 12.5px;
|
|
1327
|
+
}
|
|
1328
|
+
.log-agent th, .log-agent td {
|
|
1329
|
+
padding: 6px 10px;
|
|
977
1330
|
border: 1px solid var(--border-subtle);
|
|
978
|
-
|
|
979
|
-
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
|
980
|
-
box-shadow: var(--shadow-md);
|
|
981
|
-
display: flex;
|
|
982
|
-
flex-direction: column;
|
|
983
|
-
z-index: 1000;
|
|
984
|
-
transform: translateY(105%);
|
|
985
|
-
transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
|
|
986
|
-
font-family: var(--font-sans);
|
|
1331
|
+
text-align: left;
|
|
987
1332
|
}
|
|
988
|
-
.
|
|
989
|
-
|
|
1333
|
+
.log-agent th {
|
|
1334
|
+
background: var(--bg-surface-subtle);
|
|
1335
|
+
font-weight: 600;
|
|
990
1336
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1337
|
+
|
|
1338
|
+
/* Code Blocks with Copy Header */
|
|
1339
|
+
.code-container {
|
|
1340
|
+
position: relative;
|
|
1341
|
+
margin: 10px 0;
|
|
1342
|
+
border-radius: var(--radius-md);
|
|
1343
|
+
overflow: hidden;
|
|
1344
|
+
background: #0f172a;
|
|
1345
|
+
border: 1px solid #1e293b;
|
|
996
1346
|
}
|
|
997
|
-
.
|
|
1347
|
+
.code-header {
|
|
998
1348
|
display: flex;
|
|
999
1349
|
align-items: center;
|
|
1000
1350
|
justify-content: space-between;
|
|
1001
|
-
padding: 12px
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1351
|
+
padding: 5px 12px;
|
|
1352
|
+
background: #1e293b;
|
|
1353
|
+
color: #94a3b8;
|
|
1354
|
+
font-size: 11px;
|
|
1355
|
+
font-family: var(--font-mono);
|
|
1356
|
+
user-select: none;
|
|
1357
|
+
}
|
|
1358
|
+
.code-copy-btn {
|
|
1359
|
+
display: inline-flex;
|
|
1360
|
+
align-items: center;
|
|
1361
|
+
gap: 4px;
|
|
1362
|
+
font-size: 11px;
|
|
1363
|
+
color: #cbd5e1;
|
|
1364
|
+
background: transparent;
|
|
1365
|
+
border: none;
|
|
1366
|
+
padding: 2px 6px;
|
|
1367
|
+
border-radius: 4px;
|
|
1368
|
+
cursor: pointer;
|
|
1369
|
+
transition: background 0.12s ease, color 0.12s ease;
|
|
1370
|
+
}
|
|
1371
|
+
.code-copy-btn:hover {
|
|
1372
|
+
background: #334155;
|
|
1373
|
+
color: #ffffff;
|
|
1374
|
+
}
|
|
1375
|
+
.log-agent pre {
|
|
1376
|
+
margin: 0;
|
|
1377
|
+
padding: 12px 14px;
|
|
1378
|
+
overflow-x: auto;
|
|
1379
|
+
font-family: var(--font-mono);
|
|
1380
|
+
font-size: 12px;
|
|
1381
|
+
line-height: 1.5;
|
|
1382
|
+
color: #f1f5f9;
|
|
1383
|
+
background: transparent;
|
|
1005
1384
|
}
|
|
1006
|
-
.
|
|
1007
|
-
|
|
1385
|
+
.log-agent code {
|
|
1386
|
+
font-family: var(--font-mono);
|
|
1387
|
+
font-size: 12px;
|
|
1008
1388
|
}
|
|
1009
|
-
.
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1389
|
+
.log-agent p code, .log-agent li code {
|
|
1390
|
+
background: var(--bg-surface-subtle);
|
|
1391
|
+
color: #0f766e;
|
|
1392
|
+
border: 1px solid var(--border-subtle);
|
|
1393
|
+
padding: 1px 5px;
|
|
1394
|
+
border-radius: 4px;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
/* Shimmering Pulsing Dots for Streaming */
|
|
1398
|
+
.agent-typing-indicator {
|
|
1399
|
+
display: inline-flex;
|
|
1014
1400
|
align-items: center;
|
|
1015
|
-
gap:
|
|
1401
|
+
gap: 5px;
|
|
1402
|
+
padding: 6px 12px;
|
|
1403
|
+
background: var(--bg-surface);
|
|
1404
|
+
border: 1px solid var(--border-subtle);
|
|
1405
|
+
border-radius: 12px;
|
|
1406
|
+
margin-top: 4px;
|
|
1407
|
+
width: fit-content;
|
|
1016
1408
|
}
|
|
1017
|
-
.
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
color: var(--ok-text);
|
|
1024
|
-
border: 1px solid var(--ok-border);
|
|
1409
|
+
.typing-dot {
|
|
1410
|
+
width: 6px;
|
|
1411
|
+
height: 6px;
|
|
1412
|
+
border-radius: 50%;
|
|
1413
|
+
background: var(--brand-primary);
|
|
1414
|
+
animation: pulseDot 1.4s infinite ease-in-out both;
|
|
1025
1415
|
}
|
|
1026
|
-
.
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1416
|
+
.typing-dot:nth-child(1) { animation-delay: -0.32s; }
|
|
1417
|
+
.typing-dot:nth-child(2) { animation-delay: -0.16s; }
|
|
1418
|
+
.typing-dot:nth-child(3) { animation-delay: 0s; }
|
|
1419
|
+
@keyframes pulseDot {
|
|
1420
|
+
0%, 80%, 100% { transform: scale(0.6); opacity: 0.35; }
|
|
1421
|
+
40% { transform: scale(1.1); opacity: 1; }
|
|
1030
1422
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1423
|
+
|
|
1424
|
+
/* System & Info Messages */
|
|
1425
|
+
.log-sys {
|
|
1034
1426
|
color: var(--text-muted);
|
|
1035
|
-
|
|
1036
|
-
|
|
1427
|
+
font-size: 12px;
|
|
1428
|
+
background: var(--bg-surface-subtle);
|
|
1429
|
+
border: 1px dashed var(--border-default);
|
|
1430
|
+
padding: 8px 12px;
|
|
1037
1431
|
border-radius: var(--radius-sm);
|
|
1038
|
-
|
|
1432
|
+
text-align: center;
|
|
1433
|
+
width: 100%;
|
|
1039
1434
|
}
|
|
1040
|
-
.
|
|
1041
|
-
|
|
1042
|
-
|
|
1435
|
+
.wake-checklist-card {
|
|
1436
|
+
background: var(--bg-surface);
|
|
1437
|
+
border: 1px solid var(--brand-primary-border);
|
|
1438
|
+
border-left: 3px solid var(--brand-primary);
|
|
1439
|
+
border-radius: var(--radius-sm);
|
|
1440
|
+
padding: 10px 14px;
|
|
1441
|
+
text-align: left;
|
|
1043
1442
|
}
|
|
1443
|
+
|
|
1444
|
+
/* Quick Action Chips */
|
|
1044
1445
|
.console-quick-chips {
|
|
1045
1446
|
display: flex;
|
|
1046
1447
|
align-items: center;
|
|
1047
1448
|
gap: 6px;
|
|
1048
|
-
padding: 8px
|
|
1049
|
-
background: var(--bg-surface
|
|
1050
|
-
border-
|
|
1449
|
+
padding: 8px 16px;
|
|
1450
|
+
background: var(--bg-surface);
|
|
1451
|
+
border-top: 1px solid var(--border-subtle);
|
|
1051
1452
|
overflow-x: auto;
|
|
1453
|
+
max-width: 860px;
|
|
1454
|
+
margin: 0 auto;
|
|
1455
|
+
width: 100%;
|
|
1052
1456
|
}
|
|
1053
1457
|
.chip {
|
|
1054
1458
|
font-family: var(--font-mono);
|
|
1055
1459
|
font-size: 11px;
|
|
1056
|
-
background: var(--bg-surface);
|
|
1460
|
+
background: var(--bg-surface-subtle);
|
|
1057
1461
|
color: var(--text-secondary);
|
|
1058
|
-
border: 1px solid var(--border-
|
|
1059
|
-
padding: 3px
|
|
1060
|
-
border-radius:
|
|
1462
|
+
border: 1px solid var(--border-subtle);
|
|
1463
|
+
padding: 3px 9px;
|
|
1464
|
+
border-radius: 999px;
|
|
1061
1465
|
cursor: pointer;
|
|
1062
1466
|
white-space: nowrap;
|
|
1063
|
-
transition:
|
|
1467
|
+
transition: all 0.15s ease;
|
|
1468
|
+
display: inline-flex;
|
|
1469
|
+
align-items: center;
|
|
1470
|
+
gap: 4px;
|
|
1064
1471
|
}
|
|
1065
1472
|
.chip:hover {
|
|
1066
1473
|
background: var(--brand-primary-light);
|
|
1067
1474
|
border-color: var(--brand-primary-border);
|
|
1068
1475
|
color: var(--brand-primary);
|
|
1069
1476
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
line-height: 1.55;
|
|
1077
|
-
display: flex;
|
|
1078
|
-
flex-direction: column;
|
|
1079
|
-
gap: 12px;
|
|
1080
|
-
background: var(--bg-app);
|
|
1477
|
+
|
|
1478
|
+
/* Modern Textarea Input Box (Gemini / Codex Style) */
|
|
1479
|
+
.console-input-wrap {
|
|
1480
|
+
background: var(--bg-surface);
|
|
1481
|
+
border-top: 1px solid var(--border-subtle);
|
|
1482
|
+
padding: 12px 16px 14px;
|
|
1081
1483
|
}
|
|
1082
|
-
.
|
|
1484
|
+
.console-input-container {
|
|
1485
|
+
max-width: 860px;
|
|
1486
|
+
margin: 0 auto;
|
|
1083
1487
|
display: flex;
|
|
1084
1488
|
flex-direction: column;
|
|
1085
|
-
gap:
|
|
1086
|
-
max-width: 92%;
|
|
1087
|
-
}
|
|
1088
|
-
.log-entry.user {
|
|
1089
|
-
align-self: flex-end;
|
|
1090
|
-
align-items: flex-end;
|
|
1091
|
-
}
|
|
1092
|
-
.log-entry.agent,
|
|
1093
|
-
.log-entry.sys {
|
|
1094
|
-
align-self: flex-start;
|
|
1095
|
-
align-items: flex-start;
|
|
1096
|
-
}
|
|
1097
|
-
.log-user {
|
|
1098
|
-
color: #fff;
|
|
1099
|
-
font-weight: 500;
|
|
1100
|
-
background: var(--brand-primary);
|
|
1101
|
-
padding: 10px 12px;
|
|
1102
|
-
border-radius: 12px 12px 4px 12px;
|
|
1103
|
-
white-space: pre-wrap;
|
|
1104
|
-
word-break: break-word;
|
|
1105
|
-
box-shadow: var(--shadow-xs);
|
|
1106
|
-
}
|
|
1107
|
-
.log-agent {
|
|
1108
|
-
color: var(--text-main);
|
|
1109
|
-
background: var(--bg-surface);
|
|
1110
|
-
padding: 10px 12px;
|
|
1111
|
-
border-radius: 12px 12px 12px 4px;
|
|
1112
|
-
border: 1px solid var(--border-subtle);
|
|
1113
|
-
white-space: pre-wrap;
|
|
1114
|
-
word-break: break-word;
|
|
1115
|
-
box-shadow: var(--shadow-xs);
|
|
1116
|
-
}
|
|
1117
|
-
.log-sys {
|
|
1118
|
-
color: var(--text-muted);
|
|
1119
|
-
font-style: normal;
|
|
1120
|
-
font-size: 12px;
|
|
1121
|
-
background: transparent;
|
|
1122
|
-
padding: 2px 0;
|
|
1489
|
+
gap: 6px;
|
|
1123
1490
|
}
|
|
1124
1491
|
.console-input-box {
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
border-
|
|
1492
|
+
background: var(--bg-surface-subtle);
|
|
1493
|
+
border: 1.5px solid var(--border-default);
|
|
1494
|
+
border-radius: var(--radius-lg);
|
|
1495
|
+
padding: 8px 12px;
|
|
1128
1496
|
display: flex;
|
|
1497
|
+
align-items: flex-end;
|
|
1129
1498
|
gap: 8px;
|
|
1499
|
+
transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
|
|
1500
|
+
}
|
|
1501
|
+
.console-input-box:focus-within {
|
|
1502
|
+
background: var(--bg-surface);
|
|
1503
|
+
border-color: var(--brand-primary);
|
|
1504
|
+
box-shadow: 0 0 0 3px var(--brand-primary-border);
|
|
1130
1505
|
}
|
|
1131
|
-
.console-
|
|
1506
|
+
.console-textarea {
|
|
1132
1507
|
flex: 1;
|
|
1133
|
-
background:
|
|
1134
|
-
border:
|
|
1135
|
-
color: var(--text-main);
|
|
1136
|
-
padding: 10px 12px;
|
|
1137
|
-
font-size: 13px;
|
|
1138
|
-
border-radius: var(--radius-md);
|
|
1508
|
+
background: transparent;
|
|
1509
|
+
border: none;
|
|
1139
1510
|
outline: none;
|
|
1511
|
+
resize: none;
|
|
1140
1512
|
font-family: var(--font-sans);
|
|
1513
|
+
font-size: 13.5px;
|
|
1514
|
+
line-height: 1.5;
|
|
1515
|
+
color: var(--text-main);
|
|
1516
|
+
min-height: 24px;
|
|
1517
|
+
max-height: 160px;
|
|
1518
|
+
padding: 4px 0;
|
|
1141
1519
|
}
|
|
1142
|
-
.console-
|
|
1143
|
-
|
|
1144
|
-
background: var(--bg-surface);
|
|
1145
|
-
box-shadow: 0 0 0 3px var(--brand-primary-border);
|
|
1520
|
+
.console-textarea::placeholder {
|
|
1521
|
+
color: var(--text-muted);
|
|
1146
1522
|
}
|
|
1147
1523
|
.console-send-btn {
|
|
1148
1524
|
background: var(--brand-primary);
|
|
1149
|
-
color: #
|
|
1525
|
+
color: #ffffff;
|
|
1150
1526
|
border: none;
|
|
1151
|
-
|
|
1527
|
+
width: 32px;
|
|
1528
|
+
height: 32px;
|
|
1152
1529
|
border-radius: var(--radius-md);
|
|
1153
|
-
font-size: 13px;
|
|
1154
|
-
font-weight: 600;
|
|
1155
1530
|
cursor: pointer;
|
|
1156
|
-
display:
|
|
1157
|
-
|
|
1158
|
-
|
|
1531
|
+
display: grid;
|
|
1532
|
+
place-items: center;
|
|
1533
|
+
flex-shrink: 0;
|
|
1534
|
+
transition: background 0.15s ease, transform 0.1s ease;
|
|
1535
|
+
margin-bottom: 2px;
|
|
1159
1536
|
}
|
|
1160
|
-
.console-send-btn:hover {
|
|
1537
|
+
.console-send-btn:hover:not(:disabled) {
|
|
1161
1538
|
background: var(--brand-primary-hover);
|
|
1539
|
+
transform: translateY(-1px);
|
|
1162
1540
|
}
|
|
1163
|
-
.
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1541
|
+
.console-send-btn:disabled {
|
|
1542
|
+
opacity: 0.45;
|
|
1543
|
+
cursor: not-allowed;
|
|
1544
|
+
}
|
|
1545
|
+
.console-input-footer {
|
|
1546
|
+
display: flex;
|
|
1547
|
+
align-items: center;
|
|
1548
|
+
justify-content: space-between;
|
|
1549
|
+
padding: 0 4px;
|
|
1550
|
+
font-size: 11px;
|
|
1551
|
+
color: var(--text-muted);
|
|
1168
1552
|
}
|
|
1169
|
-
@keyframes blink { 50% { opacity: 0; } }
|
|
1170
1553
|
.wake-option-list {
|
|
1171
1554
|
display: grid;
|
|
1172
1555
|
gap: 8px;
|
|
@@ -1280,7 +1663,6 @@
|
|
|
1280
1663
|
.viewer { min-height: 480px; }
|
|
1281
1664
|
.provider-grid, .cost-metrics { grid-template-columns: 1fr; }
|
|
1282
1665
|
.topbar { padding: 0 14px; }
|
|
1283
|
-
.console-drawer { width: 100vw; right: 0; }
|
|
1284
1666
|
}
|
|
1285
1667
|
</style>
|
|
1286
1668
|
</head>
|
|
@@ -1305,9 +1687,9 @@
|
|
|
1305
1687
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg>
|
|
1306
1688
|
/plan 方案
|
|
1307
1689
|
</button>
|
|
1308
|
-
<button id="cmd-verify-btn" class="topbar-btn" title="
|
|
1690
|
+
<button id="cmd-verify-btn" class="topbar-btn" title="AI 核查清单;人审在此核实 (/crosscheck)">
|
|
1309
1691
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
|
|
1310
|
-
/
|
|
1692
|
+
/crosscheck
|
|
1311
1693
|
</button>
|
|
1312
1694
|
</div>
|
|
1313
1695
|
<div class="local-badge">
|
|
@@ -1320,32 +1702,37 @@
|
|
|
1320
1702
|
<!-- 主体工作区 Layout -->
|
|
1321
1703
|
<div class="layout">
|
|
1322
1704
|
<!-- 侧边导航栏 Sidebar -->
|
|
1323
|
-
<nav class="nav" aria-label="Panel 导航">
|
|
1705
|
+
<nav class="nav" id="workbench-nav" aria-label="Panel 导航">
|
|
1324
1706
|
<div class="nav-group">
|
|
1325
|
-
<div class="nav-
|
|
1326
|
-
|
|
1707
|
+
<div class="nav-header">
|
|
1708
|
+
<div class="nav-label">工作台导航</div>
|
|
1709
|
+
<button id="nav-toggle-btn" class="nav-toggle-btn" title="折叠/展开导航栏" aria-label="折叠导航栏">
|
|
1710
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
|
|
1711
|
+
</button>
|
|
1712
|
+
</div>
|
|
1713
|
+
<button class="active" data-view="project" title="项目文件">
|
|
1327
1714
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|
1328
|
-
|
|
1715
|
+
<span class="nav-btn-text">项目文件</span>
|
|
1329
1716
|
</button>
|
|
1330
|
-
<button data-view="ecosystem">
|
|
1717
|
+
<button data-view="ecosystem" title="能力生态">
|
|
1331
1718
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
|
|
1332
|
-
|
|
1719
|
+
<span class="nav-btn-text">能力生态</span>
|
|
1333
1720
|
</button>
|
|
1334
|
-
<button data-view="provider">
|
|
1721
|
+
<button data-view="provider" title="模型与成本">
|
|
1335
1722
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
|
1336
|
-
|
|
1723
|
+
<span class="nav-btn-text">模型与成本</span>
|
|
1337
1724
|
</button>
|
|
1338
|
-
<button data-view="help">
|
|
1725
|
+
<button data-view="help" title="使用速览">
|
|
1339
1726
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
|
1340
|
-
|
|
1727
|
+
<span class="nav-btn-text">使用速览</span>
|
|
1341
1728
|
</button>
|
|
1342
|
-
<button data-view="checklist">
|
|
1729
|
+
<button data-view="checklist" title="核对清单">
|
|
1343
1730
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
|
|
1344
|
-
|
|
1731
|
+
<span class="nav-btn-text">核对清单</span>
|
|
1345
1732
|
</button>
|
|
1346
|
-
<button data-view="chat">
|
|
1733
|
+
<button data-view="chat" title="对话">
|
|
1347
1734
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
|
1348
|
-
|
|
1735
|
+
<span class="nav-btn-text">对话</span>
|
|
1349
1736
|
</button>
|
|
1350
1737
|
</div>
|
|
1351
1738
|
<div class="nav-footer">
|
|
@@ -1548,11 +1935,12 @@
|
|
|
1548
1935
|
</section>
|
|
1549
1936
|
|
|
1550
1937
|
<section id="view-help" class="view">
|
|
1551
|
-
<div class="
|
|
1938
|
+
<div class="help-hero">
|
|
1552
1939
|
<div>
|
|
1553
1940
|
<h1 id="help-title">使用速览</h1>
|
|
1554
|
-
<p id="help-
|
|
1941
|
+
<p id="help-subtitle">三种模式 · AI 交叉核验 · 内置学术工作流</p>
|
|
1555
1942
|
</div>
|
|
1943
|
+
<div id="help-thinking" class="help-kbd">加载中…</div>
|
|
1556
1944
|
</div>
|
|
1557
1945
|
<div class="help-grid" id="help-modes"></div>
|
|
1558
1946
|
<div class="help-block">
|
|
@@ -1573,11 +1961,11 @@
|
|
|
1573
1961
|
<div class="page-head">
|
|
1574
1962
|
<div>
|
|
1575
1963
|
<h1>交叉核验清单</h1>
|
|
1576
|
-
<p
|
|
1964
|
+
<p>AI 用 <code>/crosscheck</code> 核查字段;<strong>analysis / academic 收尾必须在此点「核实」</strong>(或终端 <code>/crosscheck <id> human</code>)。AI 已核与跳过都不算通过。</p>
|
|
1577
1965
|
</div>
|
|
1578
1966
|
<div style="display:flex;gap:8px">
|
|
1579
1967
|
<button id="refresh-checklist" class="button">刷新</button>
|
|
1580
|
-
<button id="skip-checklist" class="button" title="
|
|
1968
|
+
<button id="skip-checklist" class="button" title="标为跳过;不解除 analysis/academic 人审门禁">跳过未核项</button>
|
|
1581
1969
|
</div>
|
|
1582
1970
|
</div>
|
|
1583
1971
|
<div class="panel section">
|
|
@@ -1593,62 +1981,79 @@
|
|
|
1593
1981
|
</section>
|
|
1594
1982
|
|
|
1595
1983
|
<section id="view-chat" class="view">
|
|
1596
|
-
<div class="page-head">
|
|
1984
|
+
<div class="page-head" style="margin-bottom: 12px;">
|
|
1597
1985
|
<div>
|
|
1598
1986
|
<h1>交互对话</h1>
|
|
1599
|
-
<p
|
|
1987
|
+
<p>提问将接入当前 PsyClaw 会话;助手回复经 SSE 流式同步,支持学术指令与「唤醒选项」决策。</p>
|
|
1600
1988
|
</div>
|
|
1601
1989
|
</div>
|
|
1602
|
-
<div id="chat-console-host" class="panel section" style="min-height:
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
<
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
</
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
<
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
<span>对话</span>
|
|
1620
|
-
<span id="console-status-badge" class="console-status-tag">已连接</span>
|
|
1621
|
-
</div>
|
|
1622
|
-
<div class="console-actions">
|
|
1623
|
-
<button id="console-clear-btn" class="console-btn-icon" title="清空对话">
|
|
1624
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
|
|
1625
|
-
</button>
|
|
1626
|
-
<button id="console-close-btn" class="console-btn-icon" title="最小化">
|
|
1627
|
-
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
1628
|
-
</button>
|
|
1629
|
-
</div>
|
|
1630
|
-
</div>
|
|
1990
|
+
<div id="chat-console-host" class="panel section" style="min-height:74vh;padding:0;overflow:hidden;display:flex;flex-direction:column;border-radius:var(--radius-md);">
|
|
1991
|
+
<div id="console-drawer" class="console-drawer">
|
|
1992
|
+
<div class="console-header">
|
|
1993
|
+
<div class="console-title">
|
|
1994
|
+
<span class="agent-avatar" style="width:24px;height:24px;font-size:12px">ψ</span>
|
|
1995
|
+
<span>PsyClaw Research Assistant</span>
|
|
1996
|
+
<span id="console-status-badge" class="console-status-tag">
|
|
1997
|
+
<span class="pulse-dot" style="width:5px;height:5px;"></span>
|
|
1998
|
+
已连接
|
|
1999
|
+
</span>
|
|
2000
|
+
</div>
|
|
2001
|
+
<div class="console-actions">
|
|
2002
|
+
<button id="console-clear-btn" class="console-btn-icon" title="清空对话记录">
|
|
2003
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
|
|
2004
|
+
</button>
|
|
2005
|
+
</div>
|
|
2006
|
+
</div>
|
|
1631
2007
|
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
2008
|
+
<div id="console-log" class="console-log">
|
|
2009
|
+
<div class="log-entry sys">
|
|
2010
|
+
<div class="log-sys">
|
|
2011
|
+
💡 <strong>对话已就绪</strong>:与 PsyClaw 智能体安全连接。支持 <code>/init</code>、<code>/plan</code>、<code>/grill</code>、<code>/crosscheck</code>(AI 核验)等指令。
|
|
2012
|
+
</div>
|
|
2013
|
+
</div>
|
|
2014
|
+
</div>
|
|
1639
2015
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
2016
|
+
<div class="console-quick-chips">
|
|
2017
|
+
<span class="chip" data-cmd="/plan status">
|
|
2018
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg>
|
|
2019
|
+
/plan status
|
|
2020
|
+
</span>
|
|
2021
|
+
<span class="chip" data-cmd="/crosscheck list">
|
|
2022
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/></svg>
|
|
2023
|
+
/crosscheck list
|
|
2024
|
+
</span>
|
|
2025
|
+
<span class="chip" data-cmd="/grill">
|
|
2026
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/></svg>
|
|
2027
|
+
/grill 压力追问
|
|
2028
|
+
</span>
|
|
2029
|
+
<span class="chip" data-cmd="/review">
|
|
2030
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/></svg>
|
|
2031
|
+
/review 评审
|
|
2032
|
+
</span>
|
|
2033
|
+
<span class="chip" data-cmd="/agents">
|
|
2034
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>
|
|
2035
|
+
/agents 角色
|
|
2036
|
+
</span>
|
|
2037
|
+
</div>
|
|
1645
2038
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
2039
|
+
<div class="console-input-wrap">
|
|
2040
|
+
<div class="console-input-container">
|
|
2041
|
+
<div class="console-input-box">
|
|
2042
|
+
<textarea id="console-input" class="console-textarea" placeholder="输入研究问题或指令(Enter 发送,Shift+Enter 换行)…" rows="1"></textarea>
|
|
2043
|
+
<button id="console-send-btn" class="console-send-btn" title="发送消息 (Enter)">
|
|
2044
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
|
|
2045
|
+
</button>
|
|
2046
|
+
</div>
|
|
2047
|
+
<div class="console-input-footer">
|
|
2048
|
+
<span>支持 Markdown 与学术指令</span>
|
|
2049
|
+
<span>PsyClaw 本地隔离环境</span>
|
|
2050
|
+
</div>
|
|
2051
|
+
</div>
|
|
2052
|
+
</div>
|
|
2053
|
+
</div>
|
|
2054
|
+
</div>
|
|
2055
|
+
</section>
|
|
2056
|
+
</main>
|
|
1652
2057
|
</div>
|
|
1653
2058
|
</div>
|
|
1654
2059
|
|
|
@@ -1750,24 +2155,38 @@ function setView(view) {
|
|
|
1750
2155
|
if (view === "provider") loadProvider();
|
|
1751
2156
|
if (view === "checklist") loadChecklist();
|
|
1752
2157
|
if (view === "help") loadHelp();
|
|
1753
|
-
if (view === "chat")
|
|
1754
|
-
else restoreConsoleDrawer();
|
|
2158
|
+
if (view === "chat") queueMicrotask(() => $("console-input")?.focus());
|
|
1755
2159
|
}
|
|
1756
2160
|
|
|
1757
2161
|
async function loadHelp() {
|
|
1758
2162
|
try {
|
|
1759
2163
|
const doc = await json("/api/help");
|
|
1760
2164
|
$("help-title").textContent = doc.title || "使用速览";
|
|
2165
|
+
$("help-subtitle").textContent = doc.subtitle || "";
|
|
1761
2166
|
$("help-thinking").textContent = doc.thinking || "";
|
|
1762
2167
|
$("help-modes").innerHTML = (doc.modes || []).map(mode => `
|
|
1763
2168
|
<article class="help-mode-card">
|
|
1764
|
-
<div class="mode-id">${esc(mode.
|
|
2169
|
+
<div class="mode-id">${esc(mode.hint || mode.id)}</div>
|
|
2170
|
+
<div class="mode-label">${esc(mode.label || mode.id)}</div>
|
|
1765
2171
|
<p>${esc(mode.blurb)}</p>
|
|
1766
2172
|
</article>
|
|
1767
2173
|
`).join("");
|
|
1768
|
-
$("help-steps").innerHTML = (doc.steps || []).map(step =>
|
|
1769
|
-
|
|
1770
|
-
|
|
2174
|
+
$("help-steps").innerHTML = (doc.steps || []).map((step, index) =>
|
|
2175
|
+
`<li data-step="${index + 1}">${esc(step)}</li>`
|
|
2176
|
+
).join("");
|
|
2177
|
+
const groups = new Map();
|
|
2178
|
+
for (const row of (doc.commands || [])) {
|
|
2179
|
+
const key = row.group || "其他";
|
|
2180
|
+
if (!groups.has(key)) groups.set(key, []);
|
|
2181
|
+
groups.get(key).push(row);
|
|
2182
|
+
}
|
|
2183
|
+
$("help-commands").innerHTML = [...groups.entries()].map(([group, rows]) => `
|
|
2184
|
+
<div class="help-cmd-group">
|
|
2185
|
+
<h3>${esc(group)}</h3>
|
|
2186
|
+
<div class="help-cmd-list">
|
|
2187
|
+
${rows.map(row => `<div class="help-cmd"><code>${esc(row.cmd)}</code><span>${esc(row.blurb)}</span></div>`).join("")}
|
|
2188
|
+
</div>
|
|
2189
|
+
</div>
|
|
1771
2190
|
`).join("");
|
|
1772
2191
|
$("help-notes").innerHTML = (doc.notes || []).map(note => `<li>${esc(note)}</li>`).join("");
|
|
1773
2192
|
} catch (error) {
|
|
@@ -1775,37 +2194,6 @@ async function loadHelp() {
|
|
|
1775
2194
|
}
|
|
1776
2195
|
}
|
|
1777
2196
|
|
|
1778
|
-
function mountConsoleInChat() {
|
|
1779
|
-
const host = $("chat-console-host");
|
|
1780
|
-
const drawer = $("console-drawer");
|
|
1781
|
-
if (!host || !drawer) return;
|
|
1782
|
-
host.appendChild(drawer);
|
|
1783
|
-
drawer.classList.add("open", "embedded");
|
|
1784
|
-
drawer.style.position = "relative";
|
|
1785
|
-
drawer.style.inset = "auto";
|
|
1786
|
-
drawer.style.width = "100%";
|
|
1787
|
-
drawer.style.height = "100%";
|
|
1788
|
-
drawer.style.minHeight = "58vh";
|
|
1789
|
-
drawer.style.boxShadow = "none";
|
|
1790
|
-
drawer.style.borderRadius = "0";
|
|
1791
|
-
drawer.style.transform = "none";
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
function restoreConsoleDrawer() {
|
|
1795
|
-
const drawer = $("console-drawer");
|
|
1796
|
-
if (!drawer || drawer.parentElement === document.body) return;
|
|
1797
|
-
document.body.appendChild(drawer);
|
|
1798
|
-
drawer.classList.remove("embedded");
|
|
1799
|
-
drawer.style.position = "";
|
|
1800
|
-
drawer.style.inset = "";
|
|
1801
|
-
drawer.style.width = "";
|
|
1802
|
-
drawer.style.height = "";
|
|
1803
|
-
drawer.style.minHeight = "";
|
|
1804
|
-
drawer.style.boxShadow = "";
|
|
1805
|
-
drawer.style.borderRadius = "";
|
|
1806
|
-
drawer.style.transform = "";
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
2197
|
async function loadChecklist() {
|
|
1810
2198
|
const body = $("checklist-body");
|
|
1811
2199
|
if (!body) return;
|
|
@@ -1845,7 +2233,7 @@ async function loadChecklist() {
|
|
|
1845
2233
|
|
|
1846
2234
|
$("refresh-checklist")?.addEventListener("click", loadChecklist);
|
|
1847
2235
|
$("skip-checklist")?.addEventListener("click", async () => {
|
|
1848
|
-
if (!confirm("
|
|
2236
|
+
if (!confirm("将把未核/AI已核项标为跳过。注意:这不会解除 analysis/academic 收尾人审门禁。继续?")) return;
|
|
1849
2237
|
await json("/api/crosscheck", {
|
|
1850
2238
|
method: "POST",
|
|
1851
2239
|
headers: { "content-type": "application/json" },
|
|
@@ -1854,7 +2242,7 @@ $("skip-checklist")?.addEventListener("click", async () => {
|
|
|
1854
2242
|
await loadChecklist();
|
|
1855
2243
|
});
|
|
1856
2244
|
|
|
1857
|
-
document.querySelectorAll(".nav button").forEach(button => {
|
|
2245
|
+
document.querySelectorAll(".nav button[data-view]").forEach(button => {
|
|
1858
2246
|
button.addEventListener("click", () => setView(button.dataset.view));
|
|
1859
2247
|
});
|
|
1860
2248
|
|
|
@@ -1873,16 +2261,20 @@ function inlineMarkdown(text) {
|
|
|
1873
2261
|
|
|
1874
2262
|
function renderMarkdown(markdown) {
|
|
1875
2263
|
const lines = String(markdown).replace(/\r\n/g, "\n").split("\n"), out = [];
|
|
1876
|
-
let i = 0, inCode = false, code = [];
|
|
2264
|
+
let i = 0, inCode = false, codeLang = "", code = [];
|
|
1877
2265
|
while (i < lines.length) {
|
|
1878
2266
|
const line = lines[i], trim = line.trim();
|
|
1879
2267
|
if (trim.startsWith("```")) {
|
|
1880
2268
|
if (inCode) {
|
|
1881
|
-
|
|
2269
|
+
const rawCode = code.join("\n");
|
|
2270
|
+
const langDisplay = codeLang || "code";
|
|
2271
|
+
out.push(`<div class="code-container"><div class="code-header"><span>${esc(langDisplay)}</span><button type="button" class="code-copy-btn" data-code="${esc(rawCode)}"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg><span>复制</span></button></div><pre><code>${esc(rawCode)}</code></pre></div>`);
|
|
1882
2272
|
code = [];
|
|
2273
|
+
codeLang = "";
|
|
1883
2274
|
inCode = false;
|
|
1884
2275
|
} else {
|
|
1885
2276
|
inCode = true;
|
|
2277
|
+
codeLang = trim.slice(3).trim();
|
|
1886
2278
|
}
|
|
1887
2279
|
i++;
|
|
1888
2280
|
continue;
|
|
@@ -1942,7 +2334,11 @@ function renderMarkdown(markdown) {
|
|
|
1942
2334
|
}
|
|
1943
2335
|
out.push(`<p>${inlineMarkdown(para.join(" "))}</p>`);
|
|
1944
2336
|
}
|
|
1945
|
-
if (inCode)
|
|
2337
|
+
if (inCode) {
|
|
2338
|
+
const rawCode = code.join("\n");
|
|
2339
|
+
const langDisplay = codeLang || "code";
|
|
2340
|
+
out.push(`<div class="code-container"><div class="code-header"><span>${esc(langDisplay)}</span><button type="button" class="code-copy-btn" data-code="${esc(rawCode)}"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg><span>复制</span></button></div><pre><code>${esc(rawCode)}</code></pre></div>`);
|
|
2341
|
+
}
|
|
1946
2342
|
return out.join("");
|
|
1947
2343
|
}
|
|
1948
2344
|
|
|
@@ -2343,8 +2739,6 @@ document.querySelectorAll(".step-item").forEach(item => {
|
|
|
2343
2739
|
});
|
|
2344
2740
|
|
|
2345
2741
|
/* --- 交互对话 + SSE + 唤醒选项 --- */
|
|
2346
|
-
const consoleDrawer = $("console-drawer");
|
|
2347
|
-
const consoleFab = $("console-fab");
|
|
2348
2742
|
const consoleLog = $("console-log");
|
|
2349
2743
|
const consoleInput = $("console-input");
|
|
2350
2744
|
const streamBubbles = new Map();
|
|
@@ -2352,12 +2746,8 @@ let lastLocalUserText = "";
|
|
|
2352
2746
|
let wakeState = null;
|
|
2353
2747
|
|
|
2354
2748
|
function openConsole() {
|
|
2355
|
-
|
|
2356
|
-
consoleInput
|
|
2357
|
-
}
|
|
2358
|
-
|
|
2359
|
-
function closeConsole() {
|
|
2360
|
-
consoleDrawer.classList.remove("open");
|
|
2749
|
+
setView("chat");
|
|
2750
|
+
queueMicrotask(() => consoleInput?.focus());
|
|
2361
2751
|
}
|
|
2362
2752
|
|
|
2363
2753
|
function openConsoleWithMessage(text) {
|
|
@@ -2369,9 +2759,22 @@ function appendLog(role, text) {
|
|
|
2369
2759
|
const entry = document.createElement("div");
|
|
2370
2760
|
entry.className = `log-entry ${role}`;
|
|
2371
2761
|
if (role === "user") {
|
|
2372
|
-
entry.innerHTML =
|
|
2762
|
+
entry.innerHTML = `
|
|
2763
|
+
<div class="log-user-wrap">
|
|
2764
|
+
<div class="log-user">${esc(text)}</div>
|
|
2765
|
+
</div>
|
|
2766
|
+
`;
|
|
2373
2767
|
} else if (role === "agent") {
|
|
2374
|
-
entry.innerHTML =
|
|
2768
|
+
entry.innerHTML = `
|
|
2769
|
+
<div class="agent-avatar">ψ</div>
|
|
2770
|
+
<div class="agent-content-wrap">
|
|
2771
|
+
<div class="agent-meta">
|
|
2772
|
+
<span>PsyClaw Assistant</span>
|
|
2773
|
+
<span class="agent-role-pill">Core</span>
|
|
2774
|
+
</div>
|
|
2775
|
+
<div class="log-agent">${renderMarkdown(text)}</div>
|
|
2776
|
+
</div>
|
|
2777
|
+
`;
|
|
2375
2778
|
} else {
|
|
2376
2779
|
entry.innerHTML = `<div class="log-sys">${esc(text)}</div>`;
|
|
2377
2780
|
}
|
|
@@ -2386,7 +2789,21 @@ function ensureStreamBubble(messageId) {
|
|
|
2386
2789
|
entry = document.createElement("div");
|
|
2387
2790
|
entry.className = "log-entry agent";
|
|
2388
2791
|
entry.dataset.messageId = messageId;
|
|
2389
|
-
entry.innerHTML =
|
|
2792
|
+
entry.innerHTML = `
|
|
2793
|
+
<div class="agent-avatar">ψ</div>
|
|
2794
|
+
<div class="agent-content-wrap">
|
|
2795
|
+
<div class="agent-meta">
|
|
2796
|
+
<span>PsyClaw Assistant</span>
|
|
2797
|
+
<span class="agent-role-pill">Streaming</span>
|
|
2798
|
+
</div>
|
|
2799
|
+
<div class="log-agent" style="display:none"></div>
|
|
2800
|
+
<div class="agent-typing-indicator">
|
|
2801
|
+
<span class="typing-dot"></span>
|
|
2802
|
+
<span class="typing-dot"></span>
|
|
2803
|
+
<span class="typing-dot"></span>
|
|
2804
|
+
</div>
|
|
2805
|
+
</div>
|
|
2806
|
+
`;
|
|
2390
2807
|
consoleLog.appendChild(entry);
|
|
2391
2808
|
streamBubbles.set(messageId, entry);
|
|
2392
2809
|
consoleLog.scrollTop = consoleLog.scrollHeight;
|
|
@@ -2396,9 +2813,24 @@ function ensureStreamBubble(messageId) {
|
|
|
2396
2813
|
function updateStreamBubble(messageId, text, done) {
|
|
2397
2814
|
const entry = ensureStreamBubble(messageId);
|
|
2398
2815
|
const bubble = entry.querySelector(".log-agent");
|
|
2816
|
+
const indicator = entry.querySelector(".agent-typing-indicator");
|
|
2817
|
+
const pill = entry.querySelector(".agent-role-pill");
|
|
2399
2818
|
if (!bubble) return;
|
|
2400
|
-
|
|
2401
|
-
|
|
2819
|
+
|
|
2820
|
+
if (text) {
|
|
2821
|
+
bubble.style.display = "block";
|
|
2822
|
+
bubble.innerHTML = renderMarkdown(text);
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
if (done) {
|
|
2826
|
+
if (indicator) indicator.remove();
|
|
2827
|
+
if (pill) pill.textContent = "Answered";
|
|
2828
|
+
bubble.style.display = "block";
|
|
2829
|
+
} else {
|
|
2830
|
+
if (text && indicator) {
|
|
2831
|
+
indicator.style.display = "none";
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2402
2834
|
consoleLog.scrollTop = consoleLog.scrollHeight;
|
|
2403
2835
|
}
|
|
2404
2836
|
|
|
@@ -2450,7 +2882,10 @@ function connectAssistantStream() {
|
|
|
2450
2882
|
es.addEventListener("wake_options", (ev) => {
|
|
2451
2883
|
try {
|
|
2452
2884
|
const data = JSON.parse(ev.data);
|
|
2453
|
-
if (data.prompt)
|
|
2885
|
+
if (data.prompt) {
|
|
2886
|
+
appendWakeChecklist(data.prompt);
|
|
2887
|
+
showWakeModal(data.prompt, { switchChecklist: false });
|
|
2888
|
+
}
|
|
2454
2889
|
} catch { /* ignore */ }
|
|
2455
2890
|
});
|
|
2456
2891
|
es.addEventListener("wake_options_resolved", (ev) => {
|
|
@@ -2466,8 +2901,32 @@ function connectAssistantStream() {
|
|
|
2466
2901
|
es.onerror = () => setConsoleStatus("重连中", false);
|
|
2467
2902
|
}
|
|
2468
2903
|
|
|
2469
|
-
function
|
|
2470
|
-
|
|
2904
|
+
function appendWakeChecklist(prompt) {
|
|
2905
|
+
if (!prompt || prompt.mode !== "checklist") return;
|
|
2906
|
+
const existing = document.querySelector(`[data-wake-checklist-id="${CSS.escape(prompt.id)}"]`);
|
|
2907
|
+
if (existing) return;
|
|
2908
|
+
const entry = document.createElement("div");
|
|
2909
|
+
entry.className = "log-entry sys";
|
|
2910
|
+
entry.dataset.wakeChecklistId = prompt.id;
|
|
2911
|
+
const items = (prompt.options || []).map(option => `
|
|
2912
|
+
<li data-option-id="${esc(option.id)}"><span class="wake-checklist-mark">${option.checked ? "[x]" : "[ ]"}</span> <span>${esc(option.label)}</span>${option.description ? `<small>${esc(option.description)}</small>` : ""}</li>
|
|
2913
|
+
`).join("");
|
|
2914
|
+
entry.innerHTML = `<div class="log-sys wake-checklist-card"><strong>${esc(prompt.title || "交叉核验清单")}</strong>${prompt.prompt ? `<p>${esc(prompt.prompt)}</p>` : ""}<ul>${items}</ul><span class="wake-checklist-hint">请在当前对话中的弹窗完成勾选。</span></div>`;
|
|
2915
|
+
consoleLog.appendChild(entry);
|
|
2916
|
+
consoleLog.scrollTop = consoleLog.scrollHeight;
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
function updateWakeChecklist(promptId, selectedIds) {
|
|
2920
|
+
const entry = document.querySelector(`[data-wake-checklist-id="${CSS.escape(promptId)}"]`);
|
|
2921
|
+
if (!entry) return;
|
|
2922
|
+
const selected = new Set(selectedIds || []);
|
|
2923
|
+
entry.querySelectorAll("li[data-option-id]").forEach(item => {
|
|
2924
|
+
const mark = item.querySelector(".wake-checklist-mark");
|
|
2925
|
+
if (mark) mark.textContent = selected.has(item.dataset.optionId) ? "[x]" : "[ ]";
|
|
2926
|
+
});
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
function showWakeModal(prompt) {
|
|
2471
2930
|
wakeState = {
|
|
2472
2931
|
id: prompt.id,
|
|
2473
2932
|
mode: prompt.mode,
|
|
@@ -2502,13 +2961,12 @@ function showWakeModal(prompt, { switchChecklist = true } = {}) {
|
|
|
2502
2961
|
} else {
|
|
2503
2962
|
wakeState.selected.add(option.id);
|
|
2504
2963
|
}
|
|
2505
|
-
showWakeModal(prompt
|
|
2964
|
+
showWakeModal(prompt);
|
|
2506
2965
|
});
|
|
2507
2966
|
list.appendChild(btn);
|
|
2508
2967
|
}
|
|
2509
2968
|
$("wake-modal").classList.remove("hidden");
|
|
2510
2969
|
openConsole();
|
|
2511
|
-
if (firstOpen && switchChecklist && prompt.mode === "checklist") setView("checklist");
|
|
2512
2970
|
}
|
|
2513
2971
|
|
|
2514
2972
|
function hideWakeModal() {
|
|
@@ -2527,8 +2985,8 @@ async function submitWake(cancel = false) {
|
|
|
2527
2985
|
body: JSON.stringify({ promptId, selectedIds, cancel: Boolean(cancel) }),
|
|
2528
2986
|
});
|
|
2529
2987
|
hideWakeModal();
|
|
2988
|
+
updateWakeChecklist(promptId, selectedIds);
|
|
2530
2989
|
appendLog("sys", cancel ? "已取消唤醒选项" : `已提交选择:${selectedIds.join(", ") || "(空)"}`);
|
|
2531
|
-
await loadChecklist().catch(() => {});
|
|
2532
2990
|
} catch (err) {
|
|
2533
2991
|
appendLog("sys", `[唤醒选项] ${err.message}`);
|
|
2534
2992
|
}
|
|
@@ -2538,23 +2996,55 @@ $("wake-modal-close")?.addEventListener("click", () => submitWake(true));
|
|
|
2538
2996
|
$("wake-cancel-btn")?.addEventListener("click", () => submitWake(true));
|
|
2539
2997
|
$("wake-submit-btn")?.addEventListener("click", () => submitWake(false));
|
|
2540
2998
|
|
|
2541
|
-
consoleFab.addEventListener("click", () => {
|
|
2542
|
-
if (consoleDrawer.classList.contains("open")) closeConsole();
|
|
2543
|
-
else openConsole();
|
|
2544
|
-
});
|
|
2545
|
-
$("console-close-btn").addEventListener("click", closeConsole);
|
|
2546
2999
|
$("console-clear-btn").addEventListener("click", () => {
|
|
2547
3000
|
consoleLog.innerHTML = `<div class="log-entry sys"><div class="log-sys">对话已清空。输入问题或 /help 即可继续。</div></div>`;
|
|
2548
3001
|
streamBubbles.clear();
|
|
2549
3002
|
});
|
|
2550
3003
|
|
|
3004
|
+
// 自适应高度调整函数
|
|
3005
|
+
function autoResizeConsoleInput() {
|
|
3006
|
+
if (!consoleInput) return;
|
|
3007
|
+
consoleInput.style.height = "auto";
|
|
3008
|
+
const nextHeight = Math.min(Math.max(consoleInput.scrollHeight, 24), 160);
|
|
3009
|
+
consoleInput.style.height = `${nextHeight}px`;
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
consoleInput.addEventListener("input", autoResizeConsoleInput);
|
|
3013
|
+
|
|
3014
|
+
// 代码块全局点击复制事件代理
|
|
3015
|
+
document.addEventListener("click", async (e) => {
|
|
3016
|
+
const btn = e.target.closest(".code-copy-btn");
|
|
3017
|
+
if (!btn) return;
|
|
3018
|
+
const rawCode = btn.dataset.code;
|
|
3019
|
+
if (!rawCode) return;
|
|
3020
|
+
try {
|
|
3021
|
+
await navigator.clipboard.writeText(rawCode);
|
|
3022
|
+
const textSpan = btn.querySelector("span");
|
|
3023
|
+
if (textSpan) {
|
|
3024
|
+
const originalText = textSpan.textContent;
|
|
3025
|
+
textSpan.textContent = "已复制";
|
|
3026
|
+
btn.style.color = "var(--ok-text)";
|
|
3027
|
+
setTimeout(() => {
|
|
3028
|
+
textSpan.textContent = originalText;
|
|
3029
|
+
btn.style.color = "";
|
|
3030
|
+
}, 1800);
|
|
3031
|
+
}
|
|
3032
|
+
} catch {
|
|
3033
|
+
alert("无法写入剪贴板,请手动选中文本复制。");
|
|
3034
|
+
}
|
|
3035
|
+
});
|
|
3036
|
+
|
|
2551
3037
|
async function sendConsoleMessage(msg) {
|
|
2552
3038
|
const text = (msg || consoleInput.value).trim();
|
|
2553
3039
|
if (!text) return;
|
|
2554
3040
|
consoleInput.value = "";
|
|
3041
|
+
autoResizeConsoleInput();
|
|
2555
3042
|
lastLocalUserText = text;
|
|
2556
3043
|
appendLog("user", text);
|
|
2557
3044
|
|
|
3045
|
+
const sendBtn = $("console-send-btn");
|
|
3046
|
+
if (sendBtn) sendBtn.disabled = true;
|
|
3047
|
+
|
|
2558
3048
|
try {
|
|
2559
3049
|
const res = await json("/api/assistant", {
|
|
2560
3050
|
method: "POST",
|
|
@@ -2565,6 +3055,8 @@ async function sendConsoleMessage(msg) {
|
|
|
2565
3055
|
if (res.text) appendLog("sys", res.text);
|
|
2566
3056
|
} catch (err) {
|
|
2567
3057
|
appendLog("sys", `[提示] ${err.message}`);
|
|
3058
|
+
} finally {
|
|
3059
|
+
if (sendBtn) sendBtn.disabled = false;
|
|
2568
3060
|
}
|
|
2569
3061
|
}
|
|
2570
3062
|
|
|
@@ -2583,11 +3075,31 @@ document.querySelectorAll(".chip").forEach(chip => {
|
|
|
2583
3075
|
const cmd = chip.dataset.cmd;
|
|
2584
3076
|
if (cmd) {
|
|
2585
3077
|
consoleInput.value = cmd;
|
|
3078
|
+
autoResizeConsoleInput();
|
|
2586
3079
|
sendConsoleMessage(cmd);
|
|
2587
3080
|
}
|
|
2588
3081
|
});
|
|
2589
3082
|
});
|
|
2590
3083
|
|
|
3084
|
+
/* --- 侧边栏折叠与展开交互 --- */
|
|
3085
|
+
const layoutEl = document.querySelector(".layout");
|
|
3086
|
+
const navToggleBtn = $("nav-toggle-btn");
|
|
3087
|
+
|
|
3088
|
+
function initNavCollapse() {
|
|
3089
|
+
const saved = localStorage.getItem("psyclaw_nav_collapsed");
|
|
3090
|
+
if (saved === "true") {
|
|
3091
|
+
layoutEl?.classList.add("nav-collapsed");
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
navToggleBtn?.addEventListener("click", () => {
|
|
3096
|
+
if (!layoutEl) return;
|
|
3097
|
+
const isCollapsed = layoutEl.classList.toggle("nav-collapsed");
|
|
3098
|
+
localStorage.setItem("psyclaw_nav_collapsed", isCollapsed ? "true" : "false");
|
|
3099
|
+
});
|
|
3100
|
+
|
|
3101
|
+
initNavCollapse();
|
|
3102
|
+
|
|
2591
3103
|
/* --- 顶栏快捷命令 Quick Actions --- */
|
|
2592
3104
|
const initModal = $("init-modal");
|
|
2593
3105
|
const initParadigm = $("init-paradigm");
|