@tea-agent/loop-agent 0.39.0-next.29 → 0.39.0-next.30
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 +2 -0
- package/README.md +1 -1
- package/dist/build-stamp.json +2 -2
- package/dist/commands/dag-rerun.js +55 -1
- package/dist/shared/dag-prompt-override.js +28 -0
- package/dist/shared/operator/capabilities.js +25 -0
- package/dist/worker/console/operator-actions.js +116 -0
- package/dist/worker/console/routes.js +40 -2
- package/dist/worker/console/security.js +13 -7
- package/dist/worker/console/server.js +26 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DGn9iNrd.js → abnfDiagram-N423BO3Z-CiGOV5eG.js} +1 -1
- package/dist/worker/console/static/assets/{arc-Dc0C2Nyv.js → arc-Ds9Gyfd8.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-COnz_Bhe.js → architectureDiagram-T3A2C74G-C6V6uC98.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-VhIP6vgf.js → blockDiagram-VBNYF7ZC-DezF7Ol9.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-D74lpmlb.js → c4Diagram-5PPSVZJV-BCWk3gCT.js} +1 -1
- package/dist/worker/console/static/assets/channel-DMvu1nmi.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-BxmiogQE.js → chunk-2GRJ4B5K-DbYr-Cxy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-C00Oi-2I.js → chunk-2Q5K7J3B-XSlusW4G.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DTrT1Vze.js → chunk-5RXB4S5H-BtcKAj9i.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DdKW7-fL.js → chunk-5VM5RSS4-BF57lhXj.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-D0q1WN6w.js → chunk-6Q2QTUOP-DJIlR25o.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-DBa14MSI.js → chunk-GF5L2VYU-DklNc7dm.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DkP-pEox.js → chunk-JWPE2WC7-fZNtEdQZ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-lgPogpcX.js → chunk-KBJHAD2P-BBgLqV4h.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-D-apZer0.js → chunk-RYQCIY6F-Dl9e5n_J.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-B1T2yAIe.js → chunk-XXDRQBXY-B0JK51NT.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DVzM-02m.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DVzM-02m.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-0P6hi3jF.js → cose-bilkent-JH36ORCC-Ch-ajv4O.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CntzMSR8.js → cynefin-VYW2F7L2-xn_NxcfB.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-C9zmXJtG.js → cynefinDiagram-MW4NZA55-DRD0fyga.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DfBCZqZw.js → dagre-VZM6K2ZE-COtnKp4B.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DLp-bhGL.js → diagram-7IWD3JNH-BQp_CAqG.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BksDcwZm.js → diagram-B4RE2ZJO-x0y-vNgq.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-Bdag7DYP.js → diagram-LBJQPF4R-N2ezwL31.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CoY5uNbk.js → diagram-Q27KOJAE-CSaxRH6Q.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-KcgrDXHt.js → diagram-UB23O5K3-6Ro7Kpbd.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CikErwJb.js → ebnfDiagram-BXEA7PRR-CrIIQEAI.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DqmwwzvZ.js → erDiagram-JOGREHBK-DivKcq8g.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-35krh9WG.js → flowDiagram-UKHOOZJN-BXrfDo8y.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CvTF1gJ4.js → ganttDiagram-PKOTCBZU-LTTQmMRJ.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-BiOWWClJ.js → gitGraphDiagram-DS77QQ5N-DP3o_5qd.js} +1 -1
- package/dist/worker/console/static/assets/{index-CqWlWE4l.js → index-C2jmYBfu.js} +71 -71
- package/dist/worker/console/static/assets/{index-Ya5FE7cD.css → index-C8rOIAJr.css} +1 -1
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Crha5dcA.js → infoDiagram-6WML65LV-wVfSY1WH.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DEtbscOZ.js → ishikawaDiagram-WSZJBQD7-BRKfFL0I.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-D2YYzx3z.js → journeyDiagram-NVQOT4AX-DEml3jLb.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C7x18ttQ.js → kanban-definition-27J2QSJJ-DTzBmOqN.js} +1 -1
- package/dist/worker/console/static/assets/{linear-CCLZkz45.js → linear-Cpy1d873.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-Dmy4lSGv.js → mermaid.core-C1cSavOy.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CmvIol59.js → mindmap-definition-FAOFIHXS-BEBSKvYM.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DVpEdirN.js → pegDiagram-VL7TDLO6-BrLs4Oac.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-cKQy456v.js → pieDiagram-7S7Q4E2Y-B47AZcLa.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-bx06I38m.js → quadrantDiagram-CIZ2JOQS-s0dVeYR2.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BjfIVIJr.js → railroadDiagram-AXF67PYL-lW8aJ7Q6.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DcuPGbKM.js → requirementDiagram-LRYGKXZP-BcHJPf6Q.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DvgVeDoV.js → sankeyDiagram-W5VNT64P-DdegpUUf.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DLBG9nm-.js → sequenceDiagram-SI44F4Z6-BxFWqNv8.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-D33L7FBF.js → sizeCapture-X5ZJPWSS-cOdUDPbR.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-hvqD9TpS.js → stateDiagram-OKZ733FA-DpxlYl8P.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BwecGAkM.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BtjH81Mz.js → swimlanes-SLNWSIFB-DQOfurE0.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D5WW_LbN.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CJ47Kraf.js → timeline-definition-Z64GVDOM-CIp3tC6V.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-COVPl-wh.js → vennDiagram-T6HMQDX7-C-adIPKn.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CCoQJLUY.js → wardleyDiagram-T6FBY63Y-CiYrar9M.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DTWJvfAd.js → xychartDiagram-ELKLHX3M-WHrdTV0-.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/observe/routes.js +12 -3
- package/dist/worker/observe/static/api.js +58 -0
- package/dist/worker/observe/static/styles.css +70 -0
- package/dist/worker/observe/static/views/dag-inspector.js +315 -2
- package/dist/workflows/dag/rerun-plan.js +112 -0
- package/dist/workflows/dag/rerun-run.js +58 -6
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-DWcZjWB3.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-IjoI3dqU.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-IjoI3dqU.js +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-C6MII0D1.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D_tk0V8D.js +0 -8
package/AGENTS.md
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
4. 涉及测试纪律/验证声明/调试时继续读:`docs/governance/harness-methodology-*.md`。
|
|
42
42
|
5. 查看最近提交、相关 plan/progress/report;`git status --short --branch`;跑最小基线验证。
|
|
43
43
|
6. 后端/接口/pytest → `taskKind: "backend-test"`(不是 `--profile`);知识回写 `knowledge-sync`;图谱开荒 `knowledge-graph-bootstrap`。`--profile` 仅 `auto|minimal|standard|reviewed|supervised`。
|
|
44
|
-
7. 看板/observe → `agent-worker console`(默认 repo=当前目录、port=8790;listen 成功后默认打开系统浏览器,`--no-open` 禁止)(`/inspect/`
|
|
44
|
+
7. 看板/observe → `agent-worker console`(默认 repo=当前目录、port=8790;listen 成功后默认打开系统浏览器,`--no-open` 禁止)(`/inspect/` 只读;唯一实验例外:`HARNESS_DAG_RERUN_PROMPT_OVERRIDE=1` 时节点 inspector 出现「提示词重启」tab 并注入 mutation token,默认关闭时零 token 零 tab);`observe serve` 已下线(`OBSERVE_SERVE_REMOVED` + exit 2);`observe snapshot` 仍可用。
|
|
45
45
|
8. 分支合并 → 先读 `docs/operations/branch-merge-guideline.md`。
|
|
46
46
|
9. 涉及版本发布、npm 渠道、release 分支、GitHub Actions 发布链或 dist-tag → 先读 `docs/operations/version-and-release-management.md`。
|
|
47
47
|
|
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
### 新增
|
|
20
20
|
|
|
21
|
+
- Operator Chat 时间线左缘新增「用户消息锚点栏」:每个用户输入一枚横向小条(12×3px 微圆角),紧凑等距排列并在时间线高度内垂直居中;条数超出栏高时相邻锚点自动聚合为稍宽的聚合条(悬停展开「N 条聚合输入」逐条列表,时间 + 单行预览,逐条点击定位)。悬停时小条向对话一侧平滑伸长(12→18px)并变橙,浮窗右侧弹出(白底圆角,正文最多 3 行、超出省略号,附序号与时间);单击平滑滚动定位到对应消息(精确停靠在视口顶部偏移 8px);覆盖视口顶部的锚点保持高亮。空会话自动隐藏;历史分页/流式更新/窗口缩放时自动重算(rAF 节流)。
|
|
22
|
+
- 实验能力「编辑失败节点提示词后从节点重跑」(默认关闭):内部开关 `HARNESS_DAG_RERUN_PROMPT_OVERRIDE=1` 启用后,`dag rerun` 支持 `--prompt-override <nodeId>@<file>`(全文替换)与 `--prompt-override-append <nodeId>@<file>`(追加指令:保留冻结原提示词,末尾追加 `<operator_addendum>` 块)。仅限 ERROR 且位于 reset closure 内的节点;mode + base/最终 prompt sha256 计入 planHash(execute 漂移即 `PLAN_DRIFT`),父 run spec 冻结、provenance(含 mode)落 `continuation.promptOverrides`。Console 新增 `dagPromptOverrideConfig` 开关探测 action,`dagRerunPlan`/`dagRerun` 接受 `promptOverrides`(`{nodeId, prompt, mode?}`);Inspect DAG 节点 inspector 新增「提示词重启」tab——默认「追加指令」模式(只读底稿 + 追加编辑器),可切换「全文替换(高级)」,预检通过展示执行估算,提交后续跑并跳转新 run,全程不离开图页;开关开启时 `/inspect` 只注入 **scoped** 变体凭据(独立 cookie + `__INSPECT_MUTATION_TOKEN__`,与 Console 通用 token 互不可重放),mutations 路由对 inspect 凭据仅放行 `dagRerunPlan`/`dagRerun`(其余 action 403 `ACTION_NOT_IN_INSPECT_SCOPE`),Inspect 不获得通用写能力;开关关闭时不注入任何 token、tab 不出现,检视面保持严格只读。
|
|
21
23
|
- 观察面 DAG Inspector 节点详情适配 Pi 扩展:执行器输入摘要展示节点声明的 `piExtensions` 短 id;新增「Pi 扩展运行事实」展示 `pi-extensions.json` 的 resolved(包名@版本)与 missing 降级原因(缺包降级不再静默);产物未生成/损坏时降级提示不阻断接口,绝对路径不外泄。
|
|
22
24
|
- 后端实现 DAG(standard / review-gated / supervised)的 Pi 节点支持按桶显式加载本机 Pi 导航扩展:读侧节点(除 closeout)加载 `pi-codegraph` + `pi-lens`,写侧节点只加载 `pi-codegraph`(pi-lens 的 `ast_grep_replace` 可绕过 writeSet,不加载);前端/测试模板与省略字段节点保持扩展全关。扩展发现始终关闭,只经白名单解析 `~/.pi/agent` 与项目 `.pi` settings 的已装包(缺包降级不失败,产物 `pi-extensions.json` 记录 requested/resolved/missing);session 后 pin 工具面剔 builtin 同名、deny 面与写工具,writer 的 `edit`/`write` 仍为 policy-wrapped;`.codegraph/**` index 同步不再计入 write-guard 越界。
|
|
23
25
|
- Pi SDK 终态 session-events JSONL 顶层增加可选 `finish_reason`:仅当 `message_end` / `turn_end` / `assistant_message` 明确携带非空终止原因时由序列化层提升,不伪造默认值,也不回流 `stopReason` 诊断。
|
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ loop-agent dag report --run-id <run-id>
|
|
|
116
116
|
| --- | --- | --- |
|
|
117
117
|
| 受治理 CLI | `loop-agent …` / `agent-worker …` | 权威写入与诊断 |
|
|
118
118
|
| Loop Operator Console | `agent-worker console` | Official 本地控制面(默认 repo=当前目录、`127.0.0.1:8790`,含 Operate 与 Inspect) |
|
|
119
|
-
| Inspect(只读) | `agent-worker console` → `/inspect/`;`observe snapshot` | 统一 Console 内只读检视;`observe serve` 已下线(REMOVED / exit 2) |
|
|
119
|
+
| Inspect(只读) | `agent-worker console` → `/inspect/`;`observe snapshot` | 统一 Console 内只读检视;`observe serve` 已下线(REMOVED / exit 2)。实验例外:`HARNESS_DAG_RERUN_PROMPT_OVERRIDE=1` 时节点 inspector 增加失败节点「提示词重启」tab(默认关闭,不注入任何 mutation token) |
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
122
|
# 终端 A:Console(任务/运行操作面;canonical mutation 只经 sibling loop-agent)
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { isDagRerunPromptOverrideEnabled } from "../shared/dag-prompt-override.js";
|
|
1
3
|
import { executeDagRerun, planDagRerun, } from "../workflows/dag/rerun-run.js";
|
|
2
4
|
export function parseDagRerunArgs(args) {
|
|
3
5
|
if (args.length === 0) {
|
|
@@ -9,6 +11,8 @@ export function parseDagRerunArgs(args) {
|
|
|
9
11
|
let planHash;
|
|
10
12
|
let requestId;
|
|
11
13
|
let reason;
|
|
14
|
+
const promptOverrideSpecs = [];
|
|
15
|
+
const promptOverrideAppendSpecs = [];
|
|
12
16
|
for (let index = 0; index < args.length; index += 1) {
|
|
13
17
|
const arg = args[index];
|
|
14
18
|
if (arg === "--run-id")
|
|
@@ -33,6 +37,14 @@ export function parseDagRerunArgs(args) {
|
|
|
33
37
|
reason = args[++index];
|
|
34
38
|
else if (arg.startsWith("--reason="))
|
|
35
39
|
reason = arg.slice("--reason=".length);
|
|
40
|
+
else if (arg === "--prompt-override")
|
|
41
|
+
promptOverrideSpecs.push(args[++index] ?? "");
|
|
42
|
+
else if (arg.startsWith("--prompt-override="))
|
|
43
|
+
promptOverrideSpecs.push(arg.slice("--prompt-override=".length));
|
|
44
|
+
else if (arg === "--prompt-override-append")
|
|
45
|
+
promptOverrideAppendSpecs.push(args[++index] ?? "");
|
|
46
|
+
else if (arg.startsWith("--prompt-override-append="))
|
|
47
|
+
promptOverrideAppendSpecs.push(arg.slice("--prompt-override-append=".length));
|
|
36
48
|
else if (arg === "--json")
|
|
37
49
|
continue;
|
|
38
50
|
else if (arg.startsWith("-"))
|
|
@@ -50,7 +62,13 @@ export function parseDagRerunArgs(args) {
|
|
|
50
62
|
if (planHash || requestId || reason) {
|
|
51
63
|
throw new Error("dag rerun --plan cannot be combined with execute flags");
|
|
52
64
|
}
|
|
53
|
-
return {
|
|
65
|
+
return {
|
|
66
|
+
parentRunId,
|
|
67
|
+
selectedNodeId,
|
|
68
|
+
planOnly: true,
|
|
69
|
+
promptOverrideSpecs,
|
|
70
|
+
promptOverrideAppendSpecs,
|
|
71
|
+
};
|
|
54
72
|
}
|
|
55
73
|
if (!planHash?.trim()) {
|
|
56
74
|
throw new Error("dag rerun execute requires --plan-hash <hash>");
|
|
@@ -68,15 +86,50 @@ export function parseDagRerunArgs(args) {
|
|
|
68
86
|
planHash: planHash.trim(),
|
|
69
87
|
requestId: requestId.trim(),
|
|
70
88
|
reason: reason.trim(),
|
|
89
|
+
promptOverrideSpecs,
|
|
90
|
+
promptOverrideAppendSpecs,
|
|
71
91
|
};
|
|
72
92
|
}
|
|
93
|
+
async function loadPromptOverrides(specs, mode) {
|
|
94
|
+
const overrides = [];
|
|
95
|
+
for (const spec of specs) {
|
|
96
|
+
const separator = spec.indexOf("@");
|
|
97
|
+
if (separator <= 0 || separator >= spec.length - 1) {
|
|
98
|
+
throw new Error(`dag rerun --prompt-override${mode === "append" ? "-append" : ""} expects <nodeId>@<filePath>, got: ${spec}`);
|
|
99
|
+
}
|
|
100
|
+
const nodeId = spec.slice(0, separator);
|
|
101
|
+
const filePath = spec.slice(separator + 1);
|
|
102
|
+
let prompt;
|
|
103
|
+
try {
|
|
104
|
+
prompt = await readFile(filePath, "utf-8");
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`cannot read prompt override file for node ${nodeId} (${filePath}): ${error instanceof Error ? error.message : String(error)}`);
|
|
108
|
+
}
|
|
109
|
+
overrides.push(mode === "append" ? { nodeId, prompt, mode } : { nodeId, prompt });
|
|
110
|
+
}
|
|
111
|
+
return overrides;
|
|
112
|
+
}
|
|
73
113
|
export async function runDagRerun(repoRoot, rawArgs) {
|
|
74
114
|
const parsed = parseDagRerunArgs(rawArgs);
|
|
115
|
+
let promptOverrides;
|
|
116
|
+
const hasOverrides = parsed.promptOverrideSpecs.length > 0 ||
|
|
117
|
+
parsed.promptOverrideAppendSpecs.length > 0;
|
|
118
|
+
if (hasOverrides) {
|
|
119
|
+
if (!isDagRerunPromptOverrideEnabled()) {
|
|
120
|
+
throw new Error("prompt override rerun is disabled; set HARNESS_DAG_RERUN_PROMPT_OVERRIDE=1 to enable this experimental capability");
|
|
121
|
+
}
|
|
122
|
+
promptOverrides = [
|
|
123
|
+
...(await loadPromptOverrides(parsed.promptOverrideSpecs, "replace")),
|
|
124
|
+
...(await loadPromptOverrides(parsed.promptOverrideAppendSpecs, "append")),
|
|
125
|
+
];
|
|
126
|
+
}
|
|
75
127
|
if (parsed.planOnly) {
|
|
76
128
|
const plan = await planDagRerun({
|
|
77
129
|
cwd: repoRoot,
|
|
78
130
|
parentRunId: parsed.parentRunId,
|
|
79
131
|
selectedNodeId: parsed.selectedNodeId,
|
|
132
|
+
promptOverrides,
|
|
80
133
|
});
|
|
81
134
|
const result = {
|
|
82
135
|
ok: plan.eligible,
|
|
@@ -95,6 +148,7 @@ export async function runDagRerun(repoRoot, rawArgs) {
|
|
|
95
148
|
planHash: parsed.planHash,
|
|
96
149
|
requestId: parsed.requestId,
|
|
97
150
|
reason: parsed.reason,
|
|
151
|
+
promptOverrides,
|
|
98
152
|
});
|
|
99
153
|
console.log(JSON.stringify(result, null, 2));
|
|
100
154
|
if (!result.ok) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal switch for the experimental "rerun failed node with an edited
|
|
3
|
+
* prompt" capability. Default is OFF; nothing may depend on it being enabled.
|
|
4
|
+
* The switch is deliberately env-based (no harness.json surface) while the
|
|
5
|
+
* feature is internal.
|
|
6
|
+
*/
|
|
7
|
+
export const DAG_RERUN_PROMPT_OVERRIDE_ENV = "HARNESS_DAG_RERUN_PROMPT_OVERRIDE";
|
|
8
|
+
/** Upper bound for an override input body (characters). */
|
|
9
|
+
export const MAX_DAG_RERUN_PROMPT_OVERRIDE_CHARS = 65_536;
|
|
10
|
+
export function isDagRerunPromptOverrideEnabled(env = process.env) {
|
|
11
|
+
const value = env[DAG_RERUN_PROMPT_OVERRIDE_ENV];
|
|
12
|
+
return value === "1" || value === "true";
|
|
13
|
+
}
|
|
14
|
+
export const DAG_RERUN_PROMPT_ADDENDUM_TAG = "operator_addendum";
|
|
15
|
+
/**
|
|
16
|
+
* Compose the final subtask_prompt for a rerun override.
|
|
17
|
+
* - "replace": the operator text becomes the whole prompt (advanced mode).
|
|
18
|
+
* - "append" (recommended): the frozen base prompt is kept verbatim and the
|
|
19
|
+
* operator addendum is appended in a clearly marked block, mirroring the
|
|
20
|
+
* rerunFeedback / retry_instruction augmentation semantics — small diffs,
|
|
21
|
+
* no risk of dropping template scaffolding.
|
|
22
|
+
*/
|
|
23
|
+
export function composeDagPromptOverridePrompt(input) {
|
|
24
|
+
if (input.mode === "replace") {
|
|
25
|
+
return input.text;
|
|
26
|
+
}
|
|
27
|
+
return `${input.basePrompt}\n\n<${DAG_RERUN_PROMPT_ADDENDUM_TAG}>\n${input.text.trim()}\n</${DAG_RERUN_PROMPT_ADDENDUM_TAG}>\n`;
|
|
28
|
+
}
|
|
@@ -1155,6 +1155,19 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1155
1155
|
modelCallable: "always",
|
|
1156
1156
|
humanConfirmation: "none",
|
|
1157
1157
|
},
|
|
1158
|
+
{
|
|
1159
|
+
action: "dagPromptOverrideConfig",
|
|
1160
|
+
cli: "console dag-prompt-override-config",
|
|
1161
|
+
kind: "read",
|
|
1162
|
+
inputSchemaVersion: 1,
|
|
1163
|
+
resultSchemaVersion: 1,
|
|
1164
|
+
envelopeSchemaVersion: 1,
|
|
1165
|
+
requiredErrorCodes: [],
|
|
1166
|
+
description: "Read-only probe of the experimental prompt-override rerun switch (env-gated, default off). The browser Recovery UI hides the failed-node prompt editor unless this returns enabled=true. Never mutates.",
|
|
1167
|
+
inputParams: [],
|
|
1168
|
+
modelCallable: "always",
|
|
1169
|
+
humanConfirmation: "none",
|
|
1170
|
+
},
|
|
1158
1171
|
{
|
|
1159
1172
|
action: "dagRerunPlan",
|
|
1160
1173
|
cli: "loop-agent dag rerun --run-id <id> --from-node <node> --plan --json",
|
|
@@ -1177,6 +1190,12 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1177
1190
|
required: true,
|
|
1178
1191
|
description: "node id to rerun from (prefer failed/attention node from dagReport primaryFailure.nodeId)",
|
|
1179
1192
|
},
|
|
1193
|
+
{
|
|
1194
|
+
name: "promptOverrides",
|
|
1195
|
+
type: "array",
|
|
1196
|
+
required: false,
|
|
1197
|
+
description: "experimental (switch off by default): [{nodeId, prompt, mode?}] — mode append (recommended) keeps the frozen base prompt and appends the text as a marked addendum block, replace swaps the whole subtask_prompt; only FAILED nodes inside the reset closure are admitted and the planHash binds the composed change",
|
|
1198
|
+
},
|
|
1180
1199
|
],
|
|
1181
1200
|
modelCallable: "always",
|
|
1182
1201
|
humanConfirmation: "none",
|
|
@@ -1219,6 +1238,12 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1219
1238
|
required: true,
|
|
1220
1239
|
description: "why continue from this node (e.g. provider flake; resume from review-pi)",
|
|
1221
1240
|
},
|
|
1241
|
+
{
|
|
1242
|
+
name: "promptOverrides",
|
|
1243
|
+
type: "array",
|
|
1244
|
+
required: false,
|
|
1245
|
+
description: "experimental (switch off by default): must match the dagRerunPlan promptOverrides exactly (same mode/text); the planHash already binds them, any drift is rejected",
|
|
1246
|
+
},
|
|
1222
1247
|
],
|
|
1223
1248
|
// always: fresh eligible dagRerun plans are model-callable (2026-08-11).
|
|
1224
1249
|
// The CLI keeps enforcing parent lifecycle, fromNode, planHash,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import { buildOperatorCapabilitiesDocument, OFFICIAL_TAIL_ACTION_IDS, } from "../../shared/operator/capabilities.js";
|
|
3
|
+
import { DAG_RERUN_PROMPT_OVERRIDE_ENV, isDagRerunPromptOverrideEnabled, MAX_DAG_RERUN_PROMPT_OVERRIDE_CHARS, } from "../../shared/dag-prompt-override.js";
|
|
3
4
|
import { buildOperatorResult, operatorFailed, operatorSucceeded, } from "../../shared/operator/envelope.js";
|
|
4
5
|
import { CANONICAL_TASK_ID_PATTERN, formatLocalBusinessDate, getTaskPaths, loadTaskConfig, } from "../../task/runtime.js";
|
|
5
6
|
import { diffTaskContract, validateDraftForTask, } from "../../task/contract/index.js";
|
|
@@ -401,6 +402,85 @@ async function runReadCli(ctx, args, command) {
|
|
|
401
402
|
});
|
|
402
403
|
}
|
|
403
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Parse and bound the experimental promptOverrides action param. The env
|
|
407
|
+
* switch is checked separately so disabled deployments fail closed before any
|
|
408
|
+
* staging happens. `mode` defaults to "replace"; "append" keeps the frozen
|
|
409
|
+
* base prompt and only appends the operator text as a marked addendum.
|
|
410
|
+
*/
|
|
411
|
+
function parsePromptOverrideParams(raw) {
|
|
412
|
+
if (raw === undefined || raw === null)
|
|
413
|
+
return { kind: "ok", overrides: [] };
|
|
414
|
+
if (!Array.isArray(raw)) {
|
|
415
|
+
return {
|
|
416
|
+
kind: "error",
|
|
417
|
+
message: "promptOverrides must be an array of {nodeId, prompt, mode?}",
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (raw.length === 0)
|
|
421
|
+
return { kind: "ok", overrides: [] };
|
|
422
|
+
if (raw.length > 8) {
|
|
423
|
+
return { kind: "error", message: "promptOverrides supports at most 8 nodes" };
|
|
424
|
+
}
|
|
425
|
+
const overrides = [];
|
|
426
|
+
const seen = new Set();
|
|
427
|
+
for (const item of raw) {
|
|
428
|
+
if (!item || typeof item !== "object") {
|
|
429
|
+
return {
|
|
430
|
+
kind: "error",
|
|
431
|
+
message: "promptOverrides entries must be objects {nodeId, prompt, mode?}",
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
const record = item;
|
|
435
|
+
const nodeId = typeof record.nodeId === "string" ? record.nodeId.trim() : "";
|
|
436
|
+
const prompt = typeof record.prompt === "string" ? record.prompt : "";
|
|
437
|
+
const mode = record.mode === undefined || record.mode === null
|
|
438
|
+
? undefined
|
|
439
|
+
: typeof record.mode === "string"
|
|
440
|
+
? record.mode
|
|
441
|
+
: "invalid";
|
|
442
|
+
if (!nodeId) {
|
|
443
|
+
return { kind: "error", message: "promptOverrides nodeId is required" };
|
|
444
|
+
}
|
|
445
|
+
if (seen.has(nodeId)) {
|
|
446
|
+
return {
|
|
447
|
+
kind: "error",
|
|
448
|
+
message: `promptOverrides contains duplicate nodeId: ${nodeId}`,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
seen.add(nodeId);
|
|
452
|
+
if (mode !== undefined && mode !== "append" && mode !== "replace") {
|
|
453
|
+
return {
|
|
454
|
+
kind: "error",
|
|
455
|
+
message: `promptOverrides mode for ${nodeId} must be append or replace`,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
if (!prompt.trim() || prompt.length > MAX_DAG_RERUN_PROMPT_OVERRIDE_CHARS) {
|
|
459
|
+
return {
|
|
460
|
+
kind: "error",
|
|
461
|
+
message: `promptOverrides prompt for ${nodeId} must be 1-${MAX_DAG_RERUN_PROMPT_OVERRIDE_CHARS} characters`,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
overrides.push(mode === undefined ? { nodeId, prompt } : { nodeId, prompt, mode });
|
|
465
|
+
}
|
|
466
|
+
return { kind: "ok", overrides };
|
|
467
|
+
}
|
|
468
|
+
/** Stage override bodies under app-data and build `--prompt-override` CLI
|
|
469
|
+
* args. The flag carries the mode: `--prompt-override-append` for append. */
|
|
470
|
+
async function buildPromptOverrideCliArgs(ctx, overrides) {
|
|
471
|
+
const args = [];
|
|
472
|
+
for (const override of overrides) {
|
|
473
|
+
const staged = await stageUtf8Text(ctx.appData, override.prompt, {
|
|
474
|
+
extension: ".md",
|
|
475
|
+
label: `prompt-override-${override.nodeId}`,
|
|
476
|
+
});
|
|
477
|
+
const flag = override.mode === "append"
|
|
478
|
+
? "--prompt-override-append"
|
|
479
|
+
: "--prompt-override";
|
|
480
|
+
args.push(flag, `${override.nodeId}@${staged.path}`);
|
|
481
|
+
}
|
|
482
|
+
return args;
|
|
483
|
+
}
|
|
404
484
|
async function acceptOperation(ctx, input) {
|
|
405
485
|
const created = await ctx.operations.create({
|
|
406
486
|
clientRequestId: input.clientRequestId,
|
|
@@ -2078,12 +2158,35 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
2078
2158
|
}
|
|
2079
2159
|
return accepted;
|
|
2080
2160
|
}
|
|
2161
|
+
case "dagPromptOverrideConfig": {
|
|
2162
|
+
// Experimental internal switch; the browser UI hides the prompt-edit
|
|
2163
|
+
// entry unless this reports enabled=true.
|
|
2164
|
+
return {
|
|
2165
|
+
kind: "sync",
|
|
2166
|
+
status: 200,
|
|
2167
|
+
body: operatorSucceeded(action, {
|
|
2168
|
+
enabled: isDagRerunPromptOverrideEnabled(),
|
|
2169
|
+
envVar: DAG_RERUN_PROMPT_OVERRIDE_ENV,
|
|
2170
|
+
}),
|
|
2171
|
+
};
|
|
2172
|
+
}
|
|
2081
2173
|
case "dagRerunPlan": {
|
|
2082
2174
|
const runId = str(p.runId);
|
|
2083
2175
|
const fromNode = str(p.fromNode);
|
|
2084
2176
|
if (!runId || !fromNode) {
|
|
2085
2177
|
return invalid(action, "runId and fromNode are required");
|
|
2086
2178
|
}
|
|
2179
|
+
const parsedOverrides = parsePromptOverrideParams(p.promptOverrides);
|
|
2180
|
+
if (parsedOverrides.kind === "error") {
|
|
2181
|
+
return invalid(action, parsedOverrides.message);
|
|
2182
|
+
}
|
|
2183
|
+
if (parsedOverrides.overrides.length > 0 &&
|
|
2184
|
+
!isDagRerunPromptOverrideEnabled()) {
|
|
2185
|
+
return invalid(action, `prompt override rerun is disabled; set ${DAG_RERUN_PROMPT_OVERRIDE_ENV}=1 to enable this experimental capability`);
|
|
2186
|
+
}
|
|
2187
|
+
const overrideArgs = parsedOverrides.overrides.length > 0
|
|
2188
|
+
? await buildPromptOverrideCliArgs(ctx, parsedOverrides.overrides)
|
|
2189
|
+
: [];
|
|
2087
2190
|
const body = await runReadCli(ctx, [
|
|
2088
2191
|
"dag",
|
|
2089
2192
|
"rerun",
|
|
@@ -2092,6 +2195,7 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
2092
2195
|
"--from-node",
|
|
2093
2196
|
fromNode,
|
|
2094
2197
|
"--plan",
|
|
2198
|
+
...overrideArgs,
|
|
2095
2199
|
"--json",
|
|
2096
2200
|
], "dag rerun plan");
|
|
2097
2201
|
return { kind: "sync", status: body.ok ? 200 : 400, body };
|
|
@@ -2105,6 +2209,17 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
2105
2209
|
if (!runId || !fromNode || !planHash || !reason || !clientRequestId) {
|
|
2106
2210
|
return invalid(action, "runId, fromNode, planHash, reason, and clientRequestId are required");
|
|
2107
2211
|
}
|
|
2212
|
+
const parsedOverrides = parsePromptOverrideParams(p.promptOverrides);
|
|
2213
|
+
if (parsedOverrides.kind === "error") {
|
|
2214
|
+
return invalid(action, parsedOverrides.message);
|
|
2215
|
+
}
|
|
2216
|
+
if (parsedOverrides.overrides.length > 0 &&
|
|
2217
|
+
!isDagRerunPromptOverrideEnabled()) {
|
|
2218
|
+
return invalid(action, `prompt override rerun is disabled; set ${DAG_RERUN_PROMPT_OVERRIDE_ENV}=1 to enable this experimental capability`);
|
|
2219
|
+
}
|
|
2220
|
+
const overrideArgs = parsedOverrides.overrides.length > 0
|
|
2221
|
+
? await buildPromptOverrideCliArgs(ctx, parsedOverrides.overrides)
|
|
2222
|
+
: [];
|
|
2108
2223
|
return acceptOperation(ctx, {
|
|
2109
2224
|
action,
|
|
2110
2225
|
actionParams: p,
|
|
@@ -2122,6 +2237,7 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
2122
2237
|
clientRequestId,
|
|
2123
2238
|
"--reason",
|
|
2124
2239
|
reason,
|
|
2240
|
+
...overrideArgs,
|
|
2125
2241
|
"--json",
|
|
2126
2242
|
],
|
|
2127
2243
|
});
|
|
@@ -131,6 +131,16 @@ async function handleSessionPing(req, res, ctx) {
|
|
|
131
131
|
}
|
|
132
132
|
sendJson(res, 200, { ok: true, pong: true });
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Actions the inspect-scoped mutation token may dispatch. Deliberately
|
|
136
|
+
* minimal: the experimental prompt-override rerun tab needs plan preflight +
|
|
137
|
+
* execution only. Everything else (task creation, runDag, reconcile, chat,
|
|
138
|
+
* worker actions…) requires the general Console token.
|
|
139
|
+
*/
|
|
140
|
+
export const INSPECT_MUTATION_ALLOWED_ACTIONS = new Set([
|
|
141
|
+
"dagRerunPlan",
|
|
142
|
+
"dagRerun",
|
|
143
|
+
]);
|
|
134
144
|
async function handleCreateOperation(req, res, ctx) {
|
|
135
145
|
if (!ctx.operator) {
|
|
136
146
|
sendJson(res, 503, {
|
|
@@ -142,13 +152,31 @@ async function handleCreateOperation(req, res, ctx) {
|
|
|
142
152
|
});
|
|
143
153
|
return;
|
|
144
154
|
}
|
|
145
|
-
const
|
|
155
|
+
const generalGateContext = {
|
|
146
156
|
cookieName: ctx.bootToken.cookieName,
|
|
147
157
|
bootToken: ctx.bootToken.value,
|
|
148
158
|
confirmationToken: ctx.bootToken.confirmationToken,
|
|
149
159
|
consoleOrigin: ctx.getConsoleOrigin(),
|
|
150
160
|
allowNonLoopbackAccess: ctx.allowNonLoopbackAccess === true,
|
|
151
|
-
}
|
|
161
|
+
};
|
|
162
|
+
let failure = evaluateMutationGate(req, generalGateContext);
|
|
163
|
+
let inspectScoped = false;
|
|
164
|
+
if (failure && ctx.inspectBootToken) {
|
|
165
|
+
// Scoped /inspect credentials: try the inspect gate before failing. The
|
|
166
|
+
// general gate already rejected, so passing here only ever yields the
|
|
167
|
+
// allowlisted actions below — never general write capability.
|
|
168
|
+
const scopedFailure = evaluateMutationGate(req, {
|
|
169
|
+
cookieName: ctx.inspectBootToken.cookieName,
|
|
170
|
+
bootToken: ctx.inspectBootToken.value,
|
|
171
|
+
confirmationToken: ctx.inspectBootToken.confirmationToken,
|
|
172
|
+
consoleOrigin: ctx.getConsoleOrigin(),
|
|
173
|
+
allowNonLoopbackAccess: ctx.allowNonLoopbackAccess === true,
|
|
174
|
+
});
|
|
175
|
+
if (!scopedFailure) {
|
|
176
|
+
inspectScoped = true;
|
|
177
|
+
failure = undefined;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
152
180
|
if (failure) {
|
|
153
181
|
sendJson(res, failure.status, {
|
|
154
182
|
ok: false,
|
|
@@ -175,6 +203,16 @@ async function handleCreateOperation(req, res, ctx) {
|
|
|
175
203
|
? body.actionParams
|
|
176
204
|
: {};
|
|
177
205
|
const clientRequestId = typeof body.clientRequestId === "string" ? body.clientRequestId : undefined;
|
|
206
|
+
if (inspectScoped && !INSPECT_MUTATION_ALLOWED_ACTIONS.has(action)) {
|
|
207
|
+
sendJson(res, 403, {
|
|
208
|
+
ok: false,
|
|
209
|
+
error: {
|
|
210
|
+
code: "ACTION_NOT_IN_INSPECT_SCOPE",
|
|
211
|
+
message: `inspect-scoped token only allows: ${[...INSPECT_MUTATION_ALLOWED_ACTIONS].join(", ")}`,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
178
216
|
const result = await dispatchOperatorAction(ctx.operator.actionContext, {
|
|
179
217
|
action,
|
|
180
218
|
actionParams,
|
|
@@ -35,7 +35,7 @@ function normalizeInstanceScope(scope) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
/** Deterministic Cookie name for one Console instance; never includes repo path or token. */
|
|
38
|
-
export function deriveBootCapabilityCookieName(scope) {
|
|
38
|
+
export function deriveBootCapabilityCookieName(scope, variant) {
|
|
39
39
|
const normalized = normalizeInstanceScope(scope);
|
|
40
40
|
const digest = createHash("sha256")
|
|
41
41
|
.update("loop-console-capability-v1\0", "utf8")
|
|
@@ -46,13 +46,17 @@ export function deriveBootCapabilityCookieName(scope) {
|
|
|
46
46
|
.update(String(normalized.configuredPort), "utf8")
|
|
47
47
|
.update("\0", "utf8")
|
|
48
48
|
.update(normalized.instanceNonce ?? "", "utf8")
|
|
49
|
+
.update("\0", "utf8")
|
|
50
|
+
.update(variant ?? "", "utf8")
|
|
49
51
|
.digest("hex")
|
|
50
52
|
.slice(0, 32);
|
|
51
53
|
return `${BOOT_CAPABILITY_COOKIE}_${digest}`;
|
|
52
54
|
}
|
|
53
|
-
/** Issue per-process unguessable boot capability + confirmation tokens.
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
/** Issue per-process unguessable boot capability + confirmation tokens.
|
|
56
|
+
* `variant` (e.g. "inspect") derives a separate cookie name so scoped
|
|
57
|
+
* credentials cannot be replayed against the general mutation surface. */
|
|
58
|
+
export function issueBootCapabilityToken(scope, options = {}) {
|
|
59
|
+
const cookieName = deriveBootCapabilityCookieName(scope, options.variant);
|
|
56
60
|
const value = randomBytes(32).toString("base64url");
|
|
57
61
|
const confirmationToken = randomBytes(32).toString("base64url");
|
|
58
62
|
const setCookieHeader = [
|
|
@@ -63,10 +67,12 @@ export function issueBootCapabilityToken(scope) {
|
|
|
63
67
|
].join("; ");
|
|
64
68
|
return { cookieName, value, setCookieHeader, confirmationToken };
|
|
65
69
|
}
|
|
66
|
-
/** Inject confirmation token into HTML so the SPA can send the mutation
|
|
67
|
-
|
|
70
|
+
/** Inject confirmation token into HTML so the SPA can send the mutation
|
|
71
|
+
* header. `varName` separates the general Console token from the scoped
|
|
72
|
+
* inspect token on the read-only /inspect surface. */
|
|
73
|
+
export function injectConfirmationTokenScript(html, confirmationToken, varName = "__CONSOLE_CONFIRMATION_TOKEN__") {
|
|
68
74
|
const source = typeof html === "string" ? html : html.toString("utf8");
|
|
69
|
-
const script = `<script>window
|
|
75
|
+
const script = `<script>window.${varName}=${JSON.stringify(confirmationToken)};</script>`;
|
|
70
76
|
if (source.includes("</head>")) {
|
|
71
77
|
return Buffer.from(source.replace("</head>", `${script}</head>`), "utf8");
|
|
72
78
|
}
|
|
@@ -21,8 +21,9 @@ import { createOperationEventStore, } from "./operation-sse.js";
|
|
|
21
21
|
import { OperationStore } from "./operation-store.js";
|
|
22
22
|
import { probePiReadiness, } from "./pi-readiness.js";
|
|
23
23
|
import { handleConsoleHealthRequest, handleConsoleOperatorRequest, sendJson, serveConsoleStatic, } from "./routes.js";
|
|
24
|
-
import { issueBootCapabilityToken } from "./security.js";
|
|
24
|
+
import { issueBootCapabilityToken, injectConfirmationTokenScript, } from "./security.js";
|
|
25
25
|
import { resolveSiblingLoopAgentBin } from "./sibling-controller.js";
|
|
26
|
+
import { isDagRerunPromptOverrideEnabled } from "../../shared/dag-prompt-override.js";
|
|
26
27
|
import { NightAuxTicker } from "./night-aux-ticker.js";
|
|
27
28
|
import { deriveObserveRouteCapabilities } from "../observe/health.js";
|
|
28
29
|
import { createObserveRouteContext, defaultObserveStaticDir, handleMatchedObserveRoute, matchObserveGetRoute, ROUTES, serveObserveStatic, } from "../observe/routes.js";
|
|
@@ -86,6 +87,15 @@ export async function createConsoleServer(options) {
|
|
|
86
87
|
configuredPort,
|
|
87
88
|
...(instanceNonce ? { instanceNonce } : {}),
|
|
88
89
|
});
|
|
90
|
+
// Scoped credentials for the experimental /inspect prompt-override rerun:
|
|
91
|
+
// separate cookie name + confirmation token so the read-only inspect page
|
|
92
|
+
// can never replay them against the general Console mutation surface.
|
|
93
|
+
const inspectBootToken = issueBootCapabilityToken({
|
|
94
|
+
repoFingerprint: appData.fingerprint,
|
|
95
|
+
bindHost: host,
|
|
96
|
+
configuredPort,
|
|
97
|
+
...(instanceNonce ? { instanceNonce } : {}),
|
|
98
|
+
}, { variant: "inspect" });
|
|
89
99
|
const operations = new OperationStore(appData);
|
|
90
100
|
const events = createOperationEventStore({
|
|
91
101
|
persistenceDir: path.join(appData.operations, "events"),
|
|
@@ -194,6 +204,7 @@ export async function createConsoleServer(options) {
|
|
|
194
204
|
repoRoot,
|
|
195
205
|
staticDir,
|
|
196
206
|
bootToken,
|
|
207
|
+
inspectBootToken,
|
|
197
208
|
getConsoleOrigin,
|
|
198
209
|
allowNonLoopbackAccess: !loopbackBind,
|
|
199
210
|
inspect: {
|
|
@@ -283,8 +294,22 @@ export async function createConsoleServer(options) {
|
|
|
283
294
|
}
|
|
284
295
|
}
|
|
285
296
|
if (pathname.startsWith("/inspect")) {
|
|
297
|
+
// Experimental prompt-override rerun: only while the internal switch
|
|
298
|
+
// is enabled do we hand the inspect page SCOPED mutation
|
|
299
|
+
// credentials (separate cookie + token, only strong enough for
|
|
300
|
+
// INSPECT_MUTATION_ALLOWED_ACTIONS — see routes.ts). Default stays
|
|
301
|
+
// strictly read-only: no token, no cookie, no tab.
|
|
302
|
+
const htmlEnhancer = isDagRerunPromptOverrideEnabled()
|
|
303
|
+
? (html) => ({
|
|
304
|
+
content: injectConfirmationTokenScript(html, routeContext.inspectBootToken?.confirmationToken ??
|
|
305
|
+
routeContext.bootToken.confirmationToken, "__INSPECT_MUTATION_TOKEN__"),
|
|
306
|
+
setCookie: routeContext.inspectBootToken?.setCookieHeader ??
|
|
307
|
+
routeContext.bootToken.setCookieHeader,
|
|
308
|
+
})
|
|
309
|
+
: undefined;
|
|
286
310
|
await serveObserveStatic(req, res, inspectStaticDir, {
|
|
287
311
|
urlPrefix: "/inspect",
|
|
312
|
+
...(htmlEnhancer ? { htmlEnhancer } : {}),
|
|
288
313
|
});
|
|
289
314
|
return;
|
|
290
315
|
}
|
|
@@ -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-DJIlR25o.js";import{p as f}from"./chunk-JWPE2WC7-fZNtEdQZ.js";import{_ as n,l as o}from"./mermaid.core-C1cSavOy.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-xn_NxcfB.js";import"./index-C2jmYBfu.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-C1cSavOy.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};
|