@tea-agent/loop-agent 0.40.0-next.9 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +21 -21
- package/README.md +2 -2
- package/dist/application/dag/generate-task-dag.js +6 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +9 -5
- package/dist/cli/program.js +38 -3
- package/dist/commands/client-recovery.js +8 -36
- package/dist/commands/init-model-catalog.js +22 -0
- package/dist/commands/task-advance.js +23 -1
- package/dist/commands/task-source-prepare.js +5 -0
- package/dist/commands/task-status.js +1 -0
- package/dist/executors/pi-sdk-executor.js +33 -5
- package/dist/executors/shell-executor.js +94 -20
- package/dist/governance/checks.js +1 -0
- package/dist/shared/operator/capabilities.js +9 -1
- package/dist/shared/pi-context-pressure/checkpoint.js +116 -0
- package/dist/shared/pi-context-pressure/compaction-policy.js +151 -0
- package/dist/shared/pi-context-pressure/env.js +58 -0
- package/dist/shared/pi-context-pressure/extension.js +100 -0
- package/dist/shared/pi-context-pressure/index.js +7 -0
- package/dist/shared/pi-context-pressure/overflow.js +252 -0
- package/dist/shared/pi-context-pressure/sift-bridge.js +386 -0
- package/dist/shared/pi-context-pressure/telemetry.js +51 -0
- package/dist/worker/console/chat/assistant-content.js +7 -0
- package/dist/worker/console/chat/chat-event-store.js +82 -11
- package/dist/worker/console/chat/goal-round-driver.js +72 -0
- package/dist/worker/console/chat/goals.js +300 -0
- package/dist/worker/console/chat/pi-runtime.js +285 -8
- package/dist/worker/console/chat/provider-error.js +2 -1
- package/dist/worker/console/chat/repo-browser.js +94 -12
- package/dist/worker/console/chat/routes.js +495 -30
- package/dist/worker/console/chat/session-catalog.js +48 -0
- package/dist/worker/console/chat/session-stats.js +96 -0
- package/dist/worker/console/chat/session-store.js +27 -18
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/sift-bridge.js +1 -0
- package/dist/worker/console/chat/turn-process.js +42 -5
- package/dist/worker/console/dag-execution-receipt.js +20 -2
- package/dist/worker/console/operator-actions.js +20 -5
- package/dist/worker/console/operator-selection.js +6 -2
- package/dist/worker/console/pi-plugins.catalog.json +73658 -0
- package/dist/worker/console/pi-plugins.js +179 -0
- package/dist/worker/console/routes.js +246 -6
- package/dist/worker/console/server.js +173 -42
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bs-CDAXM.js → abnfDiagram-N423BO3Z-Dy71QJp3.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CAkA3We3.js → arc-M25fNMTE.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEmI_zqr.js → architectureDiagram-T3A2C74G-CUWlVl1a.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-uDHANebE.js → blockDiagram-VBNYF7ZC-Dd0Whpx2.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Bv97b4_B.js → c4Diagram-5PPSVZJV-BdfeCkI5.js} +1 -1
- package/dist/worker/console/static/assets/channel-Ba0AKiEZ.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-shmQKsFz.js → chunk-2GRJ4B5K-D_1sUkyD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BAraNvcN.js → chunk-2Q5K7J3B-Cxnxf36E.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BirhxUop.js → chunk-5RXB4S5H-D9RG3G_x.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C9LgUJpR.js → chunk-5VM5RSS4-Zz9jgjLX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DrU-s-t7.js → chunk-6Q2QTUOP-BCggDRCH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Tx-H_FA2.js → chunk-GF5L2VYU-CFg-5iAS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BjLtNFrR.js → chunk-JWPE2WC7-DRQTE8x_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-UNLVwSsy.js → chunk-KBJHAD2P-C_Dw7uZ8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CBEUX8XD.js → chunk-RYQCIY6F-BjIiApsk.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-WTL7IZOq.js → chunk-XXDRQBXY-B5XQD4KG.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BU3IjVEe.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BU3IjVEe.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CkHG6W3s.js → cose-bilkent-JH36ORCC-huHqH6WQ.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BRzFqTaL.js → cynefin-VYW2F7L2-BSi6yZqP.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-2_CFp_i7.js → cynefinDiagram-MW4NZA55-Bs_Jp31y.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJtsmdkE.js → dagre-VZM6K2ZE-CYxavikT.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DNEFFo6w.js → diagram-7IWD3JNH-B6TErl71.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B_IWV7eo.js → diagram-B4RE2ZJO-CvH4J2ii.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DvvRx2dz.js → diagram-LBJQPF4R-v1NBAqXS.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CsibsWLg.js → diagram-Q27KOJAE-CUNHVAn2.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-les_djBQ.js → diagram-UB23O5K3-Dzz1gUu-.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BEm2n7qJ.js → ebnfDiagram-BXEA7PRR-CCF8_LjK.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BI7vHHVm.js → erDiagram-JOGREHBK-DObdPVLa.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CUFCERrB.js → flowDiagram-UKHOOZJN-DlN8Pxrj.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-wxyLiGWt.js → ganttDiagram-PKOTCBZU-BJKIPTGX.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bt897K8Z.js → gitGraphDiagram-DS77QQ5N-XcSSnObi.js} +1 -1
- package/dist/worker/console/static/assets/index-CIYzS16i.css +1 -0
- package/dist/worker/console/static/assets/index-CS3QOTfl.js +451 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DYNx_IPv.js → infoDiagram-6WML65LV-BKrRKMww.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CzpLNEu6.js → ishikawaDiagram-WSZJBQD7-CN5dk-yb.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-97f9owNU.js → journeyDiagram-NVQOT4AX-B4P4KZ-Y.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BxM9hyBn.js → kanban-definition-27J2QSJJ-BRlteP32.js} +1 -1
- package/dist/worker/console/static/assets/{linear-ByuxcHvp.js → linear-CG8D9fuL.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DwPGvpCv.js → mermaid.core-BuB6P2rX.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DCoqG9RT.js → mindmap-definition-FAOFIHXS-DYXGl_DR.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BLSBmBMx.js → pegDiagram-VL7TDLO6-BM48yEVG.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B0t_0oJW.js → pieDiagram-7S7Q4E2Y-mT8NL-Ow.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js → quadrantDiagram-CIZ2JOQS-C4pZ6DH_.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-B3jRdATC.js → railroadDiagram-AXF67PYL-BKAcr70m.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-cTtXEN.js → requirementDiagram-LRYGKXZP-CRxcKpoO.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B25igJRE.js → sankeyDiagram-W5VNT64P-Ds4LxQDI.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-jW_lM1_D.js → sequenceDiagram-SI44F4Z6-CPLwPf_p.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CrzTgsHE.js → sizeCapture-X5ZJPWSS-CL65uij0.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B01MvlqE.js → stateDiagram-OKZ733FA-CO0Mgd1W.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BUewAVYS.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-YcF12FiU.js → swimlanes-SLNWSIFB-Cxv3TSNw.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bhe67Wjl.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ClnRcg2s.js → timeline-definition-Z64GVDOM-Dw85f9L2.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B6gr_z-q.js → vennDiagram-T6HMQDX7-B4QLCqCy.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CvSgguGH.js → wardleyDiagram-T6FBY63Y-B_yKCWwn.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-23OtSZCb.js → xychartDiagram-ELKLHX3M-nniBEGv2.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +95 -25
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +35 -1
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +3 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +26 -19
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +0 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +14 -1
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +34 -4
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
- package/dist/worker/console/static-src/operator-chat/workspace-reorder.js +18 -0
- package/dist/worker/console/static-src/shell/useWorkspaces.js +150 -34
- package/dist/worker/console/static-src/shell/workspace-route.js +3 -1
- package/dist/worker/console/workspace-context.js +28 -3
- package/dist/worker/console/workspace-registry.js +333 -60
- package/dist/worker/observe/static/inspect-bootstrap.d.ts +8 -0
- package/dist/worker/observe/static/inspect-bootstrap.js +57 -0
- package/dist/worker/observe/static/inspect-workspace.js +54 -10
- package/dist/worker/observe/static/operator-chrome.css +23 -4
- package/dist/worker/observe/static/operator-chrome.js +7 -2
- package/dist/worker/observe/static/styles.css +87 -25
- package/dist/worker/observe/static/views/dag-inspector.js +42 -1
- package/dist/worker/observe/static/views/dags.js +7 -5
- package/dist/worker/observe/static/views/session-timeline.js +135 -0
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +162 -8
- package/dist/workflows/dag/backend-test-pytest-collection.js +70 -2
- package/dist/workflows/dag/backend-test-result-contract.js +5 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +339 -53
- package/dist/workflows/dag/backend-test-writer-completeness.js +11 -0
- package/dist/workflows/dag/init-hybrid.js +5 -4
- package/docs/architecture/runtime-boundaries.md +2 -1
- package/docs/templates/backend-test-dag.json +6 -5
- package/docs/templates/init-managed-agents.md +1 -1
- package/package.json +3 -2
- package/skills/loop-agent/references/command-reference.md +15 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +0 -1
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +0 -407
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +0 -8
|
@@ -49,16 +49,18 @@
|
|
|
49
49
|
.och-inner {
|
|
50
50
|
box-sizing: border-box;
|
|
51
51
|
width: 100%;
|
|
52
|
+
min-width: 0;
|
|
52
53
|
padding-inline: 14px;
|
|
53
54
|
margin: 0 auto;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
/* Band 1 — 全局带:品牌 / 仓库身份 / 模式 /
|
|
57
|
+
/* Band 1 — 全局带:品牌 / 仓库身份 / 模式 / 状态格(对象上下文在下方独立行) */
|
|
57
58
|
.och-global {
|
|
58
59
|
position: relative;
|
|
59
60
|
display: flex;
|
|
60
61
|
align-items: center;
|
|
61
62
|
gap: 12px;
|
|
63
|
+
min-width: 0;
|
|
62
64
|
/* DSH 2026-08-23:约 44px 与内容同色的压缩标题栏。 */
|
|
63
65
|
height: 44px;
|
|
64
66
|
}
|
|
@@ -318,11 +320,21 @@
|
|
|
318
320
|
z-index: 1;
|
|
319
321
|
}
|
|
320
322
|
|
|
321
|
-
/* 对象上下文 chip:跨模式选中连续性 +
|
|
323
|
+
/* 对象上下文 chip:跨模式选中连续性 + 显式返回路径。
|
|
324
|
+
* 不放进 44px 全局带:≥720px 模式开关 position:fixed 居中,长 run id
|
|
325
|
+
* 会从左侧把「返回 恢复」顶进滑块底下。独立一行后按钮始终完整可见。 */
|
|
326
|
+
.och-context-row {
|
|
327
|
+
display: flex;
|
|
328
|
+
align-items: center;
|
|
329
|
+
min-width: 0;
|
|
330
|
+
padding: 0 0 8px;
|
|
331
|
+
}
|
|
322
332
|
.och-context {
|
|
323
333
|
display: inline-flex;
|
|
324
334
|
align-items: center;
|
|
325
335
|
gap: 8px;
|
|
336
|
+
min-width: 0;
|
|
337
|
+
max-width: 100%;
|
|
326
338
|
min-height: 30px;
|
|
327
339
|
padding: 0 6px 0 12px;
|
|
328
340
|
border: 1px solid
|
|
@@ -331,26 +343,29 @@
|
|
|
331
343
|
background: color-mix(in srgb, var(--och-peach) 42%, var(--och-surface));
|
|
332
344
|
font-size: 12px;
|
|
333
345
|
color: var(--och-ink);
|
|
334
|
-
white-space: nowrap;
|
|
335
346
|
}
|
|
336
347
|
.och-context[hidden] {
|
|
337
348
|
display: none;
|
|
338
349
|
}
|
|
339
350
|
.och-context-kind {
|
|
351
|
+
flex-shrink: 0;
|
|
340
352
|
color: var(--och-orange-active);
|
|
341
353
|
font-weight: 700;
|
|
342
354
|
}
|
|
343
355
|
.och-context-id {
|
|
356
|
+
flex: 1 1 auto;
|
|
357
|
+
min-width: 0;
|
|
344
358
|
font-family: var(--och-mono);
|
|
345
359
|
font-size: 11px;
|
|
346
360
|
color: var(--och-body);
|
|
347
|
-
max-width: 260px;
|
|
348
361
|
overflow: hidden;
|
|
349
362
|
text-overflow: ellipsis;
|
|
363
|
+
white-space: nowrap;
|
|
350
364
|
}
|
|
351
365
|
.och-context-return {
|
|
352
366
|
display: inline-flex;
|
|
353
367
|
align-items: center;
|
|
368
|
+
flex-shrink: 0;
|
|
354
369
|
gap: 4px;
|
|
355
370
|
height: 22px;
|
|
356
371
|
padding: 0 9px;
|
|
@@ -360,6 +375,7 @@
|
|
|
360
375
|
font-size: 11px;
|
|
361
376
|
font-weight: 600;
|
|
362
377
|
text-decoration: none;
|
|
378
|
+
white-space: nowrap;
|
|
363
379
|
}
|
|
364
380
|
.och-context-return:hover {
|
|
365
381
|
background: var(--och-orange-active);
|
|
@@ -369,6 +385,7 @@
|
|
|
369
385
|
display: inline-flex;
|
|
370
386
|
align-items: center;
|
|
371
387
|
justify-content: center;
|
|
388
|
+
flex-shrink: 0;
|
|
372
389
|
width: 20px;
|
|
373
390
|
height: 20px;
|
|
374
391
|
padding: 0;
|
|
@@ -401,6 +418,7 @@
|
|
|
401
418
|
font-size: 12px;
|
|
402
419
|
font-variant-numeric: tabular-nums;
|
|
403
420
|
white-space: nowrap;
|
|
421
|
+
flex-shrink: 0;
|
|
404
422
|
}
|
|
405
423
|
.och-fresh-dot {
|
|
406
424
|
width: 7px;
|
|
@@ -425,6 +443,7 @@
|
|
|
425
443
|
color: var(--och-body);
|
|
426
444
|
text-decoration: none;
|
|
427
445
|
white-space: nowrap;
|
|
446
|
+
flex-shrink: 0;
|
|
428
447
|
transition: border-color 0.15s ease;
|
|
429
448
|
}
|
|
430
449
|
.och-pi:hover {
|
|
@@ -17,6 +17,7 @@ export const OPERATE_TABS = Object.freeze([
|
|
|
17
17
|
{ id: "night", label: "夜间", href: "/#/operate/night" },
|
|
18
18
|
{ id: "models", label: "模型与认证", href: "/#/operate/models" },
|
|
19
19
|
{ id: "settings", label: "设置", href: "/#/operate/settings" },
|
|
20
|
+
{ id: "pi-plugins", label: "Pi 插件", href: "/#/operate/pi-plugins" },
|
|
20
21
|
]);
|
|
21
22
|
|
|
22
23
|
export const INSPECT_TABS = Object.freeze([
|
|
@@ -653,7 +654,9 @@ export function mountOperatorChrome(root, config = {}) {
|
|
|
653
654
|
if (model.context) {
|
|
654
655
|
const chip = el("div", "och-context");
|
|
655
656
|
chip.appendChild(el("span", "och-context-kind", model.context.kindLabel));
|
|
656
|
-
|
|
657
|
+
const idEl = el("span", "och-context-id", model.context.id);
|
|
658
|
+
idEl.title = model.context.id;
|
|
659
|
+
chip.appendChild(idEl);
|
|
657
660
|
const back = el("a", "och-context-return");
|
|
658
661
|
back.href = model.context.returnHref;
|
|
659
662
|
back.appendChild(makeIcon("arrowLeft"));
|
|
@@ -675,7 +678,9 @@ export function mountOperatorChrome(root, config = {}) {
|
|
|
675
678
|
render();
|
|
676
679
|
});
|
|
677
680
|
chip.appendChild(close);
|
|
678
|
-
|
|
681
|
+
const row = el("div", "och-context-row");
|
|
682
|
+
row.appendChild(chip);
|
|
683
|
+
inner.appendChild(row);
|
|
679
684
|
}
|
|
680
685
|
|
|
681
686
|
global.appendChild(el("span", "och-spacer"));
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
:
|
|
1
|
+
html:has(body[data-shell="observe-console"]),
|
|
2
|
+
body[data-shell="observe-console"],
|
|
3
|
+
.inspect-workspace-root {
|
|
4
|
+
color-scheme: light;
|
|
2
5
|
--canvas: #f7f7f4;
|
|
3
6
|
--canvas-soft: #fafaf7;
|
|
4
7
|
--surface: #ffffff;
|
|
@@ -38,14 +41,14 @@
|
|
|
38
41
|
--transition-base: 220ms ease;
|
|
39
42
|
--shadow-panel: 0 1px 2px rgb(38 37 30 / 4%), 0 8px 24px rgb(38 37 30 / 3%);
|
|
40
43
|
--shadow-soft: 0 10px 30px rgb(38 37 30 / 6%);
|
|
41
|
-
color-scheme: light;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
body[data-shell="observe-console"] *,
|
|
47
|
+
.inspect-workspace-root * {
|
|
45
48
|
box-sizing: border-box;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
html {
|
|
51
|
+
html:has(body[data-shell="observe-console"]) {
|
|
49
52
|
background:
|
|
50
53
|
radial-gradient(
|
|
51
54
|
1200px 480px at 8% -10%,
|
|
@@ -62,7 +65,7 @@ html {
|
|
|
62
65
|
scroll-behavior: smooth;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
body {
|
|
68
|
+
body[data-shell="observe-console"] {
|
|
66
69
|
min-width: 320px;
|
|
67
70
|
margin: 0;
|
|
68
71
|
min-height: 100vh;
|
|
@@ -76,29 +79,46 @@ body {
|
|
|
76
79
|
line-height: 1.5;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
button,
|
|
80
|
-
input,
|
|
81
|
-
select,
|
|
82
|
-
textarea
|
|
82
|
+
body[data-shell="observe-console"] button,
|
|
83
|
+
body[data-shell="observe-console"] input,
|
|
84
|
+
body[data-shell="observe-console"] select,
|
|
85
|
+
body[data-shell="observe-console"] textarea,
|
|
86
|
+
.inspect-workspace-root button,
|
|
87
|
+
.inspect-workspace-root input,
|
|
88
|
+
.inspect-workspace-root select,
|
|
89
|
+
.inspect-workspace-root textarea {
|
|
83
90
|
font: inherit;
|
|
84
91
|
}
|
|
85
92
|
|
|
86
|
-
a
|
|
93
|
+
body[data-shell="observe-console"] a,
|
|
94
|
+
.inspect-workspace-root a {
|
|
87
95
|
color: inherit;
|
|
88
96
|
}
|
|
89
97
|
|
|
90
|
-
code,
|
|
91
|
-
pre,
|
|
92
|
-
.output-block,
|
|
93
|
-
.dag-node-label,
|
|
94
|
-
.dag-node-meta,
|
|
95
|
-
.dag-node-status,
|
|
96
|
-
.dag-node-table td:nth-child(2),
|
|
97
|
-
td:first-child,
|
|
98
|
-
.meta-item dd,
|
|
99
|
-
.kpi-value,
|
|
100
|
-
.risk-total,
|
|
101
|
-
.process-timeline-time
|
|
98
|
+
body[data-shell="observe-console"] code,
|
|
99
|
+
body[data-shell="observe-console"] pre,
|
|
100
|
+
body[data-shell="observe-console"] .output-block,
|
|
101
|
+
body[data-shell="observe-console"] .dag-node-label,
|
|
102
|
+
body[data-shell="observe-console"] .dag-node-meta,
|
|
103
|
+
body[data-shell="observe-console"] .dag-node-status,
|
|
104
|
+
body[data-shell="observe-console"] .dag-node-table td:nth-child(2),
|
|
105
|
+
body[data-shell="observe-console"] td:first-child,
|
|
106
|
+
body[data-shell="observe-console"] .meta-item dd,
|
|
107
|
+
body[data-shell="observe-console"] .kpi-value,
|
|
108
|
+
body[data-shell="observe-console"] .risk-total,
|
|
109
|
+
body[data-shell="observe-console"] .process-timeline-time,
|
|
110
|
+
.inspect-workspace-root code,
|
|
111
|
+
.inspect-workspace-root pre,
|
|
112
|
+
.inspect-workspace-root .output-block,
|
|
113
|
+
.inspect-workspace-root .dag-node-label,
|
|
114
|
+
.inspect-workspace-root .dag-node-meta,
|
|
115
|
+
.inspect-workspace-root .dag-node-status,
|
|
116
|
+
.inspect-workspace-root .dag-node-table td:nth-child(2),
|
|
117
|
+
.inspect-workspace-root td:first-child,
|
|
118
|
+
.inspect-workspace-root .meta-item dd,
|
|
119
|
+
.inspect-workspace-root .kpi-value,
|
|
120
|
+
.inspect-workspace-root .risk-total,
|
|
121
|
+
.inspect-workspace-root .process-timeline-time {
|
|
102
122
|
font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
|
|
103
123
|
}
|
|
104
124
|
|
|
@@ -125,6 +145,30 @@ td:first-child,
|
|
|
125
145
|
padding: var(--space-5) 0 56px;
|
|
126
146
|
}
|
|
127
147
|
|
|
148
|
+
.inspect-workspace-root {
|
|
149
|
+
position: relative;
|
|
150
|
+
min-height: 100%;
|
|
151
|
+
color: var(--ink);
|
|
152
|
+
font-family:
|
|
153
|
+
system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB",
|
|
154
|
+
"Noto Sans SC", BlinkMacSystemFont, sans-serif;
|
|
155
|
+
font-size: 14px;
|
|
156
|
+
line-height: 1.5;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.inspect-workspace-root .dag-inspector {
|
|
160
|
+
top: 8px;
|
|
161
|
+
right: 8px;
|
|
162
|
+
bottom: 8px;
|
|
163
|
+
width: min(var(--dag-inspector-width, 50%), calc(100% - 16px));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.inspect-workspace-root #app {
|
|
167
|
+
width: 100%;
|
|
168
|
+
margin: 0;
|
|
169
|
+
padding: var(--space-4) var(--space-5) var(--space-6);
|
|
170
|
+
}
|
|
171
|
+
|
|
128
172
|
.breadcrumb {
|
|
129
173
|
display: flex;
|
|
130
174
|
min-height: 16px;
|
|
@@ -257,7 +301,8 @@ td:first-child,
|
|
|
257
301
|
color: var(--body);
|
|
258
302
|
}
|
|
259
303
|
|
|
260
|
-
.panel
|
|
304
|
+
body[data-shell="observe-console"] .panel,
|
|
305
|
+
.inspect-workspace-root .panel {
|
|
261
306
|
min-width: 0;
|
|
262
307
|
background: color-mix(in srgb, var(--surface) 96%, transparent);
|
|
263
308
|
border: 1px solid var(--hairline);
|
|
@@ -288,7 +333,8 @@ td:first-child,
|
|
|
288
333
|
}
|
|
289
334
|
|
|
290
335
|
.section-heading,
|
|
291
|
-
.panel h3
|
|
336
|
+
body[data-shell="observe-console"] .panel h3,
|
|
337
|
+
.inspect-workspace-root .panel h3 {
|
|
292
338
|
margin: 0 0 var(--space-4);
|
|
293
339
|
color: var(--ink);
|
|
294
340
|
font-size: 14px;
|
|
@@ -1810,6 +1856,15 @@ body.is-resizing-dag-graph {
|
|
|
1810
1856
|
color: var(--muted);
|
|
1811
1857
|
font-size: 11px;
|
|
1812
1858
|
}
|
|
1859
|
+
.process-timeline-export-bar {
|
|
1860
|
+
display: flex;
|
|
1861
|
+
justify-content: flex-end;
|
|
1862
|
+
padding: 2px 0 var(--space-2);
|
|
1863
|
+
}
|
|
1864
|
+
.process-timeline-export-bar .btn {
|
|
1865
|
+
font-size: 11px;
|
|
1866
|
+
padding: 3px 10px;
|
|
1867
|
+
}
|
|
1813
1868
|
.process-timeline {
|
|
1814
1869
|
display: grid;
|
|
1815
1870
|
gap: 0;
|
|
@@ -2526,7 +2581,8 @@ body.is-resizing-dag-graph {
|
|
|
2526
2581
|
flex-wrap: wrap;
|
|
2527
2582
|
gap: 6px;
|
|
2528
2583
|
}
|
|
2529
|
-
.muted
|
|
2584
|
+
body[data-shell="observe-console"] .muted,
|
|
2585
|
+
.inspect-workspace-root .muted {
|
|
2530
2586
|
color: var(--muted);
|
|
2531
2587
|
}
|
|
2532
2588
|
|
|
@@ -2746,6 +2802,12 @@ body.is-resizing-dag-graph {
|
|
|
2746
2802
|
bottom: 12px;
|
|
2747
2803
|
width: calc(100vw - 24px);
|
|
2748
2804
|
}
|
|
2805
|
+
.inspect-workspace-root .dag-inspector {
|
|
2806
|
+
width: calc(100% - 16px);
|
|
2807
|
+
top: 8px;
|
|
2808
|
+
right: 8px;
|
|
2809
|
+
bottom: 8px;
|
|
2810
|
+
}
|
|
2749
2811
|
.dag-inspector-resize-handle {
|
|
2750
2812
|
display: none;
|
|
2751
2813
|
}
|
|
@@ -24,6 +24,7 @@ import { renderMarkdown, renderInspectorDocument } from "../markdown-render.js";
|
|
|
24
24
|
import { describeDagNodePurpose } from "../dag-node-purpose.js";
|
|
25
25
|
import { buildPromptRestartCandidateOptions } from "../prompt-restart-candidates.js";
|
|
26
26
|
import { copyText } from "../copy.js";
|
|
27
|
+
import { navigate } from "../router.js";
|
|
27
28
|
import {
|
|
28
29
|
fetchWithWorkspaceScope,
|
|
29
30
|
uiState,
|
|
@@ -47,6 +48,7 @@ import {
|
|
|
47
48
|
import {
|
|
48
49
|
formatSessionEventTime,
|
|
49
50
|
renderSessionTimeline,
|
|
51
|
+
buildPageStyledDoc,
|
|
50
52
|
} from "./session-timeline.js";
|
|
51
53
|
import { createCustomSelect } from "../custom-select.js";
|
|
52
54
|
|
|
@@ -1671,7 +1673,7 @@ async function renderPromptRestart(content, dagRunId, node) {
|
|
|
1671
1673
|
open.className = "prompt-restart-submit is-secondary";
|
|
1672
1674
|
open.textContent = "打开新 run";
|
|
1673
1675
|
open.addEventListener("click", () => {
|
|
1674
|
-
|
|
1676
|
+
navigate(`/dag/${encodeURIComponent(String(newRunId))}`);
|
|
1675
1677
|
});
|
|
1676
1678
|
row.appendChild(open);
|
|
1677
1679
|
} else {
|
|
@@ -2343,6 +2345,45 @@ function renderNonPiProcess(content, body) {
|
|
|
2343
2345
|
ul.appendChild(li);
|
|
2344
2346
|
}
|
|
2345
2347
|
content.appendChild(ul);
|
|
2348
|
+
appendProcessExportButton(content, body, body);
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
function downloadTextFile(filename, text) {
|
|
2352
|
+
const blob = new Blob([text], { type: "text/html;charset=utf-8" });
|
|
2353
|
+
const url = URL.createObjectURL(blob);
|
|
2354
|
+
const a = document.createElement("a");
|
|
2355
|
+
a.href = url;
|
|
2356
|
+
a.download = filename;
|
|
2357
|
+
document.body.appendChild(a);
|
|
2358
|
+
a.click();
|
|
2359
|
+
a.remove();
|
|
2360
|
+
URL.revokeObjectURL(url);
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
function appendProcessExportButton(content, body, meta) {
|
|
2364
|
+
if (!body || ((body.commands ?? []).length === 0 && (body.steps ?? []).length === 0)) return;
|
|
2365
|
+
const toolbar = el("div", "process-timeline-export-bar");
|
|
2366
|
+
const btn = el("button", "btn btn-secondary", "导出 HTML");
|
|
2367
|
+
btn.type = "button";
|
|
2368
|
+
btn.addEventListener("click", async () => {
|
|
2369
|
+
let cssText = "";
|
|
2370
|
+
try {
|
|
2371
|
+
const res = await fetch("/inspect/styles.css", { cache: "no-cache" });
|
|
2372
|
+
if (res.ok) cssText = await res.text();
|
|
2373
|
+
} catch {
|
|
2374
|
+
/* 忽略:导出仍会用内联兜底样式 */
|
|
2375
|
+
}
|
|
2376
|
+
// 复用页面真实渲染 DOM,保证导出排版与页面一致。
|
|
2377
|
+
const clone = content.cloneNode(true);
|
|
2378
|
+
const bar = clone.querySelector(".process-timeline-export-bar");
|
|
2379
|
+
if (bar) bar.remove();
|
|
2380
|
+
downloadTextFile(
|
|
2381
|
+
`node-process-${meta?.nodeId || "node"}-${Date.now()}.html`,
|
|
2382
|
+
buildPageStyledDoc(clone.innerHTML, meta ?? {}, cssText),
|
|
2383
|
+
);
|
|
2384
|
+
});
|
|
2385
|
+
toolbar.appendChild(btn);
|
|
2386
|
+
content.insertBefore(toolbar, content.firstChild);
|
|
2346
2387
|
}
|
|
2347
2388
|
|
|
2348
2389
|
export async function mergeNodeProcess(dagRunId, node) {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
DAG_HISTORY_DEFAULT_PAGE_SIZE,
|
|
16
16
|
navigate,
|
|
17
17
|
parseRoute,
|
|
18
|
+
inspectPathToCanonicalHref,
|
|
18
19
|
} from "../router.js";
|
|
19
20
|
import { fetchDagRunHistory, summarizeFetchError } from "../api.js";
|
|
20
21
|
import { copyText } from "../copy.js";
|
|
@@ -57,7 +58,8 @@ function currentHistoryQuery() {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
function syncHash(page, pageSize, { replace = false } = {}) {
|
|
60
|
-
const
|
|
61
|
+
const path = buildDagHistoryHash(page, pageSize);
|
|
62
|
+
const next = inspectPathToCanonicalHref(path).replace(/^\/#/, "") || "/inspect";
|
|
61
63
|
const current = (location.hash || "").replace(/^#/, "") || "/";
|
|
62
64
|
const currentPath = current.split("?")[0];
|
|
63
65
|
const nextPath = next.split("?")[0];
|
|
@@ -72,15 +74,15 @@ function syncHash(page, pageSize, { replace = false } = {}) {
|
|
|
72
74
|
location.hash = next;
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
|
-
return
|
|
77
|
+
return path;
|
|
76
78
|
}
|
|
77
79
|
if (replace && typeof history !== "undefined" && history.replaceState) {
|
|
78
80
|
const base = `${location.pathname}${location.search}`;
|
|
79
81
|
history.replaceState(null, "", `${base}#${next}`);
|
|
80
|
-
return
|
|
82
|
+
return path;
|
|
81
83
|
}
|
|
82
|
-
navigate(
|
|
83
|
-
return
|
|
84
|
+
navigate(path);
|
|
85
|
+
return path;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
function setControlsDisabled(disabled) {
|
|
@@ -30,6 +30,112 @@ export function sessionEventArgs(event) {
|
|
|
30
30
|
return args && typeof args === "object" && !Array.isArray(args) ? args : {};
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
function escapeHtml(text) {
|
|
34
|
+
return String(text ?? "")
|
|
35
|
+
.replaceAll("&", "&")
|
|
36
|
+
.replaceAll("<", "<")
|
|
37
|
+
.replaceAll(">", ">")
|
|
38
|
+
.replaceAll('"', """)
|
|
39
|
+
.replaceAll("'", "'");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function downloadTextFile(filename, text) {
|
|
43
|
+
const blob = new Blob([text], { type: "text/html;charset=utf-8" });
|
|
44
|
+
const url = URL.createObjectURL(blob);
|
|
45
|
+
const a = document.createElement("a");
|
|
46
|
+
a.href = url;
|
|
47
|
+
a.download = filename;
|
|
48
|
+
document.body.appendChild(a);
|
|
49
|
+
a.click();
|
|
50
|
+
a.remove();
|
|
51
|
+
URL.revokeObjectURL(url);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 兜底样式:仅在无法抓取页面 /inspect/styles.css 时使用(与页面 process-timeline 排版对齐)。 */
|
|
55
|
+
const EXPORT_FALLBACK_CSS = `
|
|
56
|
+
:root{--canvas:#f7f7f4;--surface:#ffffff;--canvas-soft:#fafaf7;--surface-muted:#f0efe9;--ink:#26251e;--body:#5a5852;--muted:#807d72;--muted-soft:#a09c92;--hairline:#e6e5e0;--hairline-strong:#cfcdc4;--orange:#f54e00;--orange-active:#d04200;--blue:#3f6ea4;--green:#1f8a65;--amber:#a66a00;--red:#c72d53;--lavender:#e4daf1;--radius-sm:6px;--space-2:8px;--space-3:12px;--space-5:20px}
|
|
57
|
+
body{margin:0;font-family:-apple-system,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;background:var(--canvas);color:var(--body);font-size:13px}
|
|
58
|
+
.process-timeline{display:grid;gap:0;margin:0;padding:var(--space-2) 0;list-style:none}
|
|
59
|
+
.process-timeline-item{display:grid;grid-template-columns:20px minmax(0,1fr);align-items:stretch;min-height:34px}
|
|
60
|
+
.process-timeline-item.has-time{grid-template-columns:20px 92px minmax(0,1fr)}
|
|
61
|
+
.process-timeline-rail{position:relative;display:grid;place-items:center;min-height:34px}
|
|
62
|
+
.process-timeline-rail::before{position:absolute;top:0;bottom:0;width:1px;background:var(--hairline-strong);content:""}
|
|
63
|
+
.process-timeline-item.is-first .process-timeline-rail::before{top:50%}
|
|
64
|
+
.process-timeline-item.is-last .process-timeline-rail::before{bottom:50%}
|
|
65
|
+
.process-timeline-dot{position:relative;z-index:1;width:8px;height:8px;border:2px solid var(--surface);border-radius:50%;background:var(--muted-soft)}
|
|
66
|
+
.process-timeline-lifecycle .process-timeline-dot{background:var(--lavender)}
|
|
67
|
+
.process-timeline-tool-start .process-timeline-dot{background:var(--orange)}
|
|
68
|
+
.process-timeline-tool-end .process-timeline-dot{background:var(--green)}
|
|
69
|
+
.process-timeline-assistant .process-timeline-dot{background:var(--blue)}
|
|
70
|
+
.process-timeline-protocol .process-timeline-dot{background:var(--muted-soft)}
|
|
71
|
+
.process-timeline-item.is-error .process-timeline-dot{background:var(--red)}
|
|
72
|
+
.process-timeline-time{padding:9px 0;color:var(--muted);font-size:10px;font-variant-numeric:tabular-nums}
|
|
73
|
+
.process-timeline-label{min-width:0;padding:8px 0 8px var(--space-2);color:var(--body);font-size:12px;line-height:1.5;overflow-wrap:anywhere}
|
|
74
|
+
.process-timeline-protocol .process-timeline-label{color:var(--muted);font-size:11px}
|
|
75
|
+
.process-timeline-body{min-width:0;padding:4px 0 8px var(--space-2)}
|
|
76
|
+
.process-timeline-card{display:grid;gap:6px;min-width:0}
|
|
77
|
+
.process-timeline-details{min-width:0;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--surface)}
|
|
78
|
+
.process-timeline-summary{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;cursor:pointer;list-style:none;color:var(--ink);font-size:12px;font-weight:650}
|
|
79
|
+
.process-timeline-summary::-webkit-details-marker{display:none}
|
|
80
|
+
.process-timeline-summary-title{min-width:0;overflow-wrap:anywhere}
|
|
81
|
+
.process-timeline-summary-status{flex-shrink:0;color:var(--muted);font-size:11px;font-weight:700}
|
|
82
|
+
.process-timeline-summary-status.status-succeeded{color:var(--green)}
|
|
83
|
+
.process-timeline-summary-status.status-failed{color:var(--red)}
|
|
84
|
+
.process-timeline-summary-status.status-pending{color:var(--orange)}
|
|
85
|
+
.process-timeline-tool-card.is-error .process-timeline-details{border-color:var(--red);background:var(--canvas-soft)}
|
|
86
|
+
.process-timeline-card-body{display:grid;gap:6px;padding:0 10px 10px}
|
|
87
|
+
.process-timeline-section-label{color:var(--muted);font-size:11px;font-weight:700}
|
|
88
|
+
.process-timeline-code,.process-timeline-thinking-body{margin:0;padding:8px 10px;overflow:auto;border-radius:var(--radius-sm);background:var(--canvas-soft);color:var(--body);font-family:"JetBrains Mono","SFMono-Regular",Consolas,monospace;font-size:11px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
89
|
+
.process-timeline-more{margin-top:2px}
|
|
90
|
+
.process-timeline-more>summary{cursor:pointer;color:var(--blue);font-size:11px;font-weight:650}
|
|
91
|
+
.process-timeline-thinking>summary{background:var(--lavender)}
|
|
92
|
+
.process-timeline-turn-text{display:grid;gap:6px;padding:8px 10px;border:1px solid var(--hairline);border-radius:var(--radius-sm);background:var(--surface)}
|
|
93
|
+
.process-timeline-turn-text .markdown-output{font-size:12px}
|
|
94
|
+
.process-timeline-tool-only-note{margin:0;font-size:12px}
|
|
95
|
+
.process-timeline-turn-tools{display:grid;gap:4px;margin:0;padding:0 0 0 1.1em;color:var(--body);font-size:12px;font-family:"JetBrains Mono","SFMono-Regular",Consolas,monospace;overflow-wrap:anywhere}
|
|
96
|
+
.process-timeline-turn-tools li{padding:2px 0}
|
|
97
|
+
.process-timeline-agent-end-note{margin:0;font-size:11px}
|
|
98
|
+
.markdown-output{display:grid;gap:var(--space-3);color:var(--body);font-size:13px;line-height:1.65}
|
|
99
|
+
.markdown-output>:first-child{margin-top:0}
|
|
100
|
+
.markdown-output>:last-child{margin-bottom:0}
|
|
101
|
+
.markdown-output h1,.markdown-output h2,.markdown-output h3,.markdown-output h4{margin:var(--space-5) 0 var(--space-2);color:var(--ink);line-height:1.3}
|
|
102
|
+
.markdown-output h1{font-size:21px}.markdown-output h2{font-size:18px}.markdown-output h3{font-size:16px}.markdown-output h4{font-size:14px}
|
|
103
|
+
.markdown-output p,.markdown-output blockquote,.markdown-output ul,.markdown-output ol{margin:0;overflow-wrap:anywhere}
|
|
104
|
+
.markdown-output ul,.markdown-output ol{padding-left:22px}
|
|
105
|
+
.markdown-output blockquote{padding-left:12px}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
const EXPORT_SHELL_CSS = `
|
|
109
|
+
body{margin:0;font-family:-apple-system,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;background:var(--canvas)}
|
|
110
|
+
.export-shell{max-width:1000px;margin:0 auto;padding:24px 28px;background:var(--surface);min-height:100vh;box-shadow:0 0 0 1px var(--hairline)}
|
|
111
|
+
.export-head h1{font-size:15px;color:var(--ink);margin:0;font-weight:700}
|
|
112
|
+
.export-sub{color:var(--muted);font-size:12px;margin:4px 0 16px}
|
|
113
|
+
.export-controls{display:flex;justify-content:flex-start;margin:0 0 12px}
|
|
114
|
+
.export-toggle{min-height:28px;padding:0 12px;border:1px solid var(--hairline-strong);border-radius:var(--radius-sm);background:var(--surface);color:var(--body);font-size:11px;font-weight:600;cursor:pointer;user-select:none}
|
|
115
|
+
.export-toggle:hover,.export-toggle:focus-visible{border-color:var(--orange);color:var(--orange-active);outline:none}
|
|
116
|
+
body.hide-protocol .process-timeline-item.process-timeline-protocol{display:none}
|
|
117
|
+
`;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 把页面渲染出的时间线 innerHTML 封装成自包含 HTML。
|
|
121
|
+
* @param {string} bodyHTML 页面渲染的 .process-timeline 等真实 DOM 序列化结果
|
|
122
|
+
* @param {{nodeId?:string,dagRunId?:string}} meta
|
|
123
|
+
* @param {string} [cssText] 页面 /inspect/styles.css 原文;缺失时用兜底样式
|
|
124
|
+
*/
|
|
125
|
+
export function buildPageStyledDoc(bodyHTML, meta = {}, cssText = "") {
|
|
126
|
+
const now = new Date().toLocaleString();
|
|
127
|
+
const title = meta.nodeId ? `节点执行过程 · ${meta.nodeId}` : "节点执行过程";
|
|
128
|
+
const style = cssText.trim()
|
|
129
|
+
? `${cssText}\n\n/* 导出外壳 */\n${EXPORT_SHELL_CSS}`
|
|
130
|
+
: `${EXPORT_FALLBACK_CSS}\n${EXPORT_SHELL_CSS}`;
|
|
131
|
+
// 有协议行时,在左上角提供一个「展开/隐藏原始协议事件」按钮(与页面一致),默认隐藏。
|
|
132
|
+
const hasProtocol = bodyHTML.includes("process-timeline-protocol");
|
|
133
|
+
const controls = hasProtocol
|
|
134
|
+
? `<div class="export-controls"><button type="button" id="exportToggleProtocol" class="export-toggle">展开原始协议事件</button></div><script>(function(){var b=document.body,t=document.getElementById('exportToggleProtocol'),on=false;function apply(){b.classList.toggle('hide-protocol',!on);t.textContent=on?'隐藏原始协议事件':'展开原始协议事件';}if(t){t.addEventListener('click',function(){on=!on;apply();});apply();}})();</script>`
|
|
135
|
+
: "";
|
|
136
|
+
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${escapeHtml(title)}</title><style>${style}</style></head><body><div class="export-shell"><div class="export-head"><h1>${escapeHtml(title)}</h1></div><p class="export-sub">DAG ${escapeHtml(meta.dagRunId ?? "")} · 导出于 ${escapeHtml(now)}</p>${controls}<div class="export-timeline">${bodyHTML}</div></div></body></html>`;
|
|
137
|
+
}
|
|
138
|
+
|
|
33
139
|
export function sessionEventResult(event) {
|
|
34
140
|
return normalizeSessionEventFields(event).result;
|
|
35
141
|
}
|
|
@@ -742,6 +848,35 @@ export function renderSessionTimeline(content, nodeId, options = {}) {
|
|
|
742
848
|
parent.scrollLeft = scrollLeft;
|
|
743
849
|
});
|
|
744
850
|
toolbar.appendChild(protocolToggle);
|
|
851
|
+
const exportBtn = el("button", "btn btn-secondary", "导出 HTML");
|
|
852
|
+
exportBtn.type = "button";
|
|
853
|
+
exportBtn.addEventListener("click", async () => {
|
|
854
|
+
let cssText = "";
|
|
855
|
+
try {
|
|
856
|
+
const res = await fetch("/inspect/styles.css", { cache: "no-cache" });
|
|
857
|
+
if (res.ok) cssText = await res.text();
|
|
858
|
+
} catch {
|
|
859
|
+
/* 忽略:导出仍会用内联兜底样式 */
|
|
860
|
+
}
|
|
861
|
+
// 复用页面真实渲染(含原始协议事件),保证导出的排版与页面一致。
|
|
862
|
+
const prevShow = uiState.sessionTimelineShowProtocol;
|
|
863
|
+
uiState.sessionTimelineShowProtocol = true;
|
|
864
|
+
const tmp = document.createElement("div");
|
|
865
|
+
tmp.className = "process-timeline-scroll";
|
|
866
|
+
renderSessionTimeline(tmp, nodeId, options);
|
|
867
|
+
const toolbar = tmp.querySelector(".process-timeline-toolbar");
|
|
868
|
+
if (toolbar) toolbar.remove();
|
|
869
|
+
const innerHTML = tmp.innerHTML;
|
|
870
|
+
uiState.sessionTimelineShowProtocol = prevShow;
|
|
871
|
+
downloadTextFile(
|
|
872
|
+
`node-process-${nodeId || "node"}-${Date.now()}.html`,
|
|
873
|
+
buildPageStyledDoc(innerHTML, {
|
|
874
|
+
nodeId,
|
|
875
|
+
dagRunId: uiState.currentDagRunId ?? "",
|
|
876
|
+
}, cssText),
|
|
877
|
+
);
|
|
878
|
+
});
|
|
879
|
+
toolbar.appendChild(exportBtn);
|
|
745
880
|
content.appendChild(toolbar);
|
|
746
881
|
|
|
747
882
|
const timelineItems = buildRichTimelineItems(visible.events, {
|