@tea-agent/loop-agent 0.40.0-next.15 → 0.40.0-next.17
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/CHANGELOG.md +10 -0
- package/dist/build-stamp.json +3 -3
- package/dist/executors/shell-executor.js +30 -3
- package/dist/worker/console/chat/routes.js +12 -3
- package/dist/worker/console/chat/session-stats.js +96 -0
- package/dist/worker/console/chat/turn-process.js +10 -2
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-ZRowCaoB.js → abnfDiagram-N423BO3Z-Dy71QJp3.js} +1 -1
- package/dist/worker/console/static/assets/{arc-Bj6ZtQJ7.js → arc-M25fNMTE.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-n4cTQxyl.js → architectureDiagram-T3A2C74G-CUWlVl1a.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CrqqRR1r.js → blockDiagram-VBNYF7ZC-Dd0Whpx2.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-CUMa3_oJ.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-DTvksUI8.js → chunk-2GRJ4B5K-D_1sUkyD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-uLaMhsnm.js → chunk-2Q5K7J3B-Cxnxf36E.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-TNZa_h2Z.js → chunk-5RXB4S5H-D9RG3G_x.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DeT4DTvU.js → chunk-5VM5RSS4-Zz9jgjLX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DpDwrgBX.js → chunk-6Q2QTUOP-BCggDRCH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-7m3mc3kT.js → chunk-GF5L2VYU-CFg-5iAS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-qD6tz6st.js → chunk-JWPE2WC7-DRQTE8x_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DmxuvfwY.js → chunk-KBJHAD2P-C_Dw7uZ8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CtloYW08.js → chunk-RYQCIY6F-BjIiApsk.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Mt0SdMYe.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-CypzApsM.js → cose-bilkent-JH36ORCC-huHqH6WQ.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CdtlN9h7.js → cynefin-VYW2F7L2-BSi6yZqP.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-B5mmrWYJ.js → cynefinDiagram-MW4NZA55-Bs_Jp31y.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CuGLsIWX.js → dagre-VZM6K2ZE-CYxavikT.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-7K_sTV8C.js → diagram-7IWD3JNH-B6TErl71.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-C6uYQF8O.js → diagram-B4RE2ZJO-CvH4J2ii.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-iQEMjbjB.js → diagram-LBJQPF4R-v1NBAqXS.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-Da_RHa6E.js → diagram-Q27KOJAE-CUNHVAn2.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-DxSC07de.js → diagram-UB23O5K3-Dzz1gUu-.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DrcKS2O2.js → ebnfDiagram-BXEA7PRR-CCF8_LjK.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DwtF5lPU.js → erDiagram-JOGREHBK-DObdPVLa.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DvaYG3Dj.js → flowDiagram-UKHOOZJN-DlN8Pxrj.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CdvS2BFz.js → ganttDiagram-PKOTCBZU-BJKIPTGX.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-C90crnKQ.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-RFJJaIj1.js → infoDiagram-6WML65LV-BKrRKMww.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Ptyp28qF.js → ishikawaDiagram-WSZJBQD7-CN5dk-yb.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BOLs4CJr.js → journeyDiagram-NVQOT4AX-B4P4KZ-Y.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DmAd2lo5.js → kanban-definition-27J2QSJJ-BRlteP32.js} +1 -1
- package/dist/worker/console/static/assets/{linear-gYqIaDdo.js → linear-CG8D9fuL.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-D7l0d1KR.js → mermaid.core-BuB6P2rX.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CfEUCuOg.js → mindmap-definition-FAOFIHXS-DYXGl_DR.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DrsrmQAq.js → pegDiagram-VL7TDLO6-BM48yEVG.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B_BtPjTs.js → pieDiagram-7S7Q4E2Y-mT8NL-Ow.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DHdtYoZ0.js → quadrantDiagram-CIZ2JOQS-C4pZ6DH_.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-C3ZRzhji.js → railroadDiagram-AXF67PYL-BKAcr70m.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-C02rlD1p.js → requirementDiagram-LRYGKXZP-CRxcKpoO.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-uKJwyQoD.js → sankeyDiagram-W5VNT64P-Ds4LxQDI.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-Dy9LwdvZ.js → sequenceDiagram-SI44F4Z6-CPLwPf_p.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BZv-lCxE.js → sizeCapture-X5ZJPWSS-CL65uij0.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BoBhkFkN.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-MQ6V_d3o.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-1ewj4q0J.js → timeline-definition-Z64GVDOM-Dw85f9L2.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-C7tpjTmO.js → vennDiagram-T6HMQDX7-B4QLCqCy.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-9hGeqY7M.js → wardleyDiagram-T6FBY63Y-B_yKCWwn.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DgW7AyLR.js → xychartDiagram-ELKLHX3M-nniBEGv2.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -0
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +5 -1
- package/dist/workflows/dag/backend-test-result-contract.js +1 -1
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-CzEKG-cL.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BjVCAg3v.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BjVCAg3v.js +0 -1
- package/dist/worker/console/static/assets/index-CffSxmqh.css +0 -1
- package/dist/worker/console/static/assets/index-OwqawHso.js +0 -437
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-SrHPpkR3.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-vkKJWZ7P.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
- 修复 Console 对话页「轨迹」视图刷新页面后工具行耗时全部变成 0ms/消失的问题:会话恢复投影现在会从持久化事件环回填每次工具调用的真实起止时间(tool_call 发起 → tool_result 返回),刷新/重开历史会话后 bash、write 等工具行继续显示真实耗时(如 20.0s、16ms);事件环已裁剪的旧记录不再显示误导性的「0ms」而是留空。
|
|
6
|
+
- 修复 Console 对话页「轨迹」视图窄窗口(≤720px)下工具行耗时列被整体隐藏的问题:工具名列本身可收缩省略,无需靠隐藏耗时信息防挤爆,任何窗口宽度都显示耗时。
|
|
7
|
+
- Console 对话页「轨迹」视图新增每轮遥测头行(对标 DSH「请求 #N」记录):从服务端持久化事件环按轮折叠出步骤数、LLM 时长、首 token 延迟、解码吞吐(tok/s)、工具调用数与耗时、上下行 token(含缓存读/写计入上行)与成本,切到历史会话立即显示;「导出 HTML」同步输出该行。
|
|
8
|
+
- Console 对话页「轨迹」视图「展开」按钮改为按实际溢出显隐:渲染后实测文本宽度并用 ResizeObserver 跟随容器尺寸,拉宽面板后能放下的行不再显示按钮,收窄时自动恢复;展开态恒显「收起」。
|
|
9
|
+
- Console 对话页「轨迹」视图「会话注入」区在服务端冷启动 Pi 会话期间(首次打开历史会话约 1 秒)显示加载占位行,不再空白后突然出现;注入读取失败也会显示错误提示。
|
|
10
|
+
- 修复 Console 对话页轨迹/工具目录数据在多工作区控制台恒为空的问题:capabilities 请求补带 `?workspaceId=`(会话所属工作区优先),工具目录与注入区正常显示 61 个模型可见工具。
|
|
11
|
+
- 修复轨迹遥测只在收到流式事件后才显示的问题:会话切换/激活与重连恢复两条 hydrate 路径现在都会带上按轮遥测数据。
|
|
12
|
+
- Console 对话页「轨迹」视图新增「会话注入」区(对标 DSH SYSTEM 记录):在轨迹顶部展示真实注入 Pi 会话的系统提示词全文(含字符数与注入上下文 suffix)与模型可见工具目录(工具 ID、动作、描述),均可展开/收起;「导出 HTML」同步包含该区块,离线导出也能审查完整注入面。
|
|
5
13
|
- 修复 Console 对话页「轨迹」视图工具行(如 bash)展开后参数与结果仍被截断在 420 字符的问题:展开现在显示完整内容(块内滚动收纳长输出),并复用聊天工具卡同款的结果解包与参数格式化,HTML 导出同步生效。
|
|
6
14
|
- Operator Chat 输入框下方的「调用记录」入口现在会常驻显示;没有记录时显示为 0,发送消息或刷新运行状态时不再突然消失。
|
|
7
15
|
- 初始化选择模型时现在能识别公司内部 `wizard-local` 的 AICoder 型号梯度:`aicoder-default`、`aicoder-plus`、`aicoder-pro`、`aicoder-max` 从左到右能力逐级增强;它会作为选择 LOW/MED/HIGH 的参考,但不会忽略成本和项目需求机械分档。
|
|
@@ -53,6 +61,8 @@
|
|
|
53
61
|
|
|
54
62
|
### 修复
|
|
55
63
|
|
|
64
|
+
- 修复 backend-test 执行节点在 pytest 7.x 环境把 `@<targets-file>` 当作普通测试路径、导致 readiness 已授权 items 以 exit 4 全部无法执行的问题;控制器现在写入 run-owned Python launcher,由同一 Python 环境读取精确 targets 并调用一次 `pytest.main()`,不提高目标项目 pytest 最低版本,同时继续保留单次业务执行、excluded items 隔离和 exit/HTML fail-closed。
|
|
65
|
+
- 修复 backend-test 将 no-body Case 的 `Payload Required Paths: none` / `Payload Allowed Paths: none` 中空值标记误识别为 JSON 字段路径、继而把全部 pytest items 判为 payload `UNSAFE` 并排除的问题;独立 empty sentinel 现在归一化为空集合,真实 required path 冲突仍保持 fail-closed。
|
|
56
66
|
- 修复 Console「更新并初始化」被观测顶栏挡住、看起来像从 DAG 详情消失的问题:入口改到操作 → 设置,观测与对话页不再挂全局悬浮按钮。
|
|
57
67
|
- 修复从恢复打开全屏观测时,长 DAG run id 把「返回 恢复」顶进居中模式开关底下、按钮显示不全的问题;上下文 chip 改到顶栏下方独立一行,过长 id 省略、按钮不收缩。
|
|
58
68
|
- 修复 Console 内嵌观测后样式泄漏到对话/操作、观测顶栏丢失新鲜度与 Pi 状态、从恢复打开观测看不到「返回 恢复」、以及检查器盖住一级导航的问题;对话里的观测链接改为壳内地址。
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.40.0-next.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-08-
|
|
3
|
+
"version": "0.40.0-next.17",
|
|
4
|
+
"gitSha": "0d5709685941d99bb7d5870be034691e28a55b78",
|
|
5
|
+
"builtAt": "2026-08-30T16:21:21.166Z"
|
|
6
6
|
}
|
|
@@ -1230,7 +1230,33 @@ async function executeBackendTestPipeline(input, meta) {
|
|
|
1230
1230
|
const pytestTargetsRelative = "reports/backend-test-pytest-targets.txt";
|
|
1231
1231
|
const pytestTargetsAbsolute = path.join(meta.runDir, pytestTargetsRelative);
|
|
1232
1232
|
await writeFile(pytestTargetsAbsolute, `${eligibleItemIds.join("\n")}\n`, "utf8");
|
|
1233
|
-
const
|
|
1233
|
+
const pytestLauncherRelative = "reports/backend-test-pytest-launcher.py";
|
|
1234
|
+
const pytestLauncherAbsolute = path.join(meta.runDir, pytestLauncherRelative);
|
|
1235
|
+
await writeFile(pytestLauncherAbsolute, [
|
|
1236
|
+
"import os",
|
|
1237
|
+
"import pathlib",
|
|
1238
|
+
"import sys",
|
|
1239
|
+
"",
|
|
1240
|
+
"sys.path[0] = os.getcwd()",
|
|
1241
|
+
"import pytest",
|
|
1242
|
+
"",
|
|
1243
|
+
"if len(sys.argv) != 3:",
|
|
1244
|
+
" print('usage: backend-test-pytest-launcher.py <targets-file> <html-file>', file=sys.stderr)",
|
|
1245
|
+
" raise SystemExit(4)",
|
|
1246
|
+
"targets_path = pathlib.Path(sys.argv[1])",
|
|
1247
|
+
"html_path = pathlib.Path(sys.argv[2])",
|
|
1248
|
+
"try:",
|
|
1249
|
+
" targets = targets_path.read_text(encoding='utf-8').splitlines()",
|
|
1250
|
+
"except (OSError, UnicodeError) as error:",
|
|
1251
|
+
" print(f'backend-test targets unreadable: {error}', file=sys.stderr)",
|
|
1252
|
+
" raise SystemExit(4)",
|
|
1253
|
+
"if not targets or any(not target or target != target.strip() for target in targets):",
|
|
1254
|
+
" print('backend-test targets must contain non-empty exact pytest node IDs', file=sys.stderr)",
|
|
1255
|
+
" raise SystemExit(4)",
|
|
1256
|
+
"pytest_args = [*targets, '-v', '-p', 'no:cacheprovider', f'--html={html_path}', '--self-contained-html']",
|
|
1257
|
+
"raise SystemExit(pytest.main(pytest_args))",
|
|
1258
|
+
"",
|
|
1259
|
+
].join("\n"), "utf8");
|
|
1234
1260
|
// Split into short bash -c commands (aligned with markdown-environment).
|
|
1235
1261
|
// A single ultra-long compound command has been observed on Windows to
|
|
1236
1262
|
// exit 0xC0000142 (STATUS_DLL_INIT_FAILED) in ~40ms with empty stdout/
|
|
@@ -1307,10 +1333,11 @@ async function executeBackendTestPipeline(input, meta) {
|
|
|
1307
1333
|
'PYTHON_BIN="$(command -v python || command -v python3 || true)"',
|
|
1308
1334
|
'if [ -z "${PYTHON_BIN}" ]; then echo "python/python3 is required for backend-test execution" | tee -a "${DIAG_FILE}" >&2; exit 127; fi',
|
|
1309
1335
|
'echo "STEP=pytest-run"',
|
|
1310
|
-
`echo "- pytestCommand:
|
|
1336
|
+
`echo "- pytestCommand: controller launcher -> pytest.main(<${eligibleItemIds.length} eligibility-authorized-items>, -v, -p no:cacheprovider, --html=reports/backend-test.html, --self-contained-html)" >> "\${DIAG_FILE}"`,
|
|
1311
1337
|
`echo "- eligibleItemCount: ${eligibleItemIds.length}" >> "\${DIAG_FILE}"`,
|
|
1312
1338
|
`echo "- excludedItemCount: ${executionReadiness.excludedItems.length}" >> "\${DIAG_FILE}"`,
|
|
1313
|
-
|
|
1339
|
+
'rm -f "${HARNESS_DAG_RUN_DIR}/reports/backend-test.html" "${HARNESS_DAG_RUN_DIR}/reports/backend-test-pytest-native.html"',
|
|
1340
|
+
`PYTHONUTF8=1 PYTHONIOENCODING=utf-8 PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 "\${PYTHON_BIN}" "\${HARNESS_DAG_RUN_DIR}/${pytestLauncherRelative}" "\${HARNESS_DAG_RUN_DIR}/${pytestTargetsRelative}" "\${HARNESS_DAG_RUN_DIR}/reports/backend-test.html"`,
|
|
1314
1341
|
"STATUS=$?",
|
|
1315
1342
|
'printf "%s" "${STATUS}" > "${HARNESS_DAG_RUN_DIR}/reports/backend-test-pytest-exit.txt"',
|
|
1316
1343
|
'echo "- pytestExitCode: ${STATUS}" >> "${DIAG_FILE}"',
|
|
@@ -34,7 +34,7 @@ import { dispatchOperatorAction } from "../operator-actions.js";
|
|
|
34
34
|
import { makeHumanGateCard, } from "./human-gate-card.js";
|
|
35
35
|
import { ContractApplyReceiptStore } from "./contract-apply-receipt-store.js";
|
|
36
36
|
import { projectTaskContext } from "./context-panel.js";
|
|
37
|
-
import { deriveChatSessionTelemetry } from "./session-stats.js";
|
|
37
|
+
import { deriveChatSessionTelemetry, deriveChatTurnTelemetry } from "./session-stats.js";
|
|
38
38
|
import { contractApplyPayloadHash, issueHumanGateToken, verifyHumanGateToken, } from "../human-gate-token.js";
|
|
39
39
|
import { sendJson } from "../routes.js";
|
|
40
40
|
import { openSseResponse, writeSseEvent } from "../operation-sse.js";
|
|
@@ -99,8 +99,16 @@ export function projectStoredMessagesWithEventOrder(messages, events) {
|
|
|
99
99
|
}
|
|
100
100
|
return {
|
|
101
101
|
...message,
|
|
102
|
-
...(start
|
|
103
|
-
|
|
102
|
+
...(start
|
|
103
|
+
? {
|
|
104
|
+
eventSeq: start.seq,
|
|
105
|
+
turnId: start.turnId,
|
|
106
|
+
startedAt: start.at,
|
|
107
|
+
}
|
|
108
|
+
: {}),
|
|
109
|
+
...(finish
|
|
110
|
+
? { finishedSeq: finish.seq, finishedAt: finish.at }
|
|
111
|
+
: {}),
|
|
104
112
|
};
|
|
105
113
|
});
|
|
106
114
|
}
|
|
@@ -828,6 +836,7 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
828
836
|
hasBash: true,
|
|
829
837
|
sessionStats: telemetry.stats,
|
|
830
838
|
usage: telemetry.usage,
|
|
839
|
+
turnTelemetry: deriveChatTurnTelemetry(snapshot),
|
|
831
840
|
contextPressure: typeof deps.runtime.getContextPressureTelemetry === "function"
|
|
832
841
|
? deps.runtime.getContextPressureTelemetry(sessionId)
|
|
833
842
|
: undefined,
|
|
@@ -156,6 +156,102 @@ export function deriveChatSessionTelemetry(events) {
|
|
|
156
156
|
export function billedInputTokens(usage) {
|
|
157
157
|
return usage.inputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
|
|
158
158
|
}
|
|
159
|
+
export function deriveChatTurnTelemetry(events) {
|
|
160
|
+
const byTurn = new Map();
|
|
161
|
+
const turnOf = (turnId) => {
|
|
162
|
+
let entry = byTurn.get(turnId);
|
|
163
|
+
if (!entry) {
|
|
164
|
+
entry = {
|
|
165
|
+
turnId,
|
|
166
|
+
steps: 0,
|
|
167
|
+
llmMs: 0,
|
|
168
|
+
toolMs: 0,
|
|
169
|
+
toolCalls: 0,
|
|
170
|
+
samples: [],
|
|
171
|
+
};
|
|
172
|
+
byTurn.set(turnId, entry);
|
|
173
|
+
}
|
|
174
|
+
return entry;
|
|
175
|
+
};
|
|
176
|
+
const toolStarts = new Map();
|
|
177
|
+
for (const event of events) {
|
|
178
|
+
const at = eventTime(event);
|
|
179
|
+
const turn = turnOf(event.turnId);
|
|
180
|
+
if (event.kind === "usage") {
|
|
181
|
+
const sample = usageSample(event.data);
|
|
182
|
+
if (sample)
|
|
183
|
+
turn.samples.push(sample);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (event.kind === "user_message") {
|
|
187
|
+
if (turn.startedAt === undefined && at !== undefined)
|
|
188
|
+
turn.startedAt = at;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (event.kind === "agent_start") {
|
|
192
|
+
if (at !== undefined)
|
|
193
|
+
turn.stepStart = at;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (event.kind === "tool_call") {
|
|
197
|
+
turn.toolCalls += 1;
|
|
198
|
+
const toolCallId = event.data.toolCallId;
|
|
199
|
+
if (typeof toolCallId === "string" && toolCallId && at !== undefined) {
|
|
200
|
+
toolStarts.set(`${event.turnId}\u0000${toolCallId}`, at);
|
|
201
|
+
}
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (event.kind === "tool_result") {
|
|
205
|
+
const toolCallId = event.data.toolCallId;
|
|
206
|
+
if (typeof toolCallId === "string" && toolCallId && at !== undefined) {
|
|
207
|
+
const key = `${event.turnId}\u0000${toolCallId}`;
|
|
208
|
+
const startedAt = toolStarts.get(key);
|
|
209
|
+
if (startedAt !== undefined && at >= startedAt) {
|
|
210
|
+
turn.toolMs += at - startedAt;
|
|
211
|
+
}
|
|
212
|
+
toolStarts.delete(key);
|
|
213
|
+
// Next assistant step within the same turn starts after this tool.
|
|
214
|
+
turn.stepStart = at;
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (event.kind !== "message_end")
|
|
219
|
+
continue;
|
|
220
|
+
turn.steps += 1;
|
|
221
|
+
const recorded = stepTiming(event.data);
|
|
222
|
+
if (recorded?.llmMs !== undefined)
|
|
223
|
+
turn.llmMs += recorded.llmMs;
|
|
224
|
+
else if (at !== undefined &&
|
|
225
|
+
turn.stepStart !== undefined &&
|
|
226
|
+
at >= turn.stepStart) {
|
|
227
|
+
turn.llmMs += at - turn.stepStart;
|
|
228
|
+
}
|
|
229
|
+
if (recorded?.ttftMs !== undefined) {
|
|
230
|
+
turn.ttftMs = (turn.ttftMs ?? 0) + recorded.ttftMs;
|
|
231
|
+
}
|
|
232
|
+
if (recorded?.decodeMs !== undefined &&
|
|
233
|
+
recorded.decodeMs > 0 &&
|
|
234
|
+
recorded.outputTokens !== undefined) {
|
|
235
|
+
turn.decodeMs = (turn.decodeMs ?? 0) + recorded.decodeMs;
|
|
236
|
+
turn.decodeTokens = (turn.decodeTokens ?? 0) + recorded.outputTokens;
|
|
237
|
+
}
|
|
238
|
+
turn.stepStart = undefined;
|
|
239
|
+
}
|
|
240
|
+
return [...byTurn.values()].map((entry) => ({
|
|
241
|
+
turnId: entry.turnId,
|
|
242
|
+
steps: entry.steps,
|
|
243
|
+
llmMs: entry.llmMs,
|
|
244
|
+
toolMs: entry.toolMs,
|
|
245
|
+
toolCalls: entry.toolCalls,
|
|
246
|
+
...(entry.ttftMs !== undefined ? { ttftMs: entry.ttftMs } : {}),
|
|
247
|
+
...(entry.decodeMs !== undefined ? { decodeMs: entry.decodeMs } : {}),
|
|
248
|
+
...(entry.decodeTokens !== undefined
|
|
249
|
+
? { decodeTokens: entry.decodeTokens }
|
|
250
|
+
: {}),
|
|
251
|
+
usage: aggregateUsage(entry.samples),
|
|
252
|
+
...(entry.startedAt !== undefined ? { startedAt: entry.startedAt } : {}),
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
159
255
|
export function cacheHitPercent(usage) {
|
|
160
256
|
const billed = billedInputTokens(usage);
|
|
161
257
|
return billed > 0 ? Math.round((usage.cacheReadTokens / billed) * 100) : null;
|
|
@@ -72,14 +72,22 @@ export function hydrateSessionThread(raw) {
|
|
|
72
72
|
turnId = item.turnId;
|
|
73
73
|
if (!turnId)
|
|
74
74
|
turnId = `restored-tool-${item.id}`;
|
|
75
|
+
// Prefer event-ring timestamps (tool_call at → tool_result at) so
|
|
76
|
+
// refreshed sessions keep real elapsed durations instead of 0ms.
|
|
77
|
+
const startedAtMs = item.startedAt ? Date.parse(item.startedAt) : NaN;
|
|
78
|
+
const finishedAtMs = item.finishedAt ? Date.parse(item.finishedAt) : NaN;
|
|
75
79
|
const entry = {
|
|
76
80
|
id: item.toolCallId || item.id,
|
|
77
81
|
toolName: item.toolName || "tool",
|
|
78
82
|
status: item.isError === true ? "error" : "ok",
|
|
79
83
|
resultText: item.text,
|
|
80
84
|
result: item.text,
|
|
81
|
-
createdAt
|
|
82
|
-
|
|
85
|
+
createdAt: Number.isFinite(startedAtMs)
|
|
86
|
+
? startedAtMs
|
|
87
|
+
: createdAt,
|
|
88
|
+
finishedAt: Number.isFinite(finishedAtMs)
|
|
89
|
+
? finishedAtMs
|
|
90
|
+
: createdAt,
|
|
83
91
|
turnId: item.turnId ?? turnId,
|
|
84
92
|
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
85
93
|
...(item.finishedSeq === undefined
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-BCggDRCH.js";import{p as f}from"./chunk-JWPE2WC7-DRQTE8x_.js";import{_ as n,l as o}from"./mermaid.core-BuB6P2rX.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BSi6yZqP.js";import"./index-CS3QOTfl.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-BuB6P2rX.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|