@tea-agent/loop-agent 0.42.0-next.7 → 0.42.0-next.9
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 +26 -0
- package/dist/application/dag/run-dag.js +40 -0
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +313 -56
- package/dist/executors/shell-executor.js +50 -20
- 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/worker/observe/routes.js +4 -0
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +58 -9
- package/dist/workflows/dag/backend-test-scenario-param.js +156 -20
- 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/frontend-recovery-plan.js +2 -1
- package/dist/workflows/dag/frontend-recovery-run.js +33 -5
- package/dist/workflows/dag/frontend-writer-admission.js +44 -10
- package/dist/workflows/dag/init-hybrid.js +26 -5
- package/dist/workflows/dag/node-execution.js +76 -0
- package/dist/workflows/dag/rerun-feedback.js +59 -0
- package/dist/workflows/dag/rerun-task.js +8 -2
- package/dist/workflows/dag/runner.js +18 -11
- package/dist/workflows/dag/scheduler.js +21 -6
- package/docs/templates/backend-test-dag.json +1 -1
- 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
|
@@ -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);
|
|
@@ -2297,19 +2299,38 @@ async function collectReviewRestartPhase(runDir, reviewNodeId) {
|
|
|
2297
2299
|
}
|
|
2298
2300
|
/** A+B (AC-009): deterministic §4.10 restart phase for a committed
|
|
2299
2301
|
* `request_design_changes` fact. Mirrors the review collector. */
|
|
2300
|
-
/**
|
|
2301
|
-
|
|
2302
|
-
async function collectDesignReviewFindingCount(runDir, designNodeId) {
|
|
2302
|
+
/** Read the committed design request as a bounded structured capsule. */
|
|
2303
|
+
async function collectDesignReviewFindings(runDir, designNodeId) {
|
|
2303
2304
|
try {
|
|
2304
2305
|
const records = await readTypedEventStoreFromJsonl(path.join(runDir, designNodeId, "design-typed-facts.jsonl"));
|
|
2305
2306
|
const request = records.find((record) => record.phase === "committed" &&
|
|
2306
2307
|
record.fact.kind ===
|
|
2307
2308
|
"request_design_changes");
|
|
2308
|
-
const
|
|
2309
|
-
|
|
2309
|
+
const fact = request?.fact;
|
|
2310
|
+
const findings = Array.isArray(fact?.findings)
|
|
2311
|
+
? fact.findings.flatMap((finding) => {
|
|
2312
|
+
if (!finding || typeof finding !== "object")
|
|
2313
|
+
return [];
|
|
2314
|
+
const value = finding;
|
|
2315
|
+
if (!(["Critical", "Important", "Minor", "Info"].includes(value.severity) &&
|
|
2316
|
+
typeof value.issue === "string" && value.issue.trim().length > 0))
|
|
2317
|
+
return [];
|
|
2318
|
+
return [{
|
|
2319
|
+
severity: value.severity,
|
|
2320
|
+
...(typeof value.file === "string" && value.file.trim() ? { file: value.file } : {}),
|
|
2321
|
+
...(typeof value.line === "number" && Number.isInteger(value.line) && value.line > 0 ? { line: value.line } : {}),
|
|
2322
|
+
issue: value.issue,
|
|
2323
|
+
...(typeof value.requiredChange === "string" && value.requiredChange.trim() ? { requiredChange: value.requiredChange } : {}),
|
|
2324
|
+
}];
|
|
2325
|
+
}).slice(0, 16)
|
|
2326
|
+
: [];
|
|
2327
|
+
const evidenceRefs = Array.isArray(fact?.evidenceRefs)
|
|
2328
|
+
? fact.evidenceRefs.filter((ref) => typeof ref === "string" && ref.trim().length > 0).slice(0, 16)
|
|
2329
|
+
: [];
|
|
2330
|
+
return { findings, evidenceRefs };
|
|
2310
2331
|
}
|
|
2311
2332
|
catch {
|
|
2312
|
-
return
|
|
2333
|
+
return { findings: [], evidenceRefs: [] };
|
|
2313
2334
|
}
|
|
2314
2335
|
}
|
|
2315
2336
|
async function collectDesignRestartPhase(runDir, designNodeId) {
|
|
@@ -2623,17 +2644,15 @@ async function executeFrontendWriterAdmission(input, meta) {
|
|
|
2623
2644
|
const shell = input.task.shell;
|
|
2624
2645
|
const config = shell.frontendWriterAdmission;
|
|
2625
2646
|
try {
|
|
2626
|
-
// 1. Design verdict handling
|
|
2647
|
+
// 1. Design verdict handling. The typed terminal
|
|
2627
2648
|
// verdict is read from the committed typed design terminal fact, not
|
|
2628
2649
|
// from the legacy first-line VERDICT text protocol (AC-003/AC-004).
|
|
2629
|
-
// A request_design_changes verdict
|
|
2630
|
-
//
|
|
2631
|
-
//
|
|
2632
|
-
//
|
|
2633
|
-
// write guard) and the final code review. A missing typed terminal
|
|
2634
|
-
// verdict still fails closed. In small topology the design review node
|
|
2635
|
-
// is absent and the check is vacuous.
|
|
2650
|
+
// A request_design_changes verdict blocks writer admission and is copied
|
|
2651
|
+
// into the receipt as a bounded advisory capsule for recovery. A missing
|
|
2652
|
+
// typed terminal verdict still fails closed. In small topology the design
|
|
2653
|
+
// review node is absent and the check is vacuous.
|
|
2636
2654
|
let verdictPass = true;
|
|
2655
|
+
let designRequested = false;
|
|
2637
2656
|
let designAdvisory;
|
|
2638
2657
|
if (config.designReviewFromNodeId) {
|
|
2639
2658
|
const designKinds = await collectDesignTerminalKinds(meta.runDir, config.designReviewFromNodeId);
|
|
@@ -2641,11 +2660,16 @@ async function executeFrontendWriterAdmission(input, meta) {
|
|
|
2641
2660
|
verdictPass = false;
|
|
2642
2661
|
}
|
|
2643
2662
|
else if (designKinds[0] !== "approve_design") {
|
|
2663
|
+
designRequested = true;
|
|
2664
|
+
const designFindings = await collectDesignReviewFindings(meta.runDir, config.designReviewFromNodeId);
|
|
2644
2665
|
designAdvisory = {
|
|
2645
|
-
verdict:
|
|
2666
|
+
verdict: "request_design_changes",
|
|
2646
2667
|
restartPhase: await collectDesignRestartPhase(meta.runDir, config.designReviewFromNodeId),
|
|
2647
|
-
findingCount:
|
|
2668
|
+
findingCount: designFindings.findings.length,
|
|
2669
|
+
findings: designFindings.findings,
|
|
2670
|
+
evidenceRefs: designFindings.evidenceRefs,
|
|
2648
2671
|
};
|
|
2672
|
+
verdictPass = false;
|
|
2649
2673
|
}
|
|
2650
2674
|
}
|
|
2651
2675
|
// 2. Read the canonical contract + design-policy result.
|
|
@@ -2713,7 +2737,9 @@ async function executeFrontendWriterAdmission(input, meta) {
|
|
|
2713
2737
|
allowedMockStrategies: config.allowedMockStrategies,
|
|
2714
2738
|
workspaceFiles,
|
|
2715
2739
|
});
|
|
2716
|
-
// 6. Design verdict enforcement:
|
|
2740
|
+
// 6. Design verdict enforcement: request_design_changes is a blocked
|
|
2741
|
+
// admission. This keeps the writer fail-closed until the recovery plan
|
|
2742
|
+
// has incorporated the reviewer's concrete findings.
|
|
2717
2743
|
const failureSource = policyRaw.classification === "blocked"
|
|
2718
2744
|
? "frontend-design-policy-shell"
|
|
2719
2745
|
: "frontend-writer-admission-shell";
|
|
@@ -2722,8 +2748,12 @@ async function executeFrontendWriterAdmission(input, meta) {
|
|
|
2722
2748
|
: [
|
|
2723
2749
|
...admission.findings,
|
|
2724
2750
|
{
|
|
2725
|
-
code:
|
|
2726
|
-
|
|
2751
|
+
code: designRequested
|
|
2752
|
+
? "design-review-requested"
|
|
2753
|
+
: "design-approval-missing",
|
|
2754
|
+
message: designRequested
|
|
2755
|
+
? "design review requested changes; writer admission is blocked until recovery incorporates the committed findings"
|
|
2756
|
+
: "design review typed terminal verdict missing or ambiguous (fail closed)",
|
|
2727
2757
|
},
|
|
2728
2758
|
];
|
|
2729
2759
|
const classification = findings.length === 0 && admission.classification === "accepted"
|
|
@@ -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};
|