@tea-agent/loop-agent 0.40.0-next.8 → 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 -20
- 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/dag-pi-executor.js +3 -0
- package/dist/executors/pi-executor.js +4 -2
- package/dist/executors/pi-sdk-executor.js +79 -6
- 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-BYBmDfPW.js → abnfDiagram-N423BO3Z-Dy71QJp3.js} +1 -1
- package/dist/worker/console/static/assets/{arc-BKMmxpGF.js → arc-M25fNMTE.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DJpwxr1d.js → architectureDiagram-T3A2C74G-CUWlVl1a.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BaPj_ZlY.js → blockDiagram-VBNYF7ZC-Dd0Whpx2.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B8iGmHlm.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-DaxXQayc.js → chunk-2GRJ4B5K-D_1sUkyD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DqQKGA7q.js → chunk-2Q5K7J3B-Cxnxf36E.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CgMKpJBB.js → chunk-5RXB4S5H-D9RG3G_x.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BpToUlaW.js → chunk-5VM5RSS4-Zz9jgjLX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BsEWOHxv.js → chunk-6Q2QTUOP-BCggDRCH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CKGSCe71.js → chunk-GF5L2VYU-CFg-5iAS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-Bm1U5299.js → chunk-JWPE2WC7-DRQTE8x_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BI0ov870.js → chunk-KBJHAD2P-C_Dw7uZ8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BmnQo0iJ.js → chunk-RYQCIY6F-BjIiApsk.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BJBqa6Xc.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-BuN9-7AR.js → cose-bilkent-JH36ORCC-huHqH6WQ.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-Bw22jc2k.js → cynefin-VYW2F7L2-BSi6yZqP.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BHnSH8Dr.js → cynefinDiagram-MW4NZA55-Bs_Jp31y.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BoXXIegj.js → dagre-VZM6K2ZE-CYxavikT.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CU8qyPhT.js → diagram-7IWD3JNH-B6TErl71.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-lrjhF0S8.js → diagram-B4RE2ZJO-CvH4J2ii.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DL0QDEpo.js → diagram-LBJQPF4R-v1NBAqXS.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DxVMJMBH.js → diagram-Q27KOJAE-CUNHVAn2.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-CFg9FzvG.js → diagram-UB23O5K3-Dzz1gUu-.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CQgP9fTG.js → ebnfDiagram-BXEA7PRR-CCF8_LjK.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-A5vQXx9U.js → erDiagram-JOGREHBK-DObdPVLa.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-ytXnLyXD.js → flowDiagram-UKHOOZJN-DlN8Pxrj.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CYuksfnS.js → ganttDiagram-PKOTCBZU-BJKIPTGX.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-f_jW3zgU.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-C3HLE-xV.js → infoDiagram-6WML65LV-BKrRKMww.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DwpgejS6.js → ishikawaDiagram-WSZJBQD7-CN5dk-yb.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-ll0YWX1y.js → journeyDiagram-NVQOT4AX-B4P4KZ-Y.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Hq3rchvU.js → kanban-definition-27J2QSJJ-BRlteP32.js} +1 -1
- package/dist/worker/console/static/assets/{linear-BaGjJx8z.js → linear-CG8D9fuL.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-CKGQHWX_.js → mermaid.core-BuB6P2rX.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DM1FA6Dr.js → mindmap-definition-FAOFIHXS-DYXGl_DR.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Xa9fHkE2.js → pegDiagram-VL7TDLO6-BM48yEVG.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-pCd4PDqJ.js → pieDiagram-7S7Q4E2Y-mT8NL-Ow.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-KqjpEBLk.js → quadrantDiagram-CIZ2JOQS-C4pZ6DH_.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DgvR7LZD.js → railroadDiagram-AXF67PYL-BKAcr70m.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-Bys1UCWA.js → requirementDiagram-LRYGKXZP-CRxcKpoO.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Ms9npnZt.js → sankeyDiagram-W5VNT64P-Ds4LxQDI.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DEIWrtQZ.js → sequenceDiagram-SI44F4Z6-CPLwPf_p.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DELJ0AhZ.js → sizeCapture-X5ZJPWSS-CL65uij0.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BpHt9wKh.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-GKRsBluT.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-Cwsq1DxL.js → timeline-definition-Z64GVDOM-Dw85f9L2.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-CfaqtKx0.js → vennDiagram-T6HMQDX7-B4QLCqCy.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-BlEUtK_g.js → wardleyDiagram-T6FBY63Y-B_yKCWwn.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CHSRXPvO.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/spatial-overlay.js +1 -2
- 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 +18 -12
- package/dist/workflows/dag/init-hybrid.js +32 -9
- package/dist/workflows/dag/types.js +13 -0
- package/docs/architecture/runtime-boundaries.md +2 -1
- package/docs/templates/agent-dag.schema.json +18 -0
- package/docs/templates/backend-test-dag.json +27 -9
- 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-CrzAa3FA.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-B7QwCCb4.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-B7QwCCb4.js +0 -1
- package/dist/worker/console/static/assets/index-BB6KxwT_.css +0 -1
- package/dist/worker/console/static/assets/index-D_wxbadT.js +0 -407
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BEeSswlv.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B2m_wca8.js +0 -8
- package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
- package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
|
@@ -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, {
|