@tea-agent/loop-agent 0.42.0-next.7 → 0.42.0-next.8
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 +17 -0
- package/dist/build-stamp.json +3 -3
- package/dist/executors/shell-executor.js +3 -1
- package/dist/worker/console/chat/pi-runtime.js +20 -4
- package/dist/worker/console/chat/routes.js +44 -22
- package/dist/worker/console/chat/session-store.js +16 -0
- package/dist/worker/console/server.js +19 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-BQBHX31n.js → abnfDiagram-N423BO3Z-C6n9_m0P.js} +1 -1
- package/dist/worker/console/static/assets/{arc-MSJ199eR.js → arc-DQh-IfZ1.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DiRq2qMX.js → architectureDiagram-T3A2C74G-54NnrwUC.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-rlaxFOvi.js → blockDiagram-VBNYF7ZC-pivRALGK.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BSpi9ump.js → c4Diagram-5PPSVZJV-BR7OV2NJ.js} +1 -1
- package/dist/worker/console/static/assets/channel-DsZxrgqe.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-BN8VNeh5.js → chunk-2GRJ4B5K-B1Aq6BcK.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CDa1OVRA.js → chunk-2Q5K7J3B-CbdU0rjo.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-zxMQ5b8E.js → chunk-5RXB4S5H-Dqi2GJeD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-XTqNlzH4.js → chunk-5VM5RSS4-BYn1Hu4R.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DpZQfFTq.js → chunk-6Q2QTUOP-DRLjDL0k.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-DPv743zu.js → chunk-GF5L2VYU-CY9Xx2jV.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CFsCFoF4.js → chunk-JWPE2WC7-BNCZs7_z.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CV__aJTt.js → chunk-KBJHAD2P-DZ8AStLL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BshKlNir.js → chunk-RYQCIY6F-DsxjYrzz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-B-A3ErBP.js → chunk-XXDRQBXY-Ddx1KC1l.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CuToPeGV.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CuToPeGV.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-25xj8928.js → cose-bilkent-JH36ORCC-W9TveCnK.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DFmv38cl.js → cynefin-VYW2F7L2-l9j_ztZH.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-hReuWDQP.js → cynefinDiagram-MW4NZA55-BMJMKi4G.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-C9X3YPUI.js → dagre-VZM6K2ZE-Bb4mG9pH.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CAVmqjg9.js → diagram-7IWD3JNH-BMgL_Qv0.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-DYNlLsIm.js → diagram-B4RE2ZJO-Bvo2T4OQ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BP5mlbfb.js → diagram-LBJQPF4R-_5kWRN9c.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-KWOHK5ZM.js → diagram-Q27KOJAE-DqdMrltM.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-D25Ro5y-.js → diagram-UB23O5K3-CDDYsNkp.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-kLaahtbh.js → ebnfDiagram-BXEA7PRR-c4nfnZUV.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-1tgKuLez.js → erDiagram-JOGREHBK-DnkUcNMs.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DARr-Cvn.js → flowDiagram-UKHOOZJN-Dz0KGLZE.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-BgwjBv_V.js → ganttDiagram-PKOTCBZU-Cj1t1uka.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DneIlYSI.js → gitGraphDiagram-DS77QQ5N-tp2FrBHd.js} +1 -1
- package/dist/worker/console/static/assets/{index-Dkv0ezuE.js → index-D9Sc0f0y.js} +84 -84
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DA7ATqY6.js → infoDiagram-6WML65LV-DQwJS8DH.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DnOS-E1Z.js → ishikawaDiagram-WSZJBQD7-eimCQWD4.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-C8JnwJ_s.js → journeyDiagram-NVQOT4AX-Dd9Gbwgv.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Cw0_OjEC.js → kanban-definition-27J2QSJJ-Qve3cyft.js} +1 -1
- package/dist/worker/console/static/assets/{linear-mrxq3fyn.js → linear-UXKSe36Z.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-Bagus6zF.js → mermaid.core-CWhj4JXN.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-Bf95bLuW.js → mindmap-definition-FAOFIHXS-yTcwf4SJ.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BvtUW6w2.js → pegDiagram-VL7TDLO6-_7qToaZP.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CbWtT-Ry.js → pieDiagram-7S7Q4E2Y-CXmrKmDm.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-ctnxxIdD.js → quadrantDiagram-CIZ2JOQS-hMmrJyaS.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BZ7Z3X0-.js → railroadDiagram-AXF67PYL-BXw8tCBe.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BMX1xnIy.js → requirementDiagram-LRYGKXZP-BmjgnLZl.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-MShOQznz.js → sankeyDiagram-W5VNT64P-Bj77SPpN.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CTGOazaB.js → sequenceDiagram-SI44F4Z6-B2FDVysL.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-zGbfM4nV.js → sizeCapture-X5ZJPWSS-UChNY9ZZ.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Brf8Wwzr.js → stateDiagram-OKZ733FA-wbAEkbd7.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-yPoT19ft.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CvNw3ZqF.js → swimlanes-SLNWSIFB-DCEkU8HR.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-VWdarchG.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-z2LyZpDt.js → timeline-definition-Z64GVDOM-BGp7H06U.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-Bc_coprH.js → vennDiagram-T6HMQDX7-DsCIQuWR.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-M1NSmWq-.js → wardleyDiagram-T6FBY63Y-cRZLP4Xe.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Ct0rjGXW.js → xychartDiagram-ELKLHX3M-CP0xLR9Y.js} +1 -1
- package/dist/worker/console/static/index.html +1 -1
- package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +10 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +31 -2
- package/dist/worker/console/static-src/operator-chat/useComposer.js +8 -3
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +29 -6
- package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +8 -2
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +40 -9
- package/dist/workflows/dag/backend-test-scenario-param.js +126 -19
- package/dist/workflows/dag/backend-test-scenario-partitions.js +62 -1
- package/dist/workflows/dag/backend-test-writer-completeness.js +7 -3
- package/dist/workflows/dag/init-hybrid.js +23 -3
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-BdTaMnYP.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Cid7CSRK.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Cid7CSRK.js +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-CIkoculx.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-pJ-V5EdT.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,8 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
- 修复 Operator Chat 打开已丢失会话时把孤儿 JSONL 升级成 503、以及删会话后残留 workspace 选择被误报为跨工作区冲突的问题:缺失会话文件现在自愈为 404 并清掉记录,前端恢复路径安静忘记该会话。
|
|
5
6
|
- 修复前端 `--from-text` 任务缺少 source-fidelity ledger、DAG 生成后降级为 v1 并在 `frontend-contract-pi` 0ms 失败的问题:文本入口现在持久化可校验的 v2 绑定输入,init-hybrid 复用任务自有需求源;Console 默认模型与 Pi readiness 同时排除无凭据 provider,避免把不可执行模型误报为可用。
|
|
6
7
|
- 常规回归 `npm test` 默认跳过约 6 分钟的 I/O-heavy 测试池(仍跑 fast + integration);完整三池改为 `npm run test:full` / `LOOP_AGENT_FULL_TEST=1`。本地 `ci.sh`、GitHub PR 与 release/next 发布门禁仍跑全量,不降低交付验证。
|
|
8
|
+
- 修复 backend-test 把 `pytest.param({"title": ""})` 整段 dict 当成 empty 观察、且 `example=` 空值导致 `target=body.title` 解析失败的问题:空 example 仍解析 field,dict 内空字符串按字段 MATCH。
|
|
9
|
+
- 修复 backend-test 把自动化映射多写的横切测试点当成 Markdown BLOCKED、挡住 N11 修 docstring 的问题:只拦 `### 测试点` 未恰好绑定一次。
|
|
10
|
+
- 修复 backend-test 把 pytest `_MISSING` 哨兵当成普通 Name、可选 `min; bound=0` UNDETERMINED 的问题:`_MISSING` 与 `_OMIT` 同为省略键。
|
|
11
|
+
- 修复 backend-test 把可选字段 `min; bound=0` 的 `_OMIT` 判成 UNDETERMINED 的问题:省略键视为空最小;`OMITTED` TP 视为 missing。
|
|
12
|
+
- 修复 backend-test 对 `http_client(operation, json_body=dict)` 观察不到 payload 的问题:http-like Name-call 的第一参是参数化 method 变量时仍计入 `json_body`。
|
|
13
|
+
- 修复 backend-test 把 Markdown `Payload Required Paths: false` 当成路径、GET filter 整 Case UNSAFE 的问题:`true`/`false` 与 `none` 一样不是 path。
|
|
14
|
+
- 修复 backend-test 把列表反引号里的 `场景意图: ... bound=0` 解析失败、并把 `max+1` 的数字 1 当成 minLength 的问题:围栏行可解析,`+/-` 后缀数字不进 prose 窗。
|
|
15
|
+
- 修复 backend-test 把 fixture `http("POST", path, json_body={"title": ...})` 当成无 payload、整 Case PAYLOAD_SHAPE_MISMATCH 的问题:首参为 HTTP method 的 Name-call 进入 observedPaths。eligibility 门禁不放宽。
|
|
16
|
+
- 修复 backend-test 把 `intent=min; bound=0` 当成缺 bound 并落到 `maxLength`、导致空 content MISMATCH 的问题:无 `minLength=` / TP LEN 时保留 0;`max; bound=0` 仍是哨兵。
|
|
17
|
+
- 修复 backend-test 把 evidence-only pytest stub(模块 docstring + Case-ID、无 `def test_`)当成截断脚本、N9 `incomplete-write-set` 的问题:闭合 stub 可通过 completeness,半截 `def (` 仍 fail-closed。
|
|
18
|
+
- 修复 backend-test 把 Markdown 机器行 `intent=max-1; bound=99` 当成契约 max、导致 `x*99` MISMATCH 的问题:`max-1`/`max+1`/`min-1` 优先 `maxLength=` 与文案三元组。eligibility 门禁不放宽。
|
|
19
|
+
- 修复 backend-test 把 pytest 多写、Markdown 没有的 `0:1` extra symbol 当成 Markdown Test Point binding 缺陷并 BLOCKED 的问题:这类条目进入 N11 删除多余函数,不再清空 pytest repair。
|
|
20
|
+
- 修复 backend-test N12 只读 effective collection 再次跑 scenario-param 确定性写回、在 `filesystem-only` 下 `write-guard` 失败的问题:N12 只复验,不再改 pytest。N10 仍可修一次。
|
|
21
|
+
- 修复 backend-test 把 `脚本:无` 的 evidence-only Case 当成缺 pytest 符号送进 N11 的问题:精确 1:0 元用例不再触发 `missing-pytest-symbol` repair,N11 不得发明业务函数。真缺符号的 1:0 仍可修。eligibility 门禁不放宽。
|
|
22
|
+
- 修复 backend-test 把 Scenario Partitions 数据行的 exact `TP-SP-...` 清单写成第 8 列、导致 N6 `MISSING_PARTITION` 的问题:仅当尾列全是该 Partition 的 slot ID 时确定性裁成 7 列并写回 run-owned plan。7 列契约与非 slot 多余列 fail-closed 不放宽。
|
|
23
|
+
- 修复 backend-test scenario 把 `intent=max-1` 当成 unknown、以及 Markdown 只写「100 个字符的最大 / 1999、2000、2001」时解析不到 bound 的问题:`max-1` 进入 closed set,长度清单三元组与「N 个字符的最大」可得到 MATCH。eligibility 门禁不放宽。
|
|
7
24
|
- 修复 backend-test correspondence 把前面函数的 `pytest.param(..., id="TP-...")` 叠进后续 Case `parameterIds` 的问题:decorator 区域遇到上一 `def`/`class` 或非 decorator 续行即停,不再把整组打成 `TEST_POINT_BINDING_EXTRA`。eligibility 门禁不放宽。
|
|
8
25
|
- 修复 backend-test scenario facts 把内部 max/min/oversize helper 哨兵 `-1/-2/-3` 写成 `observedLength`、导致 N10 在 schema `min(0)` 上 `invalid-output` 的问题:这些 helper 仍按 Markdown bound MATCH,持久化长度只保留非负值。
|
|
9
26
|
- 修复 backend-test 把 GET `params=`/`query=` 过滤字段、Python `True`/`False` 布尔字面量和混合大小写 `pytest.param` 列表漏出 correspondence/payload/scenario 观察的问题:这些 variant 现在可以按 item 授权,而不再把整 Case 打成 `PAYLOAD_SHAPE_MISMATCH` / `VARIANT_PARAMETER_MISSING`。eligibility 门禁不放宽。
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.42.0-next.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-09-
|
|
3
|
+
"version": "0.42.0-next.8",
|
|
4
|
+
"gitSha": "1d1ada8ede350e5778d753c04ed72bacd778e43d",
|
|
5
|
+
"builtAt": "2026-09-02T23:47:25.236Z"
|
|
6
6
|
}
|
|
@@ -58,6 +58,7 @@ import { readProjectGovernanceContext } from "../workflows/dag/project-governanc
|
|
|
58
58
|
import { assertMavenPlanFresh, MavenPlanStaleError, } from "../verification/maven/index.js";
|
|
59
59
|
async function runBackendScenarioParamPreflight(input) {
|
|
60
60
|
const outputs = [];
|
|
61
|
+
const allowRepair = input.allowRepair !== false;
|
|
61
62
|
const initial = await assessBackendScenarioParamConsistency({
|
|
62
63
|
workspaceRoot: input.workspaceRoot,
|
|
63
64
|
phase: "initial",
|
|
@@ -73,7 +74,7 @@ async function runBackendScenarioParamPreflight(input) {
|
|
|
73
74
|
outputs.push(`scenarioParamInitial=${initialArtifacts.reportPath}`);
|
|
74
75
|
let finalFacts;
|
|
75
76
|
let finalMarkdown;
|
|
76
|
-
if (initial.facts.repairEligible) {
|
|
77
|
+
if (allowRepair && initial.facts.repairEligible) {
|
|
77
78
|
const repair = await applyDeterministicScenarioParamRepairs({
|
|
78
79
|
workspaceRoot: input.workspaceRoot,
|
|
79
80
|
facts: initial.facts,
|
|
@@ -979,6 +980,7 @@ async function executeBackendTestPipeline(input, meta) {
|
|
|
979
980
|
workspaceRoot: input.cwd,
|
|
980
981
|
runDir: meta.runDir,
|
|
981
982
|
layout: backendLayout,
|
|
983
|
+
allowRepair: false,
|
|
982
984
|
strictScenarioParamGate: Boolean((meta.spec.globalConstraints ?? []).some((item) => /strictScenarioParamGate\s*=\s*true/i.test(item))),
|
|
983
985
|
});
|
|
984
986
|
outputs.push(...scenario.outputs);
|
|
@@ -2347,6 +2347,16 @@ export class ConsolePiRuntime {
|
|
|
2347
2347
|
});
|
|
2348
2348
|
}
|
|
2349
2349
|
catch (error) {
|
|
2350
|
+
const code = error && typeof error === "object" && "code" in error
|
|
2351
|
+
? String(error.code ?? "")
|
|
2352
|
+
: "";
|
|
2353
|
+
if (code === "SESSION_FILE_MISSING" || code === "ENOENT") {
|
|
2354
|
+
return {
|
|
2355
|
+
ok: false,
|
|
2356
|
+
code: "NO_SESSION_FILE",
|
|
2357
|
+
message: `Pi session file missing or not openable: ${init.sessionFile}`,
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2350
2360
|
return {
|
|
2351
2361
|
ok: false,
|
|
2352
2362
|
code: "REOPEN_FAILED",
|
|
@@ -3228,13 +3238,19 @@ export function createDefaultPiSdkBindings() {
|
|
|
3228
3238
|
// wrong conversation under the durable Console sessionId. Fail closed
|
|
3229
3239
|
// before open when the persisted file is absent.
|
|
3230
3240
|
await access(opts.sessionFile);
|
|
3231
|
-
return sdk.SessionManager.open(opts.sessionFile);
|
|
3232
3241
|
}
|
|
3233
|
-
catch {
|
|
3234
|
-
|
|
3235
|
-
|
|
3242
|
+
catch (error) {
|
|
3243
|
+
const code = error && typeof error === "object" && "code" in error
|
|
3244
|
+
? String(error.code ?? "")
|
|
3245
|
+
: "";
|
|
3246
|
+
if (code === "ENOENT") {
|
|
3247
|
+
throw Object.assign(new Error(`SESSION_FILE_MISSING: ${opts.sessionFile}`), { code: "SESSION_FILE_MISSING", cause: error });
|
|
3248
|
+
}
|
|
3249
|
+
// File exists but is unreadable (permissions / I/O) — caller maps
|
|
3250
|
+
// undefined to 503 rather than silently creating a fresh session.
|
|
3236
3251
|
return undefined;
|
|
3237
3252
|
}
|
|
3253
|
+
return sdk.SessionManager.open(opts.sessionFile);
|
|
3238
3254
|
},
|
|
3239
3255
|
resolveModel: (opts) => {
|
|
3240
3256
|
const rt = opts.modelRuntime;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* Read routes (GET capabilities / sessions) are open to loopback.
|
|
14
14
|
*/
|
|
15
15
|
import { randomUUID } from "node:crypto";
|
|
16
|
+
import { access } from "node:fs/promises";
|
|
16
17
|
import { parseAssistantContent } from "./assistant-content.js";
|
|
17
18
|
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, } from "./tools.js";
|
|
18
19
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
@@ -474,7 +475,7 @@ function sendRuntimeUnavailable(res, error) {
|
|
|
474
475
|
* handled here — only reopen/init readiness failures.
|
|
475
476
|
*/
|
|
476
477
|
function mapReopenSessionFailure(reopen) {
|
|
477
|
-
if (reopen.code === "NO_SESSION_FILE") {
|
|
478
|
+
if (reopen.code === "NO_SESSION_FILE" || reopen.code === "SESSION_FILE_MISSING") {
|
|
478
479
|
return {
|
|
479
480
|
status: 404,
|
|
480
481
|
code: "PI_SESSION_NOT_FOUND",
|
|
@@ -494,6 +495,19 @@ function mapReopenSessionFailure(reopen) {
|
|
|
494
495
|
message: reopen.message,
|
|
495
496
|
};
|
|
496
497
|
}
|
|
498
|
+
/** Drop an orphan catalog record whose promised Pi JSONL is gone. */
|
|
499
|
+
async function healMissingSessionFile(deps, sessionId, reopen) {
|
|
500
|
+
if (reopen && reopen.code !== "NO_SESSION_FILE" && reopen.code !== "SESSION_FILE_MISSING") {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (typeof deps.store.remove !== "function")
|
|
504
|
+
return;
|
|
505
|
+
await deps.store.remove(sessionId).catch(() => undefined);
|
|
506
|
+
}
|
|
507
|
+
async function mapFailedReopen(deps, sessionId, reopen) {
|
|
508
|
+
await healMissingSessionFile(deps, sessionId, reopen);
|
|
509
|
+
return mapReopenSessionFailure(reopen);
|
|
510
|
+
}
|
|
497
511
|
export async function handleChatCapabilities(_req, res, deps) {
|
|
498
512
|
const toolSchemas = buildModelCallableToolSchemas();
|
|
499
513
|
sendJson(res, 200, {
|
|
@@ -738,10 +752,7 @@ export async function handleBranchChatSession(req, res, deps, sessionId) {
|
|
|
738
752
|
sessionFile: record.sessionFile,
|
|
739
753
|
});
|
|
740
754
|
if (!reopened.ok) {
|
|
741
|
-
const mapped =
|
|
742
|
-
code: reopened.code,
|
|
743
|
-
message: reopened.message,
|
|
744
|
-
});
|
|
755
|
+
const mapped = await mapFailedReopen(deps, sessionId, reopened);
|
|
745
756
|
sendJson(res, mapped.status, {
|
|
746
757
|
ok: false,
|
|
747
758
|
error: { code: mapped.code, message: mapped.message },
|
|
@@ -816,6 +827,29 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
816
827
|
});
|
|
817
828
|
return;
|
|
818
829
|
}
|
|
830
|
+
if (record.sessionFile) {
|
|
831
|
+
try {
|
|
832
|
+
await access(record.sessionFile);
|
|
833
|
+
}
|
|
834
|
+
catch (error) {
|
|
835
|
+
const code = error && typeof error === "object" && "code" in error
|
|
836
|
+
? String(error.code ?? "")
|
|
837
|
+
: "";
|
|
838
|
+
if (code === "ENOENT") {
|
|
839
|
+
await healMissingSessionFile(deps, sessionId, {
|
|
840
|
+
code: "NO_SESSION_FILE",
|
|
841
|
+
});
|
|
842
|
+
sendJson(res, 404, {
|
|
843
|
+
ok: false,
|
|
844
|
+
error: {
|
|
845
|
+
code: "PI_SESSION_NOT_FOUND",
|
|
846
|
+
message: `Pi session file missing or not openable: ${record.sessionFile}`,
|
|
847
|
+
},
|
|
848
|
+
});
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
819
853
|
await deps.operationLinker.recoverSession(sessionId);
|
|
820
854
|
const composerDraft = await new ComposerDraftStore(deps.appData).get(sessionId);
|
|
821
855
|
const snapshot = deps.events.snapshot(sessionId);
|
|
@@ -1494,10 +1528,7 @@ export async function handleReopenChatSession(req, res, deps, sessionId) {
|
|
|
1494
1528
|
: {}),
|
|
1495
1529
|
});
|
|
1496
1530
|
if (!result.ok) {
|
|
1497
|
-
const mapped =
|
|
1498
|
-
code: result.code,
|
|
1499
|
-
message: result.message,
|
|
1500
|
-
});
|
|
1531
|
+
const mapped = await mapFailedReopen(deps, sessionId, result);
|
|
1501
1532
|
sendJson(res, mapped.status, {
|
|
1502
1533
|
ok: false,
|
|
1503
1534
|
error: { code: mapped.code, message: mapped.message },
|
|
@@ -1583,10 +1614,7 @@ export async function handleChatPrompt(req, res, deps, sessionId) {
|
|
|
1583
1614
|
: {}),
|
|
1584
1615
|
});
|
|
1585
1616
|
if (!reopen.ok) {
|
|
1586
|
-
const mapped =
|
|
1587
|
-
code: reopen.code,
|
|
1588
|
-
message: reopen.message,
|
|
1589
|
-
});
|
|
1617
|
+
const mapped = await mapFailedReopen(deps, sessionId, reopen);
|
|
1590
1618
|
sendJson(res, mapped.status, {
|
|
1591
1619
|
ok: false,
|
|
1592
1620
|
error: { code: mapped.code, message: mapped.message },
|
|
@@ -1855,10 +1883,7 @@ export async function handleCreateChatTurn(req, res, deps, sessionId, trustedPay
|
|
|
1855
1883
|
: {}),
|
|
1856
1884
|
});
|
|
1857
1885
|
if (!reopen.ok) {
|
|
1858
|
-
const mapped =
|
|
1859
|
-
code: reopen.code,
|
|
1860
|
-
message: reopen.message,
|
|
1861
|
-
});
|
|
1886
|
+
const mapped = await mapFailedReopen(deps, sessionId, reopen);
|
|
1862
1887
|
sendJson(res, mapped.status, {
|
|
1863
1888
|
ok: false,
|
|
1864
1889
|
accepted: false,
|
|
@@ -3050,7 +3075,7 @@ export async function ensureActiveSession(deps, sessionId) {
|
|
|
3050
3075
|
: {}),
|
|
3051
3076
|
});
|
|
3052
3077
|
if (!reopened.ok) {
|
|
3053
|
-
return { ok: false, ...
|
|
3078
|
+
return { ok: false, ...(await mapFailedReopen(deps, sessionId, reopened)) };
|
|
3054
3079
|
}
|
|
3055
3080
|
return { ok: true };
|
|
3056
3081
|
}
|
|
@@ -3997,10 +4022,7 @@ export async function handleChatCompact(req, res, deps, sessionId) {
|
|
|
3997
4022
|
: {}),
|
|
3998
4023
|
});
|
|
3999
4024
|
if (!reopened.ok) {
|
|
4000
|
-
const mapped =
|
|
4001
|
-
code: reopened.code,
|
|
4002
|
-
message: reopened.message,
|
|
4003
|
-
});
|
|
4025
|
+
const mapped = await mapFailedReopen(deps, sessionId, reopened);
|
|
4004
4026
|
sendJson(res, mapped.status, {
|
|
4005
4027
|
ok: false,
|
|
4006
4028
|
error: { code: mapped.code, message: mapped.message },
|
|
@@ -47,6 +47,16 @@ export function cleanChatTitle(value) {
|
|
|
47
47
|
function recordPath(appData, sessionId) {
|
|
48
48
|
return path.join(appData.chats, `${sessionId}.json`);
|
|
49
49
|
}
|
|
50
|
+
/** True when `sessionFile` lives inside this store's dedicated Pi JSONL dir. */
|
|
51
|
+
export function isConsoleOwnedSessionFile(appData, sessionFile) {
|
|
52
|
+
const value = sessionFile?.trim();
|
|
53
|
+
if (!value)
|
|
54
|
+
return false;
|
|
55
|
+
const root = path.resolve(appData.chatSessions);
|
|
56
|
+
const target = path.resolve(value);
|
|
57
|
+
const relative = path.relative(root, target);
|
|
58
|
+
return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
59
|
+
}
|
|
50
60
|
export class ChatSessionStore {
|
|
51
61
|
appData;
|
|
52
62
|
options;
|
|
@@ -263,8 +273,14 @@ export class ChatSessionStore {
|
|
|
263
273
|
const record = await this.get(sessionId);
|
|
264
274
|
if (!record)
|
|
265
275
|
return false;
|
|
276
|
+
const sessionFile = record.sessionFile;
|
|
266
277
|
await rm(recordPath(this.appData, sessionId), { force: true });
|
|
267
278
|
this.options.onRecordChange?.(sessionId, undefined);
|
|
279
|
+
// Record first, then best-effort JSONL unlink. Final consistency is
|
|
280
|
+
// "both gone" — a leftover JSONL is harmless, a leftover record is not.
|
|
281
|
+
if (isConsoleOwnedSessionFile(this.appData, sessionFile) && sessionFile) {
|
|
282
|
+
await rm(sessionFile, { force: true }).catch(() => undefined);
|
|
283
|
+
}
|
|
268
284
|
return true;
|
|
269
285
|
});
|
|
270
286
|
}
|
|
@@ -567,8 +567,26 @@ export async function createConsoleServer(options) {
|
|
|
567
567
|
const stored = await context.chatRouteDeps.store.get(sessionId);
|
|
568
568
|
if (stored)
|
|
569
569
|
owner = context;
|
|
570
|
+
else if (!catalogEntry) {
|
|
571
|
+
// Catalog and store both miss: the session was deleted, not
|
|
572
|
+
// retargeted. Do not scan other workspaces or leak existence.
|
|
573
|
+
sendJson(res, 404, {
|
|
574
|
+
ok: false,
|
|
575
|
+
error: {
|
|
576
|
+
code: "PI_SESSION_NOT_FOUND",
|
|
577
|
+
message: `chat session not found: ${sessionId}`,
|
|
578
|
+
},
|
|
579
|
+
});
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
570
582
|
else {
|
|
571
|
-
|
|
583
|
+
chatSessionCatalog.remove(sessionId);
|
|
584
|
+
await registry
|
|
585
|
+
.detachSession(ownerRecord.workspaceId, sessionId)
|
|
586
|
+
.catch(() => undefined);
|
|
587
|
+
// Catalog had the id, but this workspace store does not.
|
|
588
|
+
// Keep the conflict code so a mismatched selection cannot
|
|
589
|
+
// discover whether the session lives elsewhere.
|
|
572
590
|
sendJson(res, 403, {
|
|
573
591
|
ok: false,
|
|
574
592
|
error: {
|
|
@@ -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-DRLjDL0k.js";import{p as f}from"./chunk-JWPE2WC7-BNCZs7_z.js";import{_ as n,l as o}from"./mermaid.core-CWhj4JXN.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-l9j_ztZH.js";import"./index-D9Sc0f0y.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-CWhj4JXN.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};
|