@tea-agent/loop-agent 0.40.0-next.9 → 0.41.0-beta.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 +130 -3
- package/README.md +2 -2
- package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
- package/dist/adapters/context-transfer/pi-session.js +61 -0
- package/dist/application/dag/generate-task-dag.js +6 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +21 -5
- package/dist/cli/program.js +61 -4
- package/dist/commands/client-recovery.js +8 -36
- package/dist/commands/dag-artifact.js +284 -0
- package/dist/commands/dag-context.js +184 -0
- package/dist/commands/dag-rerun.js +206 -1
- 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/dag-pi-executor.js +39 -12
- package/dist/executors/pi-sdk-executor.js +36 -5
- package/dist/executors/shell-executor.js +64 -17
- package/dist/governance/checks.js +1 -0
- package/dist/{worker → infrastructure}/console/app-data.js +4 -0
- package/dist/infrastructure/console/artifact-revision-store.js +430 -0
- package/dist/infrastructure/console/context-export-store.js +160 -0
- package/dist/infrastructure/console/dir-lock.js +132 -0
- package/dist/{worker → infrastructure}/console/operation-store.js +28 -0
- package/dist/infrastructure/harness/artifact-store.js +10 -1
- package/dist/infrastructure/harness/atomic-write.js +12 -2
- package/dist/shared/context-transfer/artifact-revision.js +172 -0
- package/dist/shared/context-transfer.js +418 -0
- package/dist/shared/operator/capabilities.js +23 -1
- package/dist/shared/operator/safe-run-summary.js +1 -0
- package/dist/shared/path-safety.js +93 -0
- 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/shared/preview.js +28 -4
- package/dist/task/config-types.js +2 -1
- package/dist/task/task-demand-routing.js +3 -0
- package/dist/worker/console/chat/assistant-content.js +7 -0
- package/dist/worker/console/chat/chat-event-store.js +84 -13
- 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 +285 -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/resource-preferences-store.js +1 -1
- package/dist/worker/console/chat/routes.js +487 -30
- 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 +28 -19
- 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 +32 -3
- package/dist/worker/console/chat/user-questions.js +1 -1
- package/dist/worker/console/console-update-runtime.js +1 -1
- package/dist/worker/console/context-transfer-diagnostics.js +198 -0
- package/dist/worker/console/dag-confirmation.js +1 -1
- package/dist/worker/console/dag-execution-receipt.js +21 -3
- package/dist/worker/console/doctor.js +1 -1
- package/dist/worker/console/draft-store.js +1 -1
- package/dist/worker/console/human-gate-token.js +1 -1
- package/dist/worker/console/index.js +3 -3
- package/dist/worker/console/interview/assessment.js +1 -1
- package/dist/worker/console/interview/session.js +1 -1
- package/dist/worker/console/operation-runner.js +45 -4
- package/dist/worker/console/operation-sse.js +1 -1
- package/dist/worker/console/operation-wait.js +1 -1
- package/dist/worker/console/operator-actions.js +124 -8
- package/dist/worker/console/operator-selection.js +6 -2
- package/dist/worker/console/operator-surface-health.js +1 -1
- package/dist/worker/console/operator-user-error.js +169 -0
- 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 +864 -13
- package/dist/worker/console/security.js +35 -0
- package/dist/worker/console/server.js +177 -44
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bs-CDAXM.js → abnfDiagram-N423BO3Z-DSVcg1YO.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CAkA3We3.js → arc-BtXhIqui.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEmI_zqr.js → architectureDiagram-T3A2C74G-B-nh-ilJ.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-uDHANebE.js → blockDiagram-VBNYF7ZC-BIUSVdZI.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Bv97b4_B.js → c4Diagram-5PPSVZJV-Cmw3L4qM.js} +1 -1
- package/dist/worker/console/static/assets/channel-BhZFNefx.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-shmQKsFz.js → chunk-2GRJ4B5K-CGpMMjGm.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BAraNvcN.js → chunk-2Q5K7J3B-BNBkEpEJ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BirhxUop.js → chunk-5RXB4S5H-ubln3eaU.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C9LgUJpR.js → chunk-5VM5RSS4-_XcBTt1i.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DrU-s-t7.js → chunk-6Q2QTUOP-Ln30Pgrh.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Tx-H_FA2.js → chunk-GF5L2VYU-ESH3lhSx.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BjLtNFrR.js → chunk-JWPE2WC7-DAJt-qXB.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-UNLVwSsy.js → chunk-KBJHAD2P-Cx10LIcH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CBEUX8XD.js → chunk-RYQCIY6F-CENeOxoJ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-WTL7IZOq.js → chunk-XXDRQBXY-DXqK-D38.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Sbv-NJni.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Sbv-NJni.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CkHG6W3s.js → cose-bilkent-JH36ORCC-CE4dmvGY.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BRzFqTaL.js → cynefin-VYW2F7L2-CRacN1zK.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-2_CFp_i7.js → cynefinDiagram-MW4NZA55-Cneukjrt.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJtsmdkE.js → dagre-VZM6K2ZE-DPFboRoL.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DNEFFo6w.js → diagram-7IWD3JNH-DIAQgcOP.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B_IWV7eo.js → diagram-B4RE2ZJO-VrYMKxuy.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DvvRx2dz.js → diagram-LBJQPF4R-CLHvBghn.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CsibsWLg.js → diagram-Q27KOJAE-DVCWBif8.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-les_djBQ.js → diagram-UB23O5K3-BTMmbBzJ.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BEm2n7qJ.js → ebnfDiagram-BXEA7PRR-BUZsKJ56.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BI7vHHVm.js → erDiagram-JOGREHBK-BsBZ5NXC.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CUFCERrB.js → flowDiagram-UKHOOZJN-D7fH_kDa.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-wxyLiGWt.js → ganttDiagram-PKOTCBZU-Bza5OohY.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bt897K8Z.js → gitGraphDiagram-DS77QQ5N-DpkoGR_Y.js} +1 -1
- package/dist/worker/console/static/assets/index-Ius3vxhf.css +1 -0
- package/dist/worker/console/static/assets/index-yASzcbBr.js +451 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DYNx_IPv.js → infoDiagram-6WML65LV-BYm3g6LT.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CzpLNEu6.js → ishikawaDiagram-WSZJBQD7-C2RS_H4v.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-97f9owNU.js → journeyDiagram-NVQOT4AX-B4slKpCo.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BxM9hyBn.js → kanban-definition-27J2QSJJ-B7orRNpI.js} +1 -1
- package/dist/worker/console/static/assets/{linear-ByuxcHvp.js → linear-D1BeBxLQ.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DwPGvpCv.js → mermaid.core-0TtMP8k4.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DCoqG9RT.js → mindmap-definition-FAOFIHXS-XL5EbCtT.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BLSBmBMx.js → pegDiagram-VL7TDLO6-CwF7uas5.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B0t_0oJW.js → pieDiagram-7S7Q4E2Y-A_Jo-72f.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js → quadrantDiagram-CIZ2JOQS-CxOa4gKL.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-B3jRdATC.js → railroadDiagram-AXF67PYL-DoAoswIH.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-cTtXEN.js → requirementDiagram-LRYGKXZP-C1Lc1MlD.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B25igJRE.js → sankeyDiagram-W5VNT64P-DFXOkq0U.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-jW_lM1_D.js → sequenceDiagram-SI44F4Z6-B0ufUCuW.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CrzTgsHE.js → sizeCapture-X5ZJPWSS-iPbW55g3.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B01MvlqE.js → stateDiagram-OKZ733FA-CHiXzEKP.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BtMgzo_H.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-YcF12FiU.js → swimlanes-SLNWSIFB-LyFs7TpX.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cb-OVd9Y.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ClnRcg2s.js → timeline-definition-Z64GVDOM-tNkJnb6z.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B6gr_z-q.js → vennDiagram-T6HMQDX7-DFm7Oo8o.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CvSgguGH.js → wardleyDiagram-T6FBY63Y-tpblTp9i.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-23OtSZCb.js → xychartDiagram-ELKLHX3M-BCDLWR_D.js} +1 -1
- package/dist/worker/console/static/index.html +7 -2
- package/dist/worker/console/static-src/app/useOperatorActions.js +3 -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/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/shell/console-update-reload.js +25 -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 +56 -5
- package/dist/worker/console/workspace-registry.js +335 -62
- package/dist/worker/continuation/worker-continuation.js +278 -0
- package/dist/worker/observe/health.js +1 -1
- package/dist/worker/observe/node-transparency.js +572 -0
- package/dist/worker/observe/routes.js +51 -1
- package/dist/worker/observe/static/api.js +69 -5
- package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
- package/dist/worker/observe/static/dag-context-reason-labels.js +120 -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/state.js +3 -1
- package/dist/worker/observe/static/styles.css +1108 -135
- package/dist/worker/observe/static/views/dag-inspector.js +1257 -59
- package/dist/worker/observe/static/views/dags.js +7 -5
- package/dist/worker/observe/static/views/session-timeline.js +210 -10
- package/dist/worker/outcomes/adapters.js +19 -0
- package/dist/worker/outcomes/types.js +1 -0
- package/dist/worker/pool/attempt-lease.js +97 -66
- package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
- package/dist/worker/pool/reconcile.js +46 -1
- package/dist/worker/pool/run-store.js +2 -0
- package/dist/worker/pool/state-projection.js +2 -0
- package/dist/worker/task-spec/workflow-routing.js +8 -3
- package/dist/workflows/dag/artifact-bindings.js +149 -0
- package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -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 +4 -0
- 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/budget-enforcement.js +10 -0
- package/dist/workflows/dag/context-receipt.js +305 -0
- package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
- package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
- package/dist/workflows/dag/context-transfer/renderers.js +93 -0
- package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
- package/dist/workflows/dag/init-hybrid.js +151 -4
- package/dist/workflows/dag/node-execution.js +112 -27
- package/dist/workflows/dag/path-safety.js +1 -0
- package/dist/workflows/dag/prompt.js +29 -4
- package/dist/workflows/dag/rerun-plan.js +555 -1
- package/dist/workflows/dag/rerun-run.js +601 -15
- package/dist/workflows/dag/runner.js +20 -1
- package/dist/workflows/dag/skill-snapshot.js +17 -0
- package/dist/workflows/dag/types.js +183 -7
- package/docs/architecture/runtime-boundaries.md +8 -7
- package/docs/architecture/worker-and-feature.md +1 -1
- package/docs/templates/agent-dag.schema.json +32 -0
- package/docs/templates/backend-test-dag.json +6 -5
- package/docs/templates/init-managed-agents.md +1 -1
- package/docs/templates/product-line/task.yaml +1 -1
- package/package.json +5 -2
- package/skills/loop-agent/references/command-reference.md +21 -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/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
|
@@ -20,7 +20,7 @@ import { randomBytes } from "node:crypto";
|
|
|
20
20
|
import { readFile } from "node:fs/promises";
|
|
21
21
|
import path from "node:path";
|
|
22
22
|
import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
23
|
-
import { readJsonIfExists, sha256Utf8, writeSecureJson, } from "
|
|
23
|
+
import { readJsonIfExists, sha256Utf8, writeSecureJson, } from "../../infrastructure/console/app-data.js";
|
|
24
24
|
import { hashDagBytes, } from "./dag-confirmation.js";
|
|
25
25
|
/**
|
|
26
26
|
* Structured verification command patterns for the G2 autonomous-execution
|
|
@@ -176,8 +176,26 @@ export function deriveEligibilityFactsFromDagSpec(input) {
|
|
|
176
176
|
}));
|
|
177
177
|
const allWriteSetEntries = writers.flatMap((writer) => writer.writeSet);
|
|
178
178
|
const broadWriteSetRisk = allWriteSetEntries.some(isBroadWriteSetEntry);
|
|
179
|
-
const
|
|
180
|
-
|
|
179
|
+
const taskForbidden = input.forbiddenPaths.map(normalizePathEntry);
|
|
180
|
+
const forbiddenOverlapRisk = tasks.some((task) => stringList(task.writeSet).some((entry) => {
|
|
181
|
+
const normalizedEntry = normalizePathEntry(entry);
|
|
182
|
+
return stringList(task.forbiddenPaths).some((forbidden) => {
|
|
183
|
+
const normalizedForbidden = normalizePathEntry(forbidden);
|
|
184
|
+
const isTaskGlobal = taskForbidden.includes(normalizedForbidden);
|
|
185
|
+
if (isTaskGlobal) {
|
|
186
|
+
// Task-level forbidden paths are hard global boundaries. A broad
|
|
187
|
+
// writer that could include one is not autonomously eligible.
|
|
188
|
+
return (pathMatchesPattern(normalizedEntry, normalizedForbidden) ||
|
|
189
|
+
pathMatchesPattern(normalizedForbidden, normalizedEntry));
|
|
190
|
+
}
|
|
191
|
+
// Node-local forbidden paths may intentionally carve a narrower
|
|
192
|
+
// child (for example md/README.md) out of a broader writer
|
|
193
|
+
// writeSet. That exclusion is enforced by the runtime write guard.
|
|
194
|
+
// It is a conflict only when the writer entry itself is wholly
|
|
195
|
+
// inside the forbidden boundary.
|
|
196
|
+
return pathMatchesPattern(normalizedEntry, normalizedForbidden);
|
|
197
|
+
});
|
|
198
|
+
}));
|
|
181
199
|
const hasStructuredVerification = tasks.some((task) => {
|
|
182
200
|
if (task.executor !== "shell" || !task.shell)
|
|
183
201
|
return false;
|
|
@@ -6,7 +6,7 @@ import { LoopAgentClient } from "../loop-agent/loop-agent-client.js";
|
|
|
6
6
|
import { preflightTargetRepo } from "../preflight.js";
|
|
7
7
|
import { probePiReadiness, } from "./pi-readiness.js";
|
|
8
8
|
import { DEFAULT_OBSERVE_BASE_URL, OBSERVE_START_COMMAND, probeAndClassifyObserve, } from "./observe-health-match.js";
|
|
9
|
-
import { repoFingerprintV1 } from "
|
|
9
|
+
import { repoFingerprintV1 } from "../../infrastructure/console/repo-fingerprint.js";
|
|
10
10
|
import { resolveSiblingLoopAgentBin } from "./sibling-controller.js";
|
|
11
11
|
import { defaultObserveStaticDir, ROUTES } from "../observe/routes.js";
|
|
12
12
|
import { deriveObserveRouteCapabilities } from "../observe/health.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { readJsonIfExists, sha256Json, writeSecureJson, } from "
|
|
2
|
+
import { readJsonIfExists, sha256Json, writeSecureJson, } from "../../infrastructure/console/app-data.js";
|
|
3
3
|
/**
|
|
4
4
|
* 从任意上游载荷安全投影 ledger 摘要(未知形状丢弃,绝不抛错、绝不信任字段外的数据)。
|
|
5
5
|
* 供 DraftStore / prd-intake-bridge 把 prepare/advance 结果中的 ledger 摘要带入草稿。
|
|
@@ -85,7 +85,7 @@ export function verifyHumanGateToken(presented, expected, secret, now = new Date
|
|
|
85
85
|
* invalidates the token (defense against drift-then-confirm).
|
|
86
86
|
*/
|
|
87
87
|
import { createHash } from "node:crypto";
|
|
88
|
-
import { sha256Utf8 } from "
|
|
88
|
+
import { sha256Utf8 } from "../../infrastructure/console/app-data.js";
|
|
89
89
|
export function confirmationPayloadHash(b) {
|
|
90
90
|
const canonical = [
|
|
91
91
|
`dag=${b.dagSha256}`,
|
|
@@ -3,14 +3,14 @@ export { buildOperatorSurfaceHealthV1 } from "./operator-surface-health.js";
|
|
|
3
3
|
export { runConsoleDoctor, formatConsoleDoctorHuman } from "./doctor.js";
|
|
4
4
|
export { isLoopbackHost } from "./loopback.js";
|
|
5
5
|
export { shouldOpenConsoleBrowser, normalizeConsoleBrowserUrl, openSystemBrowser, maybeOpenConsoleBrowser, } from "./open-browser.js";
|
|
6
|
-
export { repoFingerprintV1, normalizeWorktreeRealpath, } from "
|
|
6
|
+
export { repoFingerprintV1, normalizeWorktreeRealpath, } from "../../infrastructure/console/repo-fingerprint.js";
|
|
7
7
|
export { buildObserveDeepLink } from "./observe-link.js";
|
|
8
8
|
export { classifyObserveHealth, probeAndClassifyObserve, capabilityForObserveTarget, OBSERVE_START_COMMAND, DEFAULT_OBSERVE_BASE_URL, } from "./observe-health-match.js";
|
|
9
9
|
export { allowedRecoveryCtas, classifyRecoveryFact, partitionRecoveryCtas, recoveryMatrixInvariants, } from "./recovery-cta.js";
|
|
10
10
|
export { createClosedResourceLoader, createInterviewResourceLoader, tryActivateTool, assertOfficialToolAllowed, listOfficialTools, OFFICIAL_DENIED_TOOL_IDS, INTERVIEW_ALLOWED_TOOLS, INTERVIEW_DENIED_TOOLS, authorizeInterviewTool, } from "./resource-loader.js";
|
|
11
11
|
export { resolveSiblingLoopAgentBin } from "./sibling-controller.js";
|
|
12
|
-
export { openConsoleAppData, defaultConsoleAppDataRoot } from "
|
|
13
|
-
export { OperationStore } from "
|
|
12
|
+
export { openConsoleAppData, defaultConsoleAppDataRoot } from "../../infrastructure/console/app-data.js";
|
|
13
|
+
export { OperationStore } from "../../infrastructure/console/operation-store.js";
|
|
14
14
|
export { createOperationEventStore } from "./operation-sse.js";
|
|
15
15
|
export { DagConfirmationStore } from "./dag-confirmation.js";
|
|
16
16
|
export { DraftStore } from "./draft-store.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { readJsonIfExists, writeSecureJson, } from "
|
|
3
|
+
import { readJsonIfExists, writeSecureJson, } from "../../../infrastructure/console/app-data.js";
|
|
4
4
|
import { computeDraftSha256, } from "../draft-store.js";
|
|
5
5
|
function assessmentPath(appData, assessmentId) {
|
|
6
6
|
return path.join(appData.assessments, `${assessmentId}.json`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { readJsonIfExists, writeSecureJson, } from "
|
|
3
|
+
import { readJsonIfExists, writeSecureJson, } from "../../../infrastructure/console/app-data.js";
|
|
4
4
|
import { createInterviewResourceLoader, } from "./tools.js";
|
|
5
5
|
function sessionPath(appData, sessionId) {
|
|
6
6
|
return path.join(appData.interviews, `${sessionId}.json`);
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import { clipPreview, } from "
|
|
1
|
+
import { clipPreview, } from "../../infrastructure/console/operation-store.js";
|
|
2
2
|
import { stateEvent } from "./operation-sse.js";
|
|
3
3
|
import { extractTrustedRunFacts } from "./operation-run-facts.js";
|
|
4
|
+
/** Swallow-all invoker so observers can never break the state path. */
|
|
5
|
+
function notifySettled(deps, operation, state, info) {
|
|
6
|
+
if (!deps.onSettled)
|
|
7
|
+
return;
|
|
8
|
+
void Promise.resolve()
|
|
9
|
+
.then(() => deps.onSettled?.(operation, state, info))
|
|
10
|
+
.catch(() => undefined);
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* Execute a queued operation via LoopAgentClient (or inject).
|
|
6
14
|
* Timeout without proven exit → needs-reconcile (never Cancel).
|
|
@@ -42,6 +50,7 @@ export async function runOperation(operationId, deps) {
|
|
|
42
50
|
artifactName: `operation-${operationId}`,
|
|
43
51
|
expectJson: true,
|
|
44
52
|
timeoutMs: deps.defaultTimeoutMs,
|
|
53
|
+
env: deps.env,
|
|
45
54
|
onSpawn: (info) => {
|
|
46
55
|
// Chain onto the per-operation write lock; never fire-and-forget a
|
|
47
56
|
// rejected update (unhandled rejection can crash Console on Windows).
|
|
@@ -119,6 +128,10 @@ export async function runOperation(operationId, deps) {
|
|
|
119
128
|
message: finished.errorMessage,
|
|
120
129
|
state: "needs-reconcile",
|
|
121
130
|
});
|
|
131
|
+
notifySettled(deps, finished, "needs-reconcile", {
|
|
132
|
+
ok: false,
|
|
133
|
+
errorCode: finished.errorCode,
|
|
134
|
+
});
|
|
122
135
|
}
|
|
123
136
|
return finished;
|
|
124
137
|
}
|
|
@@ -169,9 +182,10 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
|
|
|
169
182
|
// Supervisory timeout without classified CLI timeout → needs-reconcile
|
|
170
183
|
// Only mark timed-out when we have a machine timeout result after exit.
|
|
171
184
|
const state = result.exitCode !== null ? "timed-out" : "needs-reconcile";
|
|
172
|
-
const
|
|
185
|
+
const finishedAt = new Date().toISOString();
|
|
186
|
+
const patch = {
|
|
173
187
|
state,
|
|
174
|
-
finishedAt
|
|
188
|
+
finishedAt,
|
|
175
189
|
artifactRefs,
|
|
176
190
|
stdoutPreview: previewStdout,
|
|
177
191
|
stderrPreview: previewStderr,
|
|
@@ -186,7 +200,15 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
|
|
|
186
200
|
...(runFacts.runSummary ? { runSummary: runFacts.runSummary } : {}),
|
|
187
201
|
}
|
|
188
202
|
: {}),
|
|
203
|
+
};
|
|
204
|
+
const current = await deps.store.get(operationId);
|
|
205
|
+
if (!current)
|
|
206
|
+
throw new Error(`operation not found: ${operationId}`);
|
|
207
|
+
await deps.beforeTerminal?.({ ...current, ...patch }, state, {
|
|
208
|
+
ok: false,
|
|
209
|
+
errorCode: patch.errorCode,
|
|
189
210
|
});
|
|
211
|
+
const updated = await deps.store.update(operationId, patch);
|
|
190
212
|
stateEvent(deps.events, updated, state, updated.errorMessage);
|
|
191
213
|
if (runFacts) {
|
|
192
214
|
appendSafeResultEvent(deps, operationId, state, {
|
|
@@ -202,6 +224,10 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
|
|
|
202
224
|
data: { ok: false, exitCode: result.exitCode },
|
|
203
225
|
});
|
|
204
226
|
}
|
|
227
|
+
notifySettled(deps, updated, state, {
|
|
228
|
+
ok: false,
|
|
229
|
+
errorCode: updated.errorCode,
|
|
230
|
+
});
|
|
205
231
|
return updated;
|
|
206
232
|
}
|
|
207
233
|
const envelope = coerceEnvelope(result);
|
|
@@ -210,7 +236,7 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
|
|
|
210
236
|
const processOk = envelope?.ok === true || (result.ok && result.exitCode === 0);
|
|
211
237
|
const ok = processOk && !businessBlock;
|
|
212
238
|
const state = ok ? "succeeded" : "failed";
|
|
213
|
-
const
|
|
239
|
+
const patch = {
|
|
214
240
|
state,
|
|
215
241
|
finishedAt: new Date().toISOString(),
|
|
216
242
|
artifactRefs,
|
|
@@ -238,9 +264,20 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
|
|
|
238
264
|
...(runFacts.runSummary ? { runSummary: runFacts.runSummary } : {}),
|
|
239
265
|
}
|
|
240
266
|
: {}),
|
|
267
|
+
};
|
|
268
|
+
if (!operation)
|
|
269
|
+
throw new Error(`operation not found: ${operationId}`);
|
|
270
|
+
await deps.beforeTerminal?.({ ...operation, ...patch }, state, {
|
|
271
|
+
ok,
|
|
272
|
+
errorCode: patch.errorCode,
|
|
241
273
|
});
|
|
274
|
+
const updated = await deps.store.update(operationId, patch);
|
|
242
275
|
stateEvent(deps.events, updated, state, updated.errorMessage);
|
|
243
276
|
appendSafeResultEvent(deps, operationId, state, { ok, exitCode: result.exitCode }, runFacts);
|
|
277
|
+
notifySettled(deps, updated, state, {
|
|
278
|
+
ok,
|
|
279
|
+
errorCode: updated.errorCode,
|
|
280
|
+
});
|
|
244
281
|
if (ok && operation?.action === "dagRequestInterrupt") {
|
|
245
282
|
await projectInterruptRequestOntoTarget(operation, result.json, deps);
|
|
246
283
|
}
|
|
@@ -300,6 +337,10 @@ export function scheduleOperation(operationId, deps) {
|
|
|
300
337
|
})
|
|
301
338
|
.then((updated) => {
|
|
302
339
|
stateEvent(deps.events, updated, "needs-reconcile", message);
|
|
340
|
+
notifySettled(deps, updated, "needs-reconcile", {
|
|
341
|
+
ok: false,
|
|
342
|
+
errorCode: updated.errorCode,
|
|
343
|
+
});
|
|
303
344
|
})
|
|
304
345
|
.catch(() => {
|
|
305
346
|
// A failed canonical store update cannot be represented safely.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { ensureSecureDir, writeSecureJsonSync } from "
|
|
3
|
+
import { ensureSecureDir, writeSecureJsonSync } from "../../infrastructure/console/app-data.js";
|
|
4
4
|
const DEFAULT_MAX_EVENTS = 1000;
|
|
5
5
|
function safeOperationId(operationId) {
|
|
6
6
|
return operationId.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 180);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { projectOperationEventSummary, projectOperationForChat, } from "./chat/chat-event-store.js";
|
|
2
|
-
import { isTerminalOperationState, } from "
|
|
2
|
+
import { isTerminalOperationState, } from "../../infrastructure/console/operation-store.js";
|
|
3
3
|
/**
|
|
4
4
|
* P2: read-only event-driven long poll on the canonical operation event ring
|
|
5
5
|
* (2026-08-13 Operator Chat long-run supervision). Server contract bounds:
|
|
@@ -4,13 +4,14 @@ import { DAG_RERUN_PROMPT_OVERRIDE_ENV, isDagRerunPromptOverrideEnabled, MAX_DAG
|
|
|
4
4
|
import { buildOperatorResult, operatorFailed, operatorSucceeded, } from "../../shared/operator/envelope.js";
|
|
5
5
|
import { CANONICAL_TASK_ID_PATTERN, formatLocalBusinessDate, getTaskPaths, loadTaskConfig, } from "../../task/runtime.js";
|
|
6
6
|
import { diffTaskContract, validateDraftForTask, } from "../../task/contract/index.js";
|
|
7
|
-
import { stageUtf8Text } from "
|
|
7
|
+
import { stageUtf8Text } from "../../infrastructure/console/app-data.js";
|
|
8
8
|
import { ALL_CONFIRMATION_CHALLENGES, hashDagBytes, } from "./dag-confirmation.js";
|
|
9
9
|
import { capabilityForObserveTarget, DEFAULT_OBSERVE_BASE_URL, OBSERVE_START_COMMAND, probeAndClassifyObserve, } from "./observe-health-match.js";
|
|
10
10
|
import { buildInspectDeepLink, buildObserveDeepLink, } from "./observe-link.js";
|
|
11
11
|
import { resolveLatestDagRunIdForTask } from "./resolve-dag-run-for-task.js";
|
|
12
|
-
import { repoFingerprintV1 } from "
|
|
12
|
+
import { repoFingerprintV1 } from "../../infrastructure/console/repo-fingerprint.js";
|
|
13
13
|
import { scheduleOperation, } from "./operation-runner.js";
|
|
14
|
+
import { recordContextTransferEvent } from "./context-transfer-diagnostics.js";
|
|
14
15
|
import { readinessGateFailure, } from "./pi-readiness.js";
|
|
15
16
|
import { validatePiModelMatrixTiers, writePiModelMatrix, } from "./harness-pi-model-matrix.js";
|
|
16
17
|
import { isAssessmentFreshForDraft } from "./interview/assessment.js";
|
|
@@ -481,7 +482,7 @@ async function buildPromptOverrideCliArgs(ctx, overrides) {
|
|
|
481
482
|
}
|
|
482
483
|
return args;
|
|
483
484
|
}
|
|
484
|
-
async function acceptOperation(ctx, input) {
|
|
485
|
+
export async function acceptOperation(ctx, input) {
|
|
485
486
|
const created = await ctx.operations.create({
|
|
486
487
|
clientRequestId: input.clientRequestId,
|
|
487
488
|
action: input.action,
|
|
@@ -517,12 +518,55 @@ async function acceptOperation(ctx, input) {
|
|
|
517
518
|
},
|
|
518
519
|
};
|
|
519
520
|
}
|
|
521
|
+
if (input.onAdmitted) {
|
|
522
|
+
try {
|
|
523
|
+
await input.onAdmitted(created.operation);
|
|
524
|
+
}
|
|
525
|
+
catch {
|
|
526
|
+
// Lifecycle observation must never block admission.
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (input.prepare) {
|
|
530
|
+
try {
|
|
531
|
+
await input.prepare();
|
|
532
|
+
}
|
|
533
|
+
catch (error) {
|
|
534
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
535
|
+
const preparedFailure = input.prepareFailure?.(error);
|
|
536
|
+
await ctx.operations.update(created.operation.operationId, {
|
|
537
|
+
state: "failed",
|
|
538
|
+
startedAt: created.operation.createdAt,
|
|
539
|
+
finishedAt: new Date().toISOString(),
|
|
540
|
+
errorCode: preparedFailure?.errorCode ?? "INVALID_INPUT",
|
|
541
|
+
errorMessage: message,
|
|
542
|
+
});
|
|
543
|
+
return {
|
|
544
|
+
kind: "error",
|
|
545
|
+
status: preparedFailure?.status ?? 400,
|
|
546
|
+
body: preparedFailure?.body ?? operatorFailed({
|
|
547
|
+
command: input.action,
|
|
548
|
+
outcome: "blocked",
|
|
549
|
+
code: "INVALID_INPUT",
|
|
550
|
+
message,
|
|
551
|
+
}),
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const transferObserver = contextTransferSettledObserver(ctx, input.action, input.actionParams);
|
|
520
556
|
const runnerDeps = {
|
|
521
557
|
store: ctx.operations,
|
|
522
558
|
events: ctx.events,
|
|
523
559
|
client: ctx.client,
|
|
524
560
|
repoRoot: ctx.repoRoot,
|
|
561
|
+
env: { ...process.env, LOOP_CONSOLE_APP_DATA: ctx.appData.root },
|
|
525
562
|
runCommand: ctx.runCommand,
|
|
563
|
+
beforeTerminal: input.beforeTerminal,
|
|
564
|
+
onSettled: async (operation, state, info) => {
|
|
565
|
+
// Diagnostics are best-effort and must not prevent authoritative Worker
|
|
566
|
+
// settlement from running.
|
|
567
|
+
await Promise.resolve(transferObserver?.(operation, state, info)).catch(() => undefined);
|
|
568
|
+
await input.onSettled?.(operation, state, info);
|
|
569
|
+
},
|
|
526
570
|
};
|
|
527
571
|
scheduleOperation(created.operation.operationId, runnerDeps);
|
|
528
572
|
return {
|
|
@@ -536,6 +580,63 @@ async function acceptOperation(ctx, input) {
|
|
|
536
580
|
},
|
|
537
581
|
};
|
|
538
582
|
}
|
|
583
|
+
/**
|
|
584
|
+
* Map artifact revision / rerun operation outcomes onto the append-only
|
|
585
|
+
* context-transfer lifecycle event log. Only stages the Console truly
|
|
586
|
+
* observes (admission + settle) are recorded; CLI-kernel-internal stages
|
|
587
|
+
* stay in the kernel. Unknown actions emit nothing.
|
|
588
|
+
*/
|
|
589
|
+
function contextTransferSettledObserver(ctx, action, actionParams) {
|
|
590
|
+
if (action !== "artifactRevisionStage" &&
|
|
591
|
+
action !== "artifactRevisionPlan" &&
|
|
592
|
+
action !== "artifactRevisionExecute") {
|
|
593
|
+
return undefined;
|
|
594
|
+
}
|
|
595
|
+
const strParam = (key) => {
|
|
596
|
+
const value = actionParams[key];
|
|
597
|
+
return typeof value === "string" ? value.trim() : undefined;
|
|
598
|
+
};
|
|
599
|
+
const baseFields = {
|
|
600
|
+
runId: strParam("runId"),
|
|
601
|
+
nodeId: strParam("nodeId"),
|
|
602
|
+
revisionId: strParam("revisionId"),
|
|
603
|
+
};
|
|
604
|
+
return (operation, state, info) => {
|
|
605
|
+
let event;
|
|
606
|
+
if (action === "artifactRevisionStage") {
|
|
607
|
+
event = info.ok ? "artifact_revision.validated" : "artifact_revision.rejected";
|
|
608
|
+
}
|
|
609
|
+
else if (action === "artifactRevisionPlan") {
|
|
610
|
+
event = info.ok ? "artifact_rerun.plan_created" : "artifact_rerun.blocked";
|
|
611
|
+
}
|
|
612
|
+
else if (state === "needs-reconcile") {
|
|
613
|
+
event = "artifact_rerun.needs_reconcile";
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
event = info.ok ? "artifact_rerun.finished" : "artifact_rerun.failed";
|
|
617
|
+
}
|
|
618
|
+
// The stage CLI assigns the revision id; it only exists in the settle
|
|
619
|
+
// result, never in admission params.
|
|
620
|
+
let resultRevisionId;
|
|
621
|
+
const resultRevision = operation.result
|
|
622
|
+
?.revision;
|
|
623
|
+
if (resultRevision && typeof resultRevision === "object") {
|
|
624
|
+
resultRevisionId = resultRevision.revisionId;
|
|
625
|
+
}
|
|
626
|
+
return recordContextTransferEvent({
|
|
627
|
+
appData: ctx.appData,
|
|
628
|
+
event,
|
|
629
|
+
fields: {
|
|
630
|
+
...baseFields,
|
|
631
|
+
...(typeof resultRevisionId === "string"
|
|
632
|
+
? { revisionId: resultRevisionId }
|
|
633
|
+
: {}),
|
|
634
|
+
operationId: operation.operationId,
|
|
635
|
+
...(info.ok ? {} : { reasonCode: info.errorCode ?? "INTERNAL_ERROR" }),
|
|
636
|
+
},
|
|
637
|
+
}).catch(() => undefined);
|
|
638
|
+
};
|
|
639
|
+
}
|
|
539
640
|
async function acceptConsoleUpdateAndInit(ctx, clientRequestId, channel) {
|
|
540
641
|
if (!ctx.consoleUpdateExecutor) {
|
|
541
642
|
return {
|
|
@@ -1148,14 +1249,14 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1148
1249
|
if (usesUnifiedSurface) {
|
|
1149
1250
|
const inspectPath = target
|
|
1150
1251
|
? buildInspectDeepLink(consoleOrigin, target).slice(consoleOrigin.length)
|
|
1151
|
-
: "
|
|
1252
|
+
: "/#/inspect";
|
|
1152
1253
|
return {
|
|
1153
1254
|
kind: "sync",
|
|
1154
1255
|
status: 200,
|
|
1155
1256
|
body: operatorSucceeded("observeLink", {
|
|
1156
1257
|
url: target
|
|
1157
1258
|
? buildInspectDeepLink(consoleOrigin, target)
|
|
1158
|
-
: `${consoleOrigin.replace(/\/+$/, "")}
|
|
1259
|
+
: `${consoleOrigin.replace(/\/+$/, "")}/#/inspect`,
|
|
1159
1260
|
inspectPath,
|
|
1160
1261
|
status: "same-origin",
|
|
1161
1262
|
requiredCapability: requiredCapability ?? null,
|
|
@@ -1641,9 +1742,10 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1641
1742
|
broadWriteSetRisk: typeof reviewPacket.broadWriteSetRisk === "boolean"
|
|
1642
1743
|
? reviewPacket.broadWriteSetRisk
|
|
1643
1744
|
: derivedFacts.broadWriteSetRisk,
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1745
|
+
// Always use the staged DAG + live task boundary derivation here.
|
|
1746
|
+
// The generation review packet lacks task-boundary scope and can
|
|
1747
|
+
// mistake a narrower node-local exclusion for a global overlap.
|
|
1748
|
+
forbiddenOverlapRisk: derivedFacts.forbiddenOverlapRisk,
|
|
1647
1749
|
hasStructuredVerification: packetShellVerification,
|
|
1648
1750
|
};
|
|
1649
1751
|
const assessment = assessAutonomousExecutionEligibility(eligibility);
|
|
@@ -1816,6 +1918,18 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1816
1918
|
const taskIdError = taskIdInputError(taskId);
|
|
1817
1919
|
if (taskIdError)
|
|
1818
1920
|
return invalid(action, taskIdError);
|
|
1921
|
+
// Optional write-set gate approval: the token is the server-issued
|
|
1922
|
+
// `<gate-id>:sha256:<hex>` that `task status` reports in
|
|
1923
|
+
// gate.approveCommand. Forwarded as --approve-gate so an operator can
|
|
1924
|
+
// complete the human approval through the Console operation path
|
|
1925
|
+
// instead of dropping to a raw terminal. This dispatch already sits
|
|
1926
|
+
// behind the Console mutation gate (boot cookie + confirmation
|
|
1927
|
+
// header), so it carries the same authority as typing the CLI flag.
|
|
1928
|
+
const approveGateRaw = str(p.approveGate);
|
|
1929
|
+
if (approveGateRaw &&
|
|
1930
|
+
!/^[A-Za-z0-9._-]+:sha256:[0-9a-f]{64}$/.test(approveGateRaw)) {
|
|
1931
|
+
return invalid(action, "approveGate must look like <gate-id>:sha256:<64-hex> (copy the token from task status gate.approveCommand)");
|
|
1932
|
+
}
|
|
1819
1933
|
const args = ["task", "advance", taskId];
|
|
1820
1934
|
const title = str(p.title);
|
|
1821
1935
|
if (title)
|
|
@@ -1829,6 +1943,8 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1829
1943
|
const profile = str(p.profile);
|
|
1830
1944
|
if (profile)
|
|
1831
1945
|
args.push("--profile", profile);
|
|
1946
|
+
if (approveGateRaw)
|
|
1947
|
+
args.push("--approve-gate", approveGateRaw);
|
|
1832
1948
|
appendEngineeringCliArgs(args, parseEngineeringBoundaryFromParams(p));
|
|
1833
1949
|
args.push("--json");
|
|
1834
1950
|
return acceptOperation(ctx, {
|
|
@@ -27,7 +27,11 @@ export function encodeInspectHash(selection) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
export function buildInspectPath(selection) {
|
|
30
|
-
|
|
30
|
+
if (!selection)
|
|
31
|
+
return "/#/inspect";
|
|
32
|
+
const hash = encodeInspectHash(selection);
|
|
33
|
+
const internal = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
34
|
+
return `/#/inspect${internal}`;
|
|
31
35
|
}
|
|
32
36
|
export function buildInspectUrl(origin, selection) {
|
|
33
37
|
const base = origin.trim().replace(/\/+$/, "");
|
|
@@ -99,7 +103,7 @@ export function selectionFromObserveLinkTarget(target) {
|
|
|
99
103
|
export function normalizeLegacyConsoleDagHash(pathnameAndHash) {
|
|
100
104
|
const [pathname, hash = ""] = pathnameAndHash.split("#", 2);
|
|
101
105
|
if ((pathname === "/" || pathname === "") && /^\/dag\/[^/]+$/.test(hash)) {
|
|
102
|
-
return
|
|
106
|
+
return `/#/inspect${hash}`;
|
|
103
107
|
}
|
|
104
108
|
return pathnameAndHash;
|
|
105
109
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { deriveObserveRouteCapabilities, resolveObservePackageIdentity, } from "../observe/health.js";
|
|
2
|
-
import { repoFingerprintV1 } from "
|
|
2
|
+
import { repoFingerprintV1 } from "../../infrastructure/console/repo-fingerprint.js";
|
|
3
3
|
export function buildOperatorSurfaceHealthV1(input) {
|
|
4
4
|
const { packageName, packageVersion } = resolveObservePackageIdentity();
|
|
5
5
|
const snapshotAvailable = input.routes.some((route) => route.method === "GET" && route.pattern.test("/api/snapshot"));
|
|
@@ -14,6 +14,162 @@ const MUTATION_GATE_COPY = [
|
|
|
14
14
|
copy: "请求主机校验失败:非回环绑定时要求 Host 头,请刷新页面或检查访问地址。",
|
|
15
15
|
},
|
|
16
16
|
];
|
|
17
|
+
/**
|
|
18
|
+
* Context-transfer / artifact-revision 稳定 reason code(kernel CLI 会原样
|
|
19
|
+
* 透传到操作错误信息里)→ 面向操作者的中文语义。与 observe 侧
|
|
20
|
+
* dag-context-reason-labels.js 同源,保留原码便于诊断。
|
|
21
|
+
*/
|
|
22
|
+
const CONTEXT_TRANSFER_CODE_COPY = [
|
|
23
|
+
{
|
|
24
|
+
pattern: /\bCONTEXT_RECEIPT_MISSING\b/,
|
|
25
|
+
copy: "该节点没有执行时上下文回执(CONTEXT_RECEIPT_MISSING):只有真实执行过的模型节点才有可导出的上下文;历史 run 不做事后回填。",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /\bCONTEXT_COMPONENT_UNAVAILABLE\b/,
|
|
29
|
+
copy: "部分上下文组件当前不可用(CONTEXT_COMPONENT_UNAVAILABLE),无法生成完整交接包。",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
pattern: /\bCONTEXT_BUNDLE_TOO_LARGE\b/,
|
|
33
|
+
copy: "导出内容超出体积上限(CONTEXT_BUNDLE_TOO_LARGE),请缩小节点范围或联系维护者调整上限。",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
pattern: /\bRAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED\b/,
|
|
37
|
+
copy: "原文导出包含敏感数据风险(RAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED),需要先勾选风险确认。",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
pattern: /\bSECRET_SCAN_CONFIRMATION_REQUIRED\b/,
|
|
41
|
+
copy: "候选文件疑似包含凭据(SECRET_SCAN_CONFIRMATION_REQUIRED),确认风险后才能继续。",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
pattern: /\bARTIFACT_BINDING_UNAVAILABLE\b/,
|
|
45
|
+
copy: "缺少结构化产物关系(ARTIFACT_BINDING_UNAVAILABLE):只有带产物绑定的新 run 支持修订与派生,历史 run 仅可查看/下载。",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pattern: /\bARTIFACT_NOT_REVISION_ELIGIBLE\b/,
|
|
49
|
+
copy: "该产物不允许修订替换(ARTIFACT_NOT_REVISION_ELIGIBLE)。",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
pattern: /\bARTIFACT_IDENTITY_AMBIGUOUS\b/,
|
|
53
|
+
copy: "产物身份不唯一(ARTIFACT_IDENTITY_AMBIGUOUS),无法安全定位修订目标。",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
pattern: /\bARTIFACT_REVISION_SCHEMA_INVALID\b/,
|
|
57
|
+
copy: "候选文件不符合该产物声明的数据结构(ARTIFACT_REVISION_SCHEMA_INVALID),已拒绝入库。",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
pattern: /\bARTIFACT_REVISION_PATH_INVALID\b/,
|
|
61
|
+
copy: "候选目标路径无效(ARTIFACT_REVISION_PATH_INVALID),已拒绝。",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
pattern: /\bARTIFACT_REVISION_EXPIRED\b/,
|
|
65
|
+
copy: "修订候选已过期(ARTIFACT_REVISION_EXPIRED),请重新上传后再继续。",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
pattern: /\bARTIFACT_REVISION_DRIFT\b/,
|
|
69
|
+
copy: "候选文件与登记内容不一致(ARTIFACT_REVISION_DRIFT),请重新上传。",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
pattern: /\bARTIFACT_REVISION_QUOTA_EXCEEDED\b/,
|
|
73
|
+
copy: "修订暂存区配额已满(ARTIFACT_REVISION_QUOTA_EXCEEDED),请先丢弃不需要的修订或等待过期回收。",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
pattern: /\bARTIFACT_CONSUMER_UNKNOWN\b/,
|
|
77
|
+
copy: "无法确定受影响的下游节点(ARTIFACT_CONSUMER_UNKNOWN),派生继续已被阻止。",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
pattern: /\bARTIFACT_IMPACT_UNSAFE\b/,
|
|
81
|
+
copy: "影响范围包含不能自动重跑的节点(ARTIFACT_IMPACT_UNSAFE),派生继续已被阻止。",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
pattern: /\bRERUN_PLAN_DRIFT\b|\bPLAN_DRIFT\b/,
|
|
85
|
+
copy: "继续运行计划与当前事实发生漂移(RERUN_PLAN_DRIFT),请重新生成计划后再执行。",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
pattern: /\bWORKER_MANAGED_CONTINUATION_UNSUPPORTED\b/,
|
|
89
|
+
copy: "由 Worker 托管的运行暂不支持派生继续(WORKER_MANAGED_CONTINUATION_UNSUPPORTED),这是当前版本的明确边界,不是失败。",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
pattern: /\bWORKER_CONTINUATION_AUTHORITY_MISMATCH\b/,
|
|
93
|
+
copy: "Worker 派生运行的归属事实不一致(WORKER_CONTINUATION_AUTHORITY_MISMATCH),请刷新计划并核对 Task Pool 状态。",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
pattern: /\bWORKER_CONTINUATION_LEASE_CONFLICT\b/,
|
|
97
|
+
copy: "该 Worker Task 已有运行占用(WORKER_CONTINUATION_LEASE_CONFLICT),请等待当前运行结束或先完成恢复核对。",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
pattern: /\bWORKER_CONTINUATION_NEEDS_RECONCILE\b/,
|
|
101
|
+
copy: "Worker 派生运行已存在但终态尚未完成核对(WORKER_CONTINUATION_NEEDS_RECONCILE),不会再次启动;请先执行恢复核对。",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
pattern: /\bPARENT_IMMUTABILITY_VIOLATION\b/,
|
|
105
|
+
copy: "父运行事实发生变化(PARENT_IMMUTABILITY_VIOLATION),已阻止派生以保护历史证据。",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
pattern: /\bPARENT_LIFECYCLE\b/,
|
|
109
|
+
copy: "父运行当前状态不允许派生继续(PARENT_LIFECYCLE)。",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
pattern: /\bREQUEST_ID_REUSE_CONFLICT\b/,
|
|
113
|
+
copy: "相同请求 ID 已被其他操作占用(REQUEST_ID_REUSE_CONFLICT),请更换请求 ID 重试。",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
pattern: /\bOPERATION_NEEDS_RECONCILE\b/,
|
|
117
|
+
copy: "操作记录需要先恢复核对(OPERATION_NEEDS_RECONCILE):上次执行未确认结束,请刷新操作状态后重试。",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
pattern: /\bCONTEXT_EXPORT_FAILED\b/,
|
|
121
|
+
copy: "上下文导出失败(CONTEXT_EXPORT_FAILED),请稍后重试;若持续失败请检查该节点是否存在可导出的执行事实。",
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
pattern: /\bCONTEXT_EXPORT_UNAVAILABLE\b/,
|
|
125
|
+
copy: "导出内容不存在或已过期(CONTEXT_EXPORT_UNAVAILABLE),请重新生成。",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
pattern: /\bLEASE_HELD\b/,
|
|
129
|
+
copy: "资源正被其他操作占用(LEASE_HELD),请等待当前操作结束或稍后重试。",
|
|
130
|
+
},
|
|
131
|
+
// 更新并初始化链路的稳定错误码。
|
|
132
|
+
{
|
|
133
|
+
pattern: /\bREGISTRY_VERSION_REGRESSION\b/,
|
|
134
|
+
copy: "所选渠道的最新版本比当前安装的版本更旧(REGISTRY_VERSION_REGRESSION),已阻止降级更新。请改用包含更新版本的渠道(如 next/beta)。",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
pattern: /\bUPDATE_LOCKED\b/,
|
|
138
|
+
copy: "另一个 loop-agent 更新正在进行(UPDATE_LOCKED),请等待其结束后重试。",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
pattern: /\bINSTALL_FAILED\b/,
|
|
142
|
+
copy: "新版本安装失败(INSTALL_FAILED),请检查网络与 npm registry 后重试。",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
pattern: /\bINSTALL_VERIFICATION_FAILED\b/,
|
|
146
|
+
copy: "安装后校验未通过(INSTALL_VERIFICATION_FAILED),未接棒新版本;请重试或手动安装。",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
pattern: /\bACTIVE_RUNTIME\b/,
|
|
150
|
+
copy: "当前存在活跃的 DAG/Worker 运行(ACTIVE_RUNTIME),更新已推迟;请等待运行结束后再更新。",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
pattern: /\bCHAT_TURN_ACTIVE\b/,
|
|
154
|
+
copy: "对话正在执行中(CHAT_TURN_ACTIVE),更新已推迟;请等待当前回合结束后再更新。",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
pattern: /\bOPERATION_ACTIVE\b/,
|
|
158
|
+
copy: "另一个 Console 操作正在进行(OPERATION_ACTIVE),请等待其结束后再更新。",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
pattern: /\bHANDOFF_FAILED\b/,
|
|
162
|
+
copy: "新版本已安装,但接棒启动新 Console 失败(HANDOFF_FAILED);旧进程未被关闭,可直接重试或手动重启 Console。",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
pattern: /\bINIT_NEEDS_RECONCILE\b/,
|
|
166
|
+
copy: "安全初始化未完全通过(INIT_NEEDS_RECONCILE):版本已就绪,请查看初始化待处理项后重试。",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
pattern: /\bINVALID_VERSION\b/,
|
|
170
|
+
copy: "安装版本或渠道版本号无法解析(INVALID_VERSION),请重试;若持续出现请反馈。",
|
|
171
|
+
},
|
|
172
|
+
];
|
|
17
173
|
/** Map internal spawn/controller errors to actionable Chinese copy. */
|
|
18
174
|
export function formatOperatorUserError(message) {
|
|
19
175
|
const raw = (message ?? "").trim();
|
|
@@ -37,6 +193,19 @@ export function formatOperatorUserError(message) {
|
|
|
37
193
|
if (/force-required|requires --force/i.test(raw)) {
|
|
38
194
|
return "该终态需要强制 Discard。请确认后勾选强制再试。";
|
|
39
195
|
}
|
|
196
|
+
if (/not-global|GLOBAL_INSTALL_UNPROVEN/i.test(raw)) {
|
|
197
|
+
return "当前 Console 由仓库内构建启动,不是全局 npm 安装,一键更新不可用。请全局安装(npm i -g @tea-agent/loop-agent)后从全局命令启动 Console 再更新,或手动更新本仓库后重启。";
|
|
198
|
+
}
|
|
199
|
+
if (/could not verify npm (?:latest|next) \(timeout\)/i.test(raw)) {
|
|
200
|
+
return "检查 npm 更新渠道超时:请确认本机网络或 npm registry 镜像可访问后重试。";
|
|
201
|
+
}
|
|
202
|
+
if (/could not verify npm (?:latest|next) \(/i.test(raw)) {
|
|
203
|
+
return "检查 npm 更新渠道失败:请确认本机 npm 可用、网络可访问 registry 后重试。";
|
|
204
|
+
}
|
|
205
|
+
for (const entry of CONTEXT_TRANSFER_CODE_COPY) {
|
|
206
|
+
if (entry.pattern.test(raw))
|
|
207
|
+
return entry.copy;
|
|
208
|
+
}
|
|
40
209
|
for (const entry of MUTATION_GATE_COPY) {
|
|
41
210
|
if (entry.pattern.test(raw))
|
|
42
211
|
return entry.copy;
|