@tea-agent/loop-agent 0.40.0-next.9 → 0.41.0-next.1
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 +29 -20
- package/README.md +2 -2
- package/dist/application/dag/generate-task-dag.js +6 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +9 -5
- package/dist/cli/program.js +38 -3
- package/dist/commands/client-recovery.js +8 -36
- package/dist/commands/init-model-catalog.js +22 -0
- package/dist/commands/task-advance.js +23 -1
- package/dist/commands/task-source-prepare.js +5 -0
- package/dist/commands/task-status.js +1 -0
- package/dist/executors/pi-sdk-executor.js +33 -5
- package/dist/executors/shell-executor.js +94 -20
- package/dist/governance/checks.js +1 -0
- package/dist/shared/operator/capabilities.js +9 -1
- package/dist/shared/pi-context-pressure/checkpoint.js +116 -0
- package/dist/shared/pi-context-pressure/compaction-policy.js +151 -0
- package/dist/shared/pi-context-pressure/env.js +58 -0
- package/dist/shared/pi-context-pressure/extension.js +100 -0
- package/dist/shared/pi-context-pressure/index.js +7 -0
- package/dist/shared/pi-context-pressure/overflow.js +252 -0
- package/dist/shared/pi-context-pressure/sift-bridge.js +386 -0
- package/dist/shared/pi-context-pressure/telemetry.js +51 -0
- package/dist/worker/console/chat/assistant-content.js +7 -0
- package/dist/worker/console/chat/chat-event-store.js +82 -11
- package/dist/worker/console/chat/goal-round-driver.js +72 -0
- package/dist/worker/console/chat/goals.js +300 -0
- package/dist/worker/console/chat/pi-runtime.js +286 -8
- package/dist/worker/console/chat/provider-error.js +2 -1
- package/dist/worker/console/chat/repo-browser.js +94 -12
- package/dist/worker/console/chat/routes.js +495 -30
- package/dist/worker/console/chat/semantic-activity.js +12 -11
- package/dist/worker/console/chat/session-catalog.js +48 -0
- package/dist/worker/console/chat/session-stats.js +96 -0
- package/dist/worker/console/chat/session-store.js +27 -18
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/sift-bridge.js +1 -0
- package/dist/worker/console/chat/turn-process.js +60 -7
- package/dist/worker/console/dag-execution-receipt.js +20 -2
- package/dist/worker/console/operator-actions.js +20 -5
- package/dist/worker/console/operator-selection.js +6 -2
- package/dist/worker/console/pi-plugins.catalog.json +73658 -0
- package/dist/worker/console/pi-plugins.js +179 -0
- package/dist/worker/console/routes.js +246 -6
- package/dist/worker/console/server.js +173 -42
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bs-CDAXM.js → abnfDiagram-N423BO3Z-CV1qyRbn.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CAkA3We3.js → arc-B_ljC4ma.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEmI_zqr.js → architectureDiagram-T3A2C74G-DTBqsauL.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-uDHANebE.js → blockDiagram-VBNYF7ZC-CMZj6nYE.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Bv97b4_B.js → c4Diagram-5PPSVZJV-C4ey_S7v.js} +1 -1
- package/dist/worker/console/static/assets/channel-BvYm_83n.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-shmQKsFz.js → chunk-2GRJ4B5K-CGcAlY6Z.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BAraNvcN.js → chunk-2Q5K7J3B-XRSM64J1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BirhxUop.js → chunk-5RXB4S5H-COSIFYbz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C9LgUJpR.js → chunk-5VM5RSS4-BwuaXiOK.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DrU-s-t7.js → chunk-6Q2QTUOP-DNbFuVlv.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Tx-H_FA2.js → chunk-GF5L2VYU-C4DZKffE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BjLtNFrR.js → chunk-JWPE2WC7-M3A6iczx.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-UNLVwSsy.js → chunk-KBJHAD2P-C5zDzQEM.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CBEUX8XD.js → chunk-RYQCIY6F-uAcUDub8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-WTL7IZOq.js → chunk-XXDRQBXY-EPpz2uSP.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BNdy3f9F.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BNdy3f9F.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CkHG6W3s.js → cose-bilkent-JH36ORCC-BAkfFGTf.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BRzFqTaL.js → cynefin-VYW2F7L2-Cjb4d22A.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-2_CFp_i7.js → cynefinDiagram-MW4NZA55-Cf7QSgcu.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJtsmdkE.js → dagre-VZM6K2ZE-UlyVBCtl.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DNEFFo6w.js → diagram-7IWD3JNH-DWdRAZ8p.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B_IWV7eo.js → diagram-B4RE2ZJO-Y2ag2Pm0.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DvvRx2dz.js → diagram-LBJQPF4R-DBHcuPXI.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CsibsWLg.js → diagram-Q27KOJAE-BK7eno2C.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-les_djBQ.js → diagram-UB23O5K3-Dbyku82r.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BEm2n7qJ.js → ebnfDiagram-BXEA7PRR--rS0Q41A.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BI7vHHVm.js → erDiagram-JOGREHBK-Cms8pJeK.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CUFCERrB.js → flowDiagram-UKHOOZJN-DouONwBy.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-wxyLiGWt.js → ganttDiagram-PKOTCBZU-DuKB5yDe.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bt897K8Z.js → gitGraphDiagram-DS77QQ5N-DE6zp0SI.js} +1 -1
- package/dist/worker/console/static/assets/index-C39zQYik.js +451 -0
- package/dist/worker/console/static/assets/index-Crixt9tN.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DYNx_IPv.js → infoDiagram-6WML65LV-BLETv9SH.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CzpLNEu6.js → ishikawaDiagram-WSZJBQD7-DyU-2lJb.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-97f9owNU.js → journeyDiagram-NVQOT4AX-BotFSygt.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BxM9hyBn.js → kanban-definition-27J2QSJJ-CqcAMgVk.js} +1 -1
- package/dist/worker/console/static/assets/{linear-ByuxcHvp.js → linear-Bf4U8h5G.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DwPGvpCv.js → mermaid.core-D0JEVefG.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DCoqG9RT.js → mindmap-definition-FAOFIHXS-DEFgNgOo.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BLSBmBMx.js → pegDiagram-VL7TDLO6-CirKhxo1.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B0t_0oJW.js → pieDiagram-7S7Q4E2Y-BlaQYInF.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js → quadrantDiagram-CIZ2JOQS-BbyzqH4U.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-B3jRdATC.js → railroadDiagram-AXF67PYL-qA-XykV6.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-cTtXEN.js → requirementDiagram-LRYGKXZP-Cc85Zcxc.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B25igJRE.js → sankeyDiagram-W5VNT64P-CS7BVnoH.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-jW_lM1_D.js → sequenceDiagram-SI44F4Z6-DMQ-kKmZ.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CrzTgsHE.js → sizeCapture-X5ZJPWSS-DXKs1dcE.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B01MvlqE.js → stateDiagram-OKZ733FA-xG1ti87X.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-tYINJZ8x.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-YcF12FiU.js → swimlanes-SLNWSIFB-BQwmKGHd.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-OoBOXPiG.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ClnRcg2s.js → timeline-definition-Z64GVDOM-BwL9oHtP.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B6gr_z-q.js → vennDiagram-T6HMQDX7-BWk-i_Y1.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CvSgguGH.js → wardleyDiagram-T6FBY63Y-DAvETpEZ.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-23OtSZCb.js → xychartDiagram-ELKLHX3M-Cd4pASnF.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/useRunProgress.js +9 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +95 -25
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +35 -1
- package/dist/worker/console/static-src/operator-chat/dag-progress-link.js +22 -0
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +3 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +26 -19
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +0 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +14 -1
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +34 -4
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
- package/dist/worker/console/static-src/operator-chat/workspace-reorder.js +18 -0
- package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +106 -0
- package/dist/worker/console/static-src/shell/useWorkspaces.js +150 -34
- package/dist/worker/console/static-src/shell/workspace-route.js +3 -1
- package/dist/worker/console/workspace-context.js +28 -3
- package/dist/worker/console/workspace-registry.js +333 -60
- package/dist/worker/observability/read-model.js +4 -0
- package/dist/worker/observe/static/inspect-bootstrap.d.ts +8 -0
- package/dist/worker/observe/static/inspect-bootstrap.js +57 -0
- package/dist/worker/observe/static/inspect-workspace.js +54 -10
- package/dist/worker/observe/static/operator-chrome.css +23 -4
- package/dist/worker/observe/static/operator-chrome.js +7 -2
- package/dist/worker/observe/static/styles.css +87 -25
- package/dist/worker/observe/static/views/dag-inspector.js +42 -1
- package/dist/worker/observe/static/views/dags.js +7 -5
- package/dist/worker/observe/static/views/session-timeline.js +135 -0
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +162 -8
- package/dist/workflows/dag/backend-test-pytest-collection.js +70 -2
- package/dist/workflows/dag/backend-test-result-contract.js +5 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +339 -53
- package/dist/workflows/dag/backend-test-writer-completeness.js +11 -0
- package/dist/workflows/dag/init-hybrid.js +5 -4
- package/docs/architecture/runtime-boundaries.md +2 -1
- package/docs/templates/backend-test-dag.json +6 -5
- package/docs/templates/init-managed-agents.md +1 -1
- package/package.json +3 -2
- package/skills/loop-agent/references/command-reference.md +15 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +0 -1
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +0 -407
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +0 -8
package/AGENTS.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
- 机器校验契约真源:`docs/init-surface.manifest.json`、`docs/architecture/runtime-boundaries.md`、`src/cli/command-definitions.ts`、`skills/loop-agent/`、`scripts/check-*.sh`;本文件只指路。
|
|
25
25
|
- 本仓库既是源项目也是 init 默认模板;新增能力必须判断 npm 内置 vs `loop-agent init` 投影。
|
|
26
26
|
- 委托写入前必须结构化 `task.json.allowedPaths` / `forbiddenPaths`,并审查 DAG writer `writeSet`。
|
|
27
|
-
- Shell 搜索优先 `rg`,按名找文件优先 `fd`;脚本用 Git Bash / 兼容 Bash。
|
|
27
|
+
- Shell 搜索优先 `rg`,按名找文件优先 `fd`;脚本用 Git Bash / 兼容 Bash。rg 短标志禁止粘写:rg 的 `-r` 是 `--replace`(grep 里才是递归,rg 递归默认开启),`rg -rln pat` 会把匹配文本静默替换成 `ln` 且无报错;行号搜索用 `rg -n pat`,仅列文件用 `rg -l pat`,输出呈 `文件名:内容`(单冒号无行号)即为替换污染,须重跑。
|
|
28
28
|
- 用 loop-agent 迭代本仓库时,控制器必须来自已发布 npm 包(记录实际版本);启动后不要中途升级;不要用工作区 `npm link` / `npm run dev` 控制可能改 CLI/runtime/package 的任务。
|
|
29
29
|
- 反复出现的约束固化为文档、脚本、检查、测试或模板;禁止占位实现(除非 contract 标明脚手架)。
|
|
30
30
|
- 非微小实现:`exec-plan` 不能替代 Agent DAG;除非用户要求 one-shot 或计划记录 escape hatch,否则改实现前完成 `task advance`(PRD + 结构化路径边界)与 writeSet gate 审查。长跑 DAG 启动一律走 `prepareDagExecution → runDag → operationId` 由 Console operation 后台持有;**禁止**在前台 Bash 直接执行 `task advance --approve-gate`(会阻塞会话且超时杀 runner)、禁止把长跑命令管道到 `tail`/`head`、禁止自行拼接 `nohup`/`Start-Process`/`start`。
|
package/CHANGELOG.md
CHANGED
|
@@ -2,36 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
- 对话中的长时间 DAG 执行现在会保留一条实时状态:持续显示总运行时间、当前阶段、完成步数和最近一次有效进展;重复等待不再堆叠,点击状态可以直接查看对应 DAG。模型仍会在阶段变化、重要发现、失败恢复和结束时,用自然语言说明刚完成什么、下一步做什么。
|
|
6
|
+
|
|
7
|
+
## [0.40.0] - 2026-08-31
|
|
8
|
+
|
|
5
9
|
### 重点更新
|
|
6
10
|
|
|
7
|
-
-
|
|
8
|
-
- Operator Chat
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
11
|
+
- **Console 对话页「轨迹」视图**:仿 DSH ui-trajectory 把对话按「用户 → 过程 → AI 回复」渲染为统一单元格列表,每行带类型标签与图标,思考/工具/超长消息可展开收起,支持一键导出自包含 HTML。轨迹顶部新增「会话注入」区,展示真实注入 Pi 会话的系统提示词全文(含字符数与注入上下文 suffix)与模型可见工具目录,离线导出同样包含;每轮新增遥测头行(步骤数、LLM 时长、首 token 延迟、解码吞吐、工具调用数与耗时、上下行 token 与成本),切换历史会话立即显示。同时修复刷新后工具耗时全部变成 0ms/消失(会话恢复现在回填每次工具调用的真实起止时间)、窄窗口耗时列被整体隐藏、展开后内容仍截断在 420 字符、多工作区下轨迹数据恒为空等问题。
|
|
12
|
+
- **上下文压力处理默认开启**:Operator Chat 与 DAG Pi 节点在发送前接近模型窗口时主动压缩一次、识别网关「请求上下文过大」响应后压缩并继续原请求、对 OpenAI 格式的大工具输出做线路压缩;消息流按顺序展示触发原因、压缩进度与结果。Anthropic 缺省 prompt cache 形态保持 no-op 不破坏缓存;`HARNESS_CONTEXT_PRESSURE_MODE` / `HARNESS_CONSOLE_SIFT` / `HARNESS_DAG_SIFT` 可整体或分路关闭;可选依赖 `@agent-context/sift@0.0.1-alpha.6` 精确 pin,不投影 init。
|
|
13
|
+
- **Console「Pi 插件」管理**:从「设置」提升为与「设置」同级的独立 tab,内置经 npm 校验的插件目录(6303 个,展示 5562 个可安装、含中文说明),支持搜索、每页条数、分页与一键安装/卸载;插件版本改为从 npm 配置的仓库地址拉取(内网镜像可用),安装时提供版本下拉、默认装最新,已安装插件显示实际版本,`@version` 形式的已装包也能正确识别;进度动画改为 JS 驱动,不受系统「减少动态效果」影响。
|
|
14
|
+
- **Operator Chat 持续目标模式**:用 `/goal` 或输入框上方的目标条创建跨多回合推进的目标,可随时暂停、继续、编辑或清除;长任务在安全轮数内自动续行,优先处理排队消息;上下文压缩后当前目标自动回到模型上下文;刷新后仍可见,重启 Console 不会未经确认自行续跑。配套新增任务清单与结构化提问卡片,长任务进度与需要用户决策的内容更易理解。
|
|
15
|
+
- **多工作区与消息流重构**:同一页面管理多个工作区,会话稳定归属创建它的工作区,会话列表改为独立全局目录(移除工作区不丢会话);消息流整体更紧凑,思考、工具执行、阶段性结果与最终回答按真实发生顺序展示;对话进行中可连续提交多条消息(编辑/删除/立即插入),排队消息由输入框上方队列面板统一管理;右侧辅助栏统一承载文件、上下文、调用记录、运行活动与当前 DAG,宽度可调。
|
|
16
|
+
- **CLI 可用性修复**:`--help` 现在直接显示真实 usage(此前 raw-args 命令只在解析出错时才抛出):`task advance` / `task status` / `task source prepare` 与 `dag resume|doctor|report|rerun|...` 的帮助顶部即列出完整参数契约;`task source prepare`(确定性任务源投影)从不可达死代码转正为可用子命令。
|
|
17
|
+
- **backend-test 执行与判定系列修复**:pytest 7.x 环境改用 run-owned Python launcher 精确执行已授权 items(不再把 `@<targets-file>` 当普通路径导致全部无法执行);payload readiness 修复空值标记误判 UNSAFE、本地 transport payload 假阴性、同模块安全 payload helper 绑定、`\u0020` 空白表示误判、超长边界 observed 持久化等系列假阳/假阴性;Scenario Partition 的 exact slot 清单正确下发 Markdown writer(普通别名不再替代 partition slots)、补集槽位合同统一;payload/fixture/Markdown→pytest 多类缺陷合并进唯一一次有界 repair;文档审计不再扫描 `.scratch/` 临时证据阻断发布前验证。
|
|
18
|
+
|
|
19
|
+
### 改进
|
|
20
|
+
|
|
21
|
+
- 初始化选择模型时识别公司内部 `wizard-local` 的 AICoder 型号梯度(default/plus/pro/max),作为 LOW/MED/HIGH 参考但不机械分档。
|
|
22
|
+
- 右侧文件工作台打开 HTML 默认沙箱预览(同项目相对资源可用、脚本与外部网络阻断),超大源码显示前 512 KiB 并明确提示截断。
|
|
23
|
+
- 工作区列表支持拖动排序并自动保存;多个 Console 同时运行时安全合并工作区增删并实时同步。
|
|
24
|
+
- 设置页用自然中文展示模型状态;DAG 检查器简化节点说明与提示词重启面板,长内容更易定位。
|
|
25
|
+
- 输入框整合模型与推理等级选择,只展示有真实数据的轮次、耗时、速度与缓存统计。
|
|
26
|
+
- 修复 Console「更新并初始化」被观测顶栏遮挡(入口改到操作 → 设置)、内嵌观测样式泄漏与「提示词重启」入口丢失、宽表格/窄屏多处显示异常、部分 Windows 偶发读取失败等。
|
|
27
|
+
|
|
28
|
+
## [0.39.3] - 2026-08-28
|
|
12
29
|
|
|
13
30
|
### 新增
|
|
14
31
|
|
|
15
|
-
-
|
|
16
|
-
- 新增任务清单与结构化提问卡片,让长任务的进度和需要用户选择的内容更容易理解。
|
|
17
|
-
- 「对话 / 操作 / 观测」使用统一导航;操作和观测页面可以切换工作区查看对应数据。
|
|
32
|
+
- 前端实现支持来源归属运行时注入,使用宽松校验,不符合格式也不会阻断现有流程,方便后续接入完整的来源追溯。
|
|
18
33
|
|
|
19
|
-
|
|
34
|
+
## [0.39.2] - 2026-08-28
|
|
35
|
+
|
|
36
|
+
### 重点更新
|
|
20
37
|
|
|
21
|
-
-
|
|
22
|
-
- Operator Chat 的任务清单工具描述补齐多步骤与 DAG 使用纪律:开始前按具体步骤规划、保持进行中约束、完成后立即更新完整列表,并用面向用户的阶段呈现 DAG 进度,简单任务自动跳过。
|
|
23
|
-
- 正式发布会自动同步更新版本日志和文档站摘要;发布说明优先生成简洁自然的中文,生成服务不可用时也能安全完成发布。
|
|
24
|
-
- 输入框整合模型与推理等级选择,并只展示有真实数据的轮次、耗时、速度和缓存统计。
|
|
25
|
-
- 工作区、会话列表、文件标签和侧栏交互更加紧凑自然,折叠、切换和页面过渡更加流畅。
|
|
26
|
-
- 设置页改用自然中文展示当前工作区的模型状态,减少内部状态和重复信息。
|
|
27
|
-
- DAG 检查器简化节点说明、执行记录和提示词重启面板,长内容更容易阅读和定位。
|
|
38
|
+
- DAG 检查器与提示词重启面板重做:节点备注列改为节点用途简介不再复读节点 ID,默认隐藏协议事件、需要时可一键展开;提示词重启只读面板撑满剩余高度,内容在卡片内滚动,避免长提示词被压缩或被全局滚动条逼出视区。
|
|
28
39
|
|
|
29
40
|
### 修复
|
|
30
41
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
- 修复宽表格、文件预览、滚动条和窄屏布局中的多处显示异常。
|
|
34
|
-
- 修复部分 Windows 环境读取运行状态时的偶发失败,并提高前后端任务验证的可靠性。
|
|
42
|
+
- 为 `views/dag.js` 补充缺失类型声明,修复 next 发布通道的 typecheck 阻断。
|
|
43
|
+
- 记录 release/0.39 上 observe 面板改动的回移植入 0.39.2,方便追溯修复来源。
|
|
35
44
|
|
|
36
45
|
## [0.39.1] - 2026-08-25
|
|
37
46
|
|
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ loop-agent init doctor --repo-root .
|
|
|
54
54
|
loop-agent inspect --repo-root .
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
`init model-catalog` 会通过 Pi runtime 与 OpenCode 的非 verbose 列表发现本机可用模型,只输出白名单模型元数据、Pi setup 状态和 provider 凭据就绪状态,不输出原始配置或凭据。已有 LOW/MED/HIGH 只要仍存在于 Pi
|
|
57
|
+
`init model-catalog` 会通过 Pi runtime 与 OpenCode 的非 verbose 列表发现本机可用模型,只输出白名单模型元数据、Pi setup 状态和 provider 凭据就绪状态,不输出原始配置或凭据。已有 LOW/MED/HIGH 只要仍存在于 Pi 就保持不变;只有已移除或缺失的档位才由模型结合项目、能力、成本和上下文窗口重选。对于 `wizard-local` provider,目录会识别 `aicoder-default < aicoder-plus < aicoder-pro < aicoder-max` 的家族内相对能力顺序,但不会把它机械绑定为固定三档。如果 Pi 没有模型定义,初始化模型会先向用户补齐 provider/model、API/base URL、上下文窗口、最大输出等无法推断的信息并协助配置;如果只是凭据缺失,则保留 harness 选择并修复认证。初始化会保留已有用户内容,并补充 `AGENTS.md`、`harness.json`、`ai_workspace/loop-agent/`、`.agents/skills/`、`.harness/` 和验证脚本等治理入口。
|
|
58
58
|
|
|
59
59
|
控制器升级后,旧项目可能仍使用过期的 repo-local skills、模板、managed blocks 和治理说明。普通安全仓库命令结束时会自动检测目标项目是否需要对齐:非 TTY 只向 stderr 输出提示且不写入目标;TTY 且无 human decisions、无活跃 DAG/Worker 时,可经明确 `y/yes` 同意后应用 deterministic safe actions;也可手动运行统一入口:
|
|
60
60
|
|
|
@@ -126,7 +126,7 @@ agent-worker console doctor --repo .
|
|
|
126
126
|
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
裸 `agent-worker console`
|
|
129
|
+
裸 `agent-worker console` 不在终端询问升级。操作 → 设置提供非阻塞的「更新并初始化」入口,默认选择 npm `latest` 稳定版,也可由操作者显式选择 `next` 预发布版;更新前会先检查活跃运行和全局安装来源。`console doctor`、帮助和版本命令均不触发更新检查。
|
|
130
130
|
|
|
131
131
|
访问 Console <http://127.0.0.1:8790/>;**Operator Chat Official** 是 Console 内的主引导交互,默认打开「对话」工作区。构建时设置 `VITE_OPERATOR_CHAT_DEFAULT_LANDING=tasks` 可改回 Tasks;URL hash(`#/tasks`)与 localStorage 仍优先于默认值。顶部「检视」以及 `/inspect/` 提供只读 Dashboard、DAG、时间线与 artifacts;`loop-agent …` / `agent-worker …` CLI direct path 仍是受治理 fallback。当前状态为 **code ready, dogfood pending/unmet**,不宣称已替代 openCode 或其他外部主会话。
|
|
132
132
|
|
|
@@ -109,8 +109,12 @@ function findForbiddenOverlapsForPacket(task) {
|
|
|
109
109
|
const overlaps = [];
|
|
110
110
|
for (const writeSetEntry of task.writeSet ?? []) {
|
|
111
111
|
for (const forbiddenPath of task.forbiddenPaths ?? []) {
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
// A narrower forbidden child may intentionally carve a protected
|
|
113
|
+
// file out of a broader node writeSet. The runtime write guard gives
|
|
114
|
+
// forbiddenPaths precedence; report a packet conflict only when the
|
|
115
|
+
// writeSet entry itself is inside the forbidden boundary. Console G2
|
|
116
|
+
// separately rechecks task-global forbidden paths with live scope.
|
|
117
|
+
if (pathMatchesPattern(writeSetEntry, forbiddenPath)) {
|
|
114
118
|
overlaps.push({ writeSetEntry, forbiddenPath });
|
|
115
119
|
}
|
|
116
120
|
}
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-08-
|
|
3
|
+
"version": "0.41.0-next.1",
|
|
4
|
+
"gitSha": "082093199826919c9699608265a26e4840207421",
|
|
5
|
+
"builtAt": "2026-08-31T02:28:34.598Z"
|
|
6
6
|
}
|
|
@@ -11,6 +11,7 @@ import { runInspectNext } from "../commands/inspect-next.js";
|
|
|
11
11
|
import { runInstructions } from "../commands/instructions.js";
|
|
12
12
|
import { runTaskAdvance } from "../commands/task-advance.js";
|
|
13
13
|
import { runTaskStatus } from "../commands/task-status.js";
|
|
14
|
+
import { runTaskSourcePrepare } from "../commands/task-source-prepare.js";
|
|
14
15
|
import { runOperator } from "../commands/operator.js";
|
|
15
16
|
import { runPlanList } from "../commands/plan-list.js";
|
|
16
17
|
import { runPlanCheck, runPlanComplete, runPlanCreate, } from "../commands/plan.js";
|
|
@@ -100,7 +101,6 @@ const EVAL_SUBCOMMANDS = [
|
|
|
100
101
|
"outer-loop",
|
|
101
102
|
"ignition",
|
|
102
103
|
];
|
|
103
|
-
const CLOSEOUT_SUBCOMMANDS = ["task"];
|
|
104
104
|
const PLAN_SUBCOMMANDS = ["list", "create", "complete", "check"];
|
|
105
105
|
const SPINE_SUBCOMMANDS = ["audit"];
|
|
106
106
|
const HANDOFF_SUBCOMMANDS = ["check", "coverage"];
|
|
@@ -139,7 +139,7 @@ const DAG_SUBCOMMANDS = [
|
|
|
139
139
|
"final-verification",
|
|
140
140
|
"decision",
|
|
141
141
|
];
|
|
142
|
-
const TASK_SUBCOMMANDS = ["advance", "status"];
|
|
142
|
+
const TASK_SUBCOMMANDS = ["advance", "status", "source"];
|
|
143
143
|
const OPERATOR_SUBCOMMANDS = ["capabilities"];
|
|
144
144
|
const WORKFLOW_SUBCOMMANDS = [
|
|
145
145
|
"list",
|
|
@@ -215,7 +215,7 @@ export const COMMAND_DEFINITIONS = [
|
|
|
215
215
|
name: "init",
|
|
216
216
|
adapter: "none",
|
|
217
217
|
tier: "primary",
|
|
218
|
-
intent: "Initialize a target repository with loop-agent harness capabilities.",
|
|
218
|
+
intent: "Initialize a target repository with loop-agent harness capabilities. Run INSIDE the target repo, or pass the global --repo-root <path> BEFORE this subcommand (e.g. `loop-agent --repo-root . init --profile full --merge`).",
|
|
219
219
|
usage: "init [instructions|model-catalog|doctor|check-update|update|reconcile|upgrade] [--profile full|minimal] [--merge] [--model provider/model | --low-model provider/model --med-model provider/model --high-model provider/model] [--json|--markdown] [--bootstrap-surface|--apply-safe] [--client-recovery=auto|project|user|off] [--run-id <id> --status|--continue|--report]",
|
|
220
220
|
subcommands: [...INIT_SUBCOMMANDS],
|
|
221
221
|
handler: async ({ repoRoot, subcommand, rest }) => {
|
|
@@ -248,8 +248,8 @@ export const COMMAND_DEFINITIONS = [
|
|
|
248
248
|
name: "task",
|
|
249
249
|
adapter: "required",
|
|
250
250
|
tier: "primary",
|
|
251
|
-
intent: "Task lifecycle: advance (mutation)
|
|
252
|
-
usage: "task <advance|status> ...",
|
|
251
|
+
intent: "Task lifecycle: advance (mutation), status (read), source prepare (deterministic source files).",
|
|
252
|
+
usage: "task <advance|status|source> ...",
|
|
253
253
|
subcommands: [...TASK_SUBCOMMANDS],
|
|
254
254
|
handler: async ({ repoRoot, subcommand, rest }) => {
|
|
255
255
|
if (subcommand === "advance") {
|
|
@@ -260,6 +260,10 @@ export const COMMAND_DEFINITIONS = [
|
|
|
260
260
|
await runTaskStatus(repoRoot, rest);
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
|
+
if (subcommand === "source") {
|
|
264
|
+
await runTaskSourcePrepare(repoRoot, rest);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
263
267
|
throw new Error(formatSubcommandUsageError("task", TASK_SUBCOMMANDS));
|
|
264
268
|
},
|
|
265
269
|
},
|
package/dist/cli/program.js
CHANGED
|
@@ -38,8 +38,9 @@ import { runInstructions } from "../commands/instructions.js";
|
|
|
38
38
|
import { runKnowledge } from "../commands/knowledge.js";
|
|
39
39
|
import { runLoop } from "../commands/loop.js";
|
|
40
40
|
import { runLoopBenchmark } from "../commands/loop-benchmark.js";
|
|
41
|
-
import { runTaskAdvance } from "../commands/task-advance.js";
|
|
42
|
-
import { runTaskStatus } from "../commands/task-status.js";
|
|
41
|
+
import { runTaskAdvance, TASK_ADVANCE_USAGE } from "../commands/task-advance.js";
|
|
42
|
+
import { runTaskStatus, TASK_STATUS_USAGE } from "../commands/task-status.js";
|
|
43
|
+
import { runTaskSourcePrepare, TASK_SOURCE_PREPARE_USAGE, } from "../commands/task-source-prepare.js";
|
|
43
44
|
import { runOperator } from "../commands/operator.js";
|
|
44
45
|
import { runPiReuseBenchmark } from "../commands/pi-reuse-benchmark.js";
|
|
45
46
|
import { parsePiPromptArgs, printPiPromptUsage, runPiPrompt, } from "../commands/pi-prompt.js";
|
|
@@ -124,7 +125,11 @@ async function runTaskCommand(repoRoot, subcommand, rest) {
|
|
|
124
125
|
await runTaskStatus(repoRoot, rest);
|
|
125
126
|
return;
|
|
126
127
|
}
|
|
127
|
-
|
|
128
|
+
if (subcommand === "source") {
|
|
129
|
+
await runTaskSourcePrepare(repoRoot, rest);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
throw new Error("usage: task <advance|status|source> ...");
|
|
128
133
|
}
|
|
129
134
|
async function runCommanderAction(ctx, command, subcommand, rest) {
|
|
130
135
|
switch (command) {
|
|
@@ -402,9 +407,38 @@ function createRawArgsCommand(name, description, defaultRepoRoot) {
|
|
|
402
407
|
function addRawSubcommands(parent, subcommands, defaultRepoRoot) {
|
|
403
408
|
for (const subcommand of subcommands) {
|
|
404
409
|
const command = createRawArgsCommand(subcommand, `${parent.name()} ${subcommand}`, defaultRepoRoot);
|
|
410
|
+
applyRawSubcommandUsage(command, `${parent.name()} ${subcommand}`);
|
|
405
411
|
parent.addCommand(command);
|
|
406
412
|
}
|
|
407
413
|
}
|
|
414
|
+
/**
|
|
415
|
+
* Well-known raw-args subcommands whose real USAGE would otherwise only appear
|
|
416
|
+
* after a parse error. `--help` shows this text at the top (beforeAll help text)
|
|
417
|
+
* so one-shot callers (Humans, Pi, Chat) can read the real contract up front.
|
|
418
|
+
* Keys are the full chain (`<parent> <subcommand>`); values must mirror the
|
|
419
|
+
* command module's own usage strings verbatim where one exists.
|
|
420
|
+
*/
|
|
421
|
+
const RAW_SUBCOMMAND_USAGE = {
|
|
422
|
+
"task advance": TASK_ADVANCE_USAGE,
|
|
423
|
+
"task status": TASK_STATUS_USAGE,
|
|
424
|
+
"task source prepare": TASK_SOURCE_PREPARE_USAGE,
|
|
425
|
+
"task source": "usage: task source prepare <task-id> [--from-text|--from-file|--from-stdin|--from-draft] [--dry-run|--apply]\nDeterministic task source projection (managed 需求.md / 执行约束.md). See `task source prepare --help` for the full flag surface.",
|
|
426
|
+
"dag resume": "usage: dag resume --run-id <id>",
|
|
427
|
+
"dag status": "usage: dag status --run-id <id>",
|
|
428
|
+
"dag approve": 'usage: dag approve --run-id <id> --option <A|B|...> [--notes "..."]',
|
|
429
|
+
"dag reject": 'usage: dag reject --run-id <id> --reason "..."',
|
|
430
|
+
"dag rerun": "usage: dag rerun --run-id <id> --from-node <node-id> --plan [--json] | dag rerun --run-id <id> --from-node <node-id> --plan-hash <hash> --request-id <key> --reason <text> [--json]",
|
|
431
|
+
"dag rerun-task": "usage: dag rerun-task --run-id <id> --reason <text> --request-id <key> [--profile auto|minimal|standard|reviewed|supervised] [--task-id <id>] [--json]",
|
|
432
|
+
"dag reconcile-run": "usage: dag reconcile-run --run-id <id> [--action supersede|abandon] [--reason <text>]",
|
|
433
|
+
"dag doctor": "usage: dag doctor [--run-id <id>]\nInspect health issues before approve/reject/resume; no --json (output is already structured JSON).",
|
|
434
|
+
"dag report": "usage: dag report [--run-id <id>] [--lifecycle active|paused|completed|all] [--json|--markdown] [--failed-only] [--latest] [--paused-latest]\nRead-only run report; --json gives structured facts (canonical: `dag report --run-id <id> --lifecycle completed --json`).",
|
|
435
|
+
};
|
|
436
|
+
function applyRawSubcommandUsage(command, chainKey) {
|
|
437
|
+
const usage = RAW_SUBCOMMAND_USAGE[chainKey];
|
|
438
|
+
if (!usage)
|
|
439
|
+
return;
|
|
440
|
+
command.addHelpText("beforeAll", usage);
|
|
441
|
+
}
|
|
408
442
|
function addStandaloneSubcommands(parent, subcommands, handler) {
|
|
409
443
|
for (const subcommand of subcommands) {
|
|
410
444
|
parent
|
|
@@ -640,6 +674,7 @@ export function buildLoopAgentProgram(options) {
|
|
|
640
674
|
const prepare = createRawArgsCommand("prepare", "Prepare deterministic task source files", options.defaultRepoRoot);
|
|
641
675
|
configureTaskSourcePrepare(prepare);
|
|
642
676
|
replaceActionWithOptionAwareDispatch(prepare, options.defaultRepoRoot);
|
|
677
|
+
applyRawSubcommandUsage(prepare, "task source prepare");
|
|
643
678
|
source.addCommand(prepare);
|
|
644
679
|
}
|
|
645
680
|
}
|
|
@@ -19,36 +19,11 @@ export const MAX_SESSION_RETRIES = 5;
|
|
|
19
19
|
/** Hard cap for OpenCode overflow compact+resume recoveries (≤ 2). */
|
|
20
20
|
export const MAX_OVERFLOW_RECOVERIES = 1;
|
|
21
21
|
import { PI_RECOMMENDED_COMPACTION, PI_RECOMMENDED_RETRY, } from "../shared/pi-retry-settings.js";
|
|
22
|
+
import { CONTEXT_OVERFLOW_PHRASES, buildGeneratedOverflowClassifierSource, isContextOverflow as classifySharedOverflow, } from "../shared/pi-context-pressure/overflow.js";
|
|
22
23
|
export { PI_RECOMMENDED_COMPACTION, PI_RECOMMENDED_RETRY };
|
|
23
|
-
|
|
24
|
-
* Shared overflow phrase sources used by isContextOverflow and generated plugins.
|
|
25
|
-
* Keep English + Chinese intranet gateway messages in one place to avoid drift.
|
|
26
|
-
*/
|
|
27
|
-
export const CONTEXT_OVERFLOW_PHRASES = [
|
|
28
|
-
"请求上下文过大",
|
|
29
|
-
"context_length_exceeded",
|
|
30
|
-
"context overflow",
|
|
31
|
-
"context length overflow",
|
|
32
|
-
"too many tokens",
|
|
33
|
-
"maximum context",
|
|
34
|
-
"prompt is too long",
|
|
35
|
-
"request_too_large",
|
|
36
|
-
"context window",
|
|
37
|
-
];
|
|
38
|
-
function escapeRegExpLiteral(value) {
|
|
39
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
40
|
-
}
|
|
41
|
-
const CONTEXT_OVERFLOW_PATTERN = new RegExp(CONTEXT_OVERFLOW_PHRASES.map(escapeRegExpLiteral).join("|"), "i");
|
|
24
|
+
export { CONTEXT_OVERFLOW_PHRASES };
|
|
42
25
|
function buildGeneratedContextOverflowPatternSource() {
|
|
43
|
-
return
|
|
44
|
-
...CONTEXT_OVERFLOW_PHRASES,
|
|
45
|
-
])};
|
|
46
|
-
const OVERFLOW_PATTERN = new RegExp(
|
|
47
|
-
CONTEXT_OVERFLOW_PHRASES.map((phrase) =>
|
|
48
|
-
phrase.replace(/[.*+?^\${}()|[\\]\\\\]/g, "\\\\$&"),
|
|
49
|
-
).join("|"),
|
|
50
|
-
"i",
|
|
51
|
-
);`;
|
|
26
|
+
return buildGeneratedOverflowClassifierSource();
|
|
52
27
|
}
|
|
53
28
|
const PERMANENT_MESSAGE_PATTERNS = [
|
|
54
29
|
{
|
|
@@ -65,7 +40,7 @@ const PERMANENT_MESSAGE_PATTERNS = [
|
|
|
65
40
|
},
|
|
66
41
|
{
|
|
67
42
|
reason: "context-overflow",
|
|
68
|
-
pattern:
|
|
43
|
+
pattern: /context_length_exceeded|请求上下文过大/i,
|
|
69
44
|
},
|
|
70
45
|
{
|
|
71
46
|
reason: "cancelled",
|
|
@@ -180,6 +155,8 @@ function permanentReason(error) {
|
|
|
180
155
|
return "api-error";
|
|
181
156
|
}
|
|
182
157
|
const text = collectErrorText(error);
|
|
158
|
+
if (isContextOverflow(error))
|
|
159
|
+
return "context-overflow";
|
|
183
160
|
for (const entry of PERMANENT_MESSAGE_PATTERNS) {
|
|
184
161
|
if (entry.pattern.test(text))
|
|
185
162
|
return entry.reason;
|
|
@@ -192,7 +169,7 @@ function permanentReason(error) {
|
|
|
192
169
|
* business validation, or standard 502/LLMRequestError as overflow.
|
|
193
170
|
*/
|
|
194
171
|
export function isContextOverflow(error) {
|
|
195
|
-
return
|
|
172
|
+
return classifySharedOverflow(error);
|
|
196
173
|
}
|
|
197
174
|
function looksTransient(error) {
|
|
198
175
|
const text = collectErrorText(error);
|
|
@@ -887,7 +864,7 @@ function textOf(error) {
|
|
|
887
864
|
}
|
|
888
865
|
|
|
889
866
|
function isContextOverflow(error) {
|
|
890
|
-
return
|
|
867
|
+
return isOverflowMessage(textOf(error));
|
|
891
868
|
}
|
|
892
869
|
|
|
893
870
|
function buildOverflowResumePrompt(sessionId, error, attempt) {
|
|
@@ -1163,11 +1140,6 @@ const EXTENSION_PATH = ${JSON.stringify(PI_CONTEXT_OVERFLOW_EXTENSION_PATH)};
|
|
|
1163
1140
|
${buildGeneratedContextOverflowPatternSource()}
|
|
1164
1141
|
const NORMALIZED_PREFIX = "context_length_exceeded:";
|
|
1165
1142
|
|
|
1166
|
-
function isOverflowMessage(text) {
|
|
1167
|
-
if (typeof text !== "string" || !text) return false;
|
|
1168
|
-
return OVERFLOW_PATTERN.test(text);
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
1143
|
export default function loopAgentContextOverflowExtension(pi) {
|
|
1172
1144
|
void EXTENSION_PATH;
|
|
1173
1145
|
pi.on("message_end", (event) => {
|
|
@@ -31,8 +31,28 @@ function sanitizeInputKinds(value) {
|
|
|
31
31
|
.sort();
|
|
32
32
|
return entries.length > 0 ? entries : undefined;
|
|
33
33
|
}
|
|
34
|
+
const AICODER_CAPABILITY_RANK = {
|
|
35
|
+
"aicoder-default": 1,
|
|
36
|
+
"aicoder-plus": 2,
|
|
37
|
+
"aicoder-pro": 3,
|
|
38
|
+
"aicoder-max": 4,
|
|
39
|
+
};
|
|
40
|
+
function relativeCapabilityForModelId(provider, modelId) {
|
|
41
|
+
if (provider !== "wizard-local")
|
|
42
|
+
return undefined;
|
|
43
|
+
const rank = AICODER_CAPABILITY_RANK[modelId];
|
|
44
|
+
if (!rank)
|
|
45
|
+
return undefined;
|
|
46
|
+
return {
|
|
47
|
+
family: "aicoder",
|
|
48
|
+
rank,
|
|
49
|
+
scale: 4,
|
|
50
|
+
order: "weakest-to-strongest",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
34
53
|
function createCatalogEntry(input) {
|
|
35
54
|
const piCompatible = input.source === "pi";
|
|
55
|
+
const relativeCapability = relativeCapabilityForModelId(input.provider, input.modelId);
|
|
36
56
|
return {
|
|
37
57
|
reference: `${input.provider}/${input.modelId}`,
|
|
38
58
|
provider: input.provider,
|
|
@@ -42,6 +62,7 @@ function createCatalogEntry(input) {
|
|
|
42
62
|
credentialReady: input.credentialReady,
|
|
43
63
|
piCompatible,
|
|
44
64
|
eligibleForHarness: piCompatible && input.credentialReady === true && input.tools !== false,
|
|
65
|
+
...(relativeCapability ? { relativeCapability } : {}),
|
|
45
66
|
...(compactRecord({
|
|
46
67
|
reasoning: input.reasoning,
|
|
47
68
|
tools: input.tools,
|
|
@@ -448,6 +469,7 @@ export async function discoverInitModelCatalog(options) {
|
|
|
448
469
|
rules: [
|
|
449
470
|
"Choose only models with eligibleForHarness=true; OpenCode-only entries are context, not proof of Pi executor compatibility.",
|
|
450
471
|
"Use target-project evidence plus model capabilities, cost, context window, and credential readiness; tiers may intentionally share a model.",
|
|
472
|
+
"When relativeCapability is present, compare only entries from the same family and treat larger rank values as stronger; it is a relative capability hint, not a mandatory LOW/MED/HIGH assignment.",
|
|
451
473
|
"Preserve an existing complete usable matrix unless it is unavailable or the user asked to reselect it.",
|
|
452
474
|
"Ask the user only for a material unresolved credential, cost, compliance, or availability decision.",
|
|
453
475
|
],
|
|
@@ -13,7 +13,7 @@ const USAGE = `usage:
|
|
|
13
13
|
[--feature-id <id>]
|
|
14
14
|
[--allowed-path <glob>]...
|
|
15
15
|
[--forbidden-path <glob>]...
|
|
16
|
-
[--verify <label:command>]...
|
|
16
|
+
[--verify <label:command>]... # e.g. --verify "typecheck:npx tsc --noEmit" (label BEFORE the colon)
|
|
17
17
|
[--verify-timeout <label:timeoutMs>]...
|
|
18
18
|
[--backend-test <json>]
|
|
19
19
|
[--accept-recommendations <digest>]
|
|
@@ -31,6 +31,7 @@ const USAGE = `usage:
|
|
|
31
31
|
[--progress-interval-ms <ms>]
|
|
32
32
|
[--dry-run]
|
|
33
33
|
[--json]`;
|
|
34
|
+
export { USAGE as TASK_ADVANCE_USAGE };
|
|
34
35
|
function pushList(target, value) {
|
|
35
36
|
const list = target ?? [];
|
|
36
37
|
list.push(value);
|
|
@@ -232,6 +233,26 @@ export function parseTaskAdvanceArgs(args) {
|
|
|
232
233
|
}
|
|
233
234
|
return { taskId, options };
|
|
234
235
|
}
|
|
236
|
+
const FOREGROUND_DAG_WARNING = [
|
|
237
|
+
"[task advance] --approve-gate will execute the whole DAG in the FOREGROUND:",
|
|
238
|
+
" this terminal must stay open until every node finishes (writer nodes can run 10-60+ min).",
|
|
239
|
+
" Killing it mid-run (timeout / Ctrl-C / closed terminal) leaves an orphaned run that",
|
|
240
|
+
" only `dag reconcile-run --action supersede|abandon` can close.",
|
|
241
|
+
" Prefer background holders instead:",
|
|
242
|
+
" - Console: prepareDagExecution -> runDag (operation-held)",
|
|
243
|
+
" - CLI: nohup loop-agent task advance <task-id> --approve-gate <token> ... &",
|
|
244
|
+
].join("\n");
|
|
245
|
+
/**
|
|
246
|
+
* Operator guardrail (dogfood 2026-08-29): warn a human sitting on a TTY that
|
|
247
|
+
* `--approve-gate` runs the full DAG in the foreground before the process
|
|
248
|
+
* parks on node execution. Piped/non-TTY invocations (Console operations,
|
|
249
|
+
* scripts, --json pipelines) stay silent so machine paths are unaffected.
|
|
250
|
+
*/
|
|
251
|
+
export function warnForegroundDagExecution(options, stream = process.stderr) {
|
|
252
|
+
if (options.quiet || stream.isTTY !== true)
|
|
253
|
+
return;
|
|
254
|
+
stream.write(`${FOREGROUND_DAG_WARNING}\n`);
|
|
255
|
+
}
|
|
235
256
|
function mapOutcome(result) {
|
|
236
257
|
if (result.blockers.length > 0) {
|
|
237
258
|
const code = result.blockers[0]?.code ?? "";
|
|
@@ -351,6 +372,7 @@ export async function runTaskAdvance(repoRoot, args) {
|
|
|
351
372
|
// ONLY for the approve-gate execution path and disposed on every exit;
|
|
352
373
|
// its timer starts only after onRunStart (double guard, no stray timer).
|
|
353
374
|
if (options.approveGate && !options.dryRun && !options.quiet) {
|
|
375
|
+
warnForegroundDagExecution(options);
|
|
354
376
|
progress = createRunDagProgressObserver({
|
|
355
377
|
intervalMs: options.progressIntervalMs,
|
|
356
378
|
});
|
|
@@ -32,6 +32,7 @@ const USAGE = `usage:
|
|
|
32
32
|
[--dry-run | --apply]
|
|
33
33
|
[--force-overwrite-source]
|
|
34
34
|
[--json]`;
|
|
35
|
+
export { USAGE as TASK_SOURCE_PREPARE_USAGE };
|
|
35
36
|
function pushList(target, value) {
|
|
36
37
|
const list = target ?? [];
|
|
37
38
|
list.push(value);
|
|
@@ -386,6 +387,10 @@ function printHuman(result) {
|
|
|
386
387
|
console.log(lines.join("\n"));
|
|
387
388
|
}
|
|
388
389
|
export async function runTaskSourcePrepare(repoRoot, args) {
|
|
390
|
+
// CLI chain routing (task -> source -> prepare) folds the leaf name into
|
|
391
|
+
// rest[0]; strip it so `loop-agent task source prepare <id> ...` works.
|
|
392
|
+
if (args[0] === "prepare")
|
|
393
|
+
args = args.slice(1);
|
|
389
394
|
if (args.includes("--help") || args.includes("-h")) {
|
|
390
395
|
console.log(USAGE);
|
|
391
396
|
process.exitCode = 0;
|
|
@@ -3,6 +3,7 @@ import { buildOperatorResult, operatorFailed, processExitCodeForOutcome, writeOp
|
|
|
3
3
|
const COMMAND = "task status";
|
|
4
4
|
const USAGE = `usage:
|
|
5
5
|
task status <task-id> [--json|--markdown] [--details]`;
|
|
6
|
+
export { USAGE as TASK_STATUS_USAGE };
|
|
6
7
|
export function parseTaskStatusArgs(args) {
|
|
7
8
|
const options = {};
|
|
8
9
|
const positional = [];
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { appendFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
3
5
|
import { computeExtensionToolAllowlistExtras } from "./pi-extension-resolver.js";
|
|
4
6
|
import { BoundedTextPreview, classifyPiFailure, createPiJsonlStreamCollector, DEFAULT_ABORT_GRACE_MS, DEFAULT_STALL_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, extractPiEventStopReason, extractAssistantTextFromPiJson, } from "./pi-executor.js";
|
|
5
7
|
import { serializeSessionEvent } from "./pi-event-serializer.js";
|
|
6
8
|
import { PI_RECOMMENDED_COMPACTION, PI_RECOMMENDED_RETRY, } from "../shared/pi-retry-settings.js";
|
|
9
|
+
import { createCompactionController, createContextPressureExtension, createSiftBridgeState, inMemoryCompactionSettings, isDagSiftEnabled, parseCompactionPolicy, parseSiftBridgeConfig, SIFT_RETRIEVE_TOOL_NAME, } from "../shared/pi-context-pressure/index.js";
|
|
7
10
|
/** Same-session recovery after a transport stall. Exactly one continue per SDK attempt. */
|
|
8
11
|
export const PI_SDK_STALL_CONTINUE_MAX = 1;
|
|
9
12
|
/**
|
|
@@ -215,15 +218,37 @@ async function createSdkSession(sdk, input, shared) {
|
|
|
215
218
|
// Inject rate-limit-tolerant auto-retry settings for the session lifecycle.
|
|
216
219
|
// Prefer SettingsManager.inMemory so harness runs do not depend on ~/.pi or
|
|
217
220
|
// project .pi/settings.json being present/trusted.
|
|
221
|
+
const policy = parseCompactionPolicy();
|
|
222
|
+
const compaction = {
|
|
223
|
+
...PI_RECOMMENDED_COMPACTION,
|
|
224
|
+
...inMemoryCompactionSettings(policy),
|
|
225
|
+
};
|
|
218
226
|
const settingsManager = typeof SettingsManager?.inMemory === "function"
|
|
219
227
|
? SettingsManager.inMemory({
|
|
220
228
|
retry: {
|
|
221
229
|
...PI_RECOMMENDED_RETRY,
|
|
222
230
|
provider: { ...PI_RECOMMENDED_RETRY.provider },
|
|
223
231
|
},
|
|
224
|
-
compaction
|
|
232
|
+
compaction,
|
|
225
233
|
}, { projectTrusted: true })
|
|
226
234
|
: undefined;
|
|
235
|
+
const nodeSessionId = `dag-${randomUUID()}`;
|
|
236
|
+
const controller = createCompactionController();
|
|
237
|
+
const siftEnabled = isDagSiftEnabled();
|
|
238
|
+
const sift = siftEnabled.enabled
|
|
239
|
+
? createSiftBridgeState(parseSiftBridgeConfig({
|
|
240
|
+
sessionId: nodeSessionId,
|
|
241
|
+
defaultStashRoot: path.join(os.tmpdir(), "loop-agent-dag-sift"),
|
|
242
|
+
}))
|
|
243
|
+
: undefined;
|
|
244
|
+
if (sift)
|
|
245
|
+
sift.counters = controller.counters;
|
|
246
|
+
const pressureExtension = createContextPressureExtension({
|
|
247
|
+
name: "dag-pi-context-pressure",
|
|
248
|
+
policy,
|
|
249
|
+
controller,
|
|
250
|
+
sift,
|
|
251
|
+
});
|
|
227
252
|
const loader = new DefaultResourceLoader({
|
|
228
253
|
cwd: input.cwd,
|
|
229
254
|
agentDir,
|
|
@@ -233,6 +258,7 @@ async function createSdkSession(sdk, input, shared) {
|
|
|
233
258
|
...(input.additionalExtensionPaths && input.additionalExtensionPaths.length > 0
|
|
234
259
|
? { additionalExtensionPaths: input.additionalExtensionPaths }
|
|
235
260
|
: {}),
|
|
261
|
+
...(pressureExtension ? { extensionFactories: [pressureExtension] } : {}),
|
|
236
262
|
...(settingsManager ? { settingsManager } : {}),
|
|
237
263
|
appendSystemPromptOverride: (base) => [
|
|
238
264
|
...base,
|
|
@@ -247,10 +273,12 @@ async function createSdkSession(sdk, input, shared) {
|
|
|
247
273
|
// extras into the create-time allowlist; protected builtins, the deny
|
|
248
274
|
// surface, and write-capable extension tools never join.
|
|
249
275
|
const extensionToolExtras = [];
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
extensionToolExtras.
|
|
276
|
+
const registered = collectLoaderExtensionToolNames(loader);
|
|
277
|
+
extensionToolExtras.push(...computeExtensionToolAllowlistExtras(registered.map((name) => ({ name })), input.toolNames));
|
|
278
|
+
if (siftEnabled.enabled &&
|
|
279
|
+
!extensionToolExtras.includes(SIFT_RETRIEVE_TOOL_NAME) &&
|
|
280
|
+
!input.toolNames.includes(SIFT_RETRIEVE_TOOL_NAME)) {
|
|
281
|
+
extensionToolExtras.push(...computeExtensionToolAllowlistExtras([{ name: SIFT_RETRIEVE_TOOL_NAME }], input.toolNames));
|
|
254
282
|
}
|
|
255
283
|
const sessionToolNames = [...input.toolNames, ...extensionToolExtras];
|
|
256
284
|
if (input.requireWriterCustomTools) {
|