@tea-agent/loop-agent 0.37.0 → 0.37.1-beta.0
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 +2 -6
- package/CHANGELOG.md +71 -144
- package/README.md +1 -1
- package/bin/loop-agent.js +1 -37
- package/dist/application/task-lifecycle/advance.js +0 -1
- package/dist/application/task-lifecycle/observe.js +0 -15
- package/dist/application/task-lifecycle/plan-transitions.js +0 -15
- package/dist/cli/command-definitions.js +0 -7
- package/dist/cli/program.js +3 -8
- package/dist/commands/init-upgrade.js +19 -351
- package/dist/commands/init.js +67 -14
- package/dist/commands/run-dag-progress.js +0 -14
- package/dist/commands/task-advance.js +3 -33
- package/dist/executors/dag-pi-executor.js +30 -47
- package/dist/executors/pi-sdk-executor.js +0 -34
- package/dist/executors/shell-executor.js +95 -6
- package/dist/shared/operator/capabilities.js +13 -200
- package/dist/shared/package-metadata.js +0 -42
- package/dist/task/contract/project.js +0 -4
- package/dist/task/source-prepare/completeness.js +0 -53
- package/dist/task/source-prepare/parse-intent.js +12 -82
- package/dist/task/source-prepare/prepare.js +5 -102
- package/dist/task/source-prepare/semantic-intake.js +23 -144
- package/dist/worker/console/chat/artifact-card.js +1 -8
- package/dist/worker/console/chat/chat-event-store.js +0 -152
- package/dist/worker/console/chat/human-gate-card.js +1 -9
- package/dist/worker/console/chat/operation-card.js +2 -71
- package/dist/worker/console/chat/pi-runtime.js +62 -111
- package/dist/worker/console/chat/routes.js +10 -43
- package/dist/worker/console/chat/session-store.js +1 -9
- package/dist/worker/console/chat/shortcuts.js +7 -9
- package/dist/worker/console/chat/turn-process.js +23 -204
- package/dist/worker/console/chat/workspace-landing.js +1 -2
- package/dist/worker/console/operation-runner.js +6 -155
- package/dist/worker/console/operator-actions.js +14 -391
- package/dist/worker/console/operator-user-error.js +0 -4
- package/dist/worker/console/recovery-cta.js +3 -50
- package/dist/worker/console/static/assets/index-HX1pbOyl.css +1 -0
- package/dist/worker/console/static/assets/index-M0BLEBfh.js +56 -0
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +9 -13
- package/dist/worker/console/static-src/app/useOperatorActions.js +2 -4
- package/dist/worker/console/static-src/app/useRecoveryActions.js +56 -65
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +1 -73
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +30 -114
- package/dist/worker/console/static-src/operator-chat/refs.js +0 -3
- package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +13 -67
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -12
- package/dist/worker/console/static-src/operator-chat/useComposer.js +8 -45
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -7
- package/dist/worker/loop-agent/loop-agent-client.js +3 -17
- package/dist/worker/observability/read-model.js +0 -20
- package/dist/worker/observe/spec-evidence.js +8 -3
- package/dist/worker/observe/static/operator-chrome.d.ts +0 -1
- package/dist/worker/observe/static/operator-chrome.js +3 -10
- package/dist/worker/observe/static/views/dag-inspector.js +71 -6
- package/dist/worker/observe/static/views/dag.js +0 -12
- package/dist/worker/preflight.js +1 -2
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +707 -37
- package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
- package/dist/workflows/dag/backend-test-markdown-workflow.js +109 -7
- package/dist/workflows/dag/backend-test-module-stem.js +5 -0
- package/dist/workflows/dag/backend-test-pytest-collection.js +345 -24
- package/dist/workflows/dag/backend-test-scenario-param.js +890 -164
- package/dist/workflows/dag/backend-test-writer-completeness.js +47 -16
- package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
- package/dist/workflows/dag/dynamic-runtime/shared.js +1 -9
- package/dist/workflows/dag/frontend-implementation-contract.js +39 -233
- package/dist/workflows/dag/frontend-prewrite-gate.js +61 -364
- package/dist/workflows/dag/frontend-repair.js +18 -219
- package/dist/workflows/dag/frontend-verification-trace.js +32 -47
- package/dist/workflows/dag/init-hybrid.js +82 -165
- package/dist/workflows/dag/node-execution.js +0 -89
- package/dist/workflows/dag/recovery-recommendation.js +0 -58
- package/dist/workflows/dag/runner.js +15 -333
- package/dist/workflows/dag/scheduler.js +3 -257
- package/dist/workflows/dag/types.js +9 -130
- package/docs/README.md +3 -3
- package/docs/architecture/evolution.md +67 -102
- package/docs/templates/backend-test-dag.json +50 -32
- package/docs/templates/init-managed-agents.md +2 -5
- package/harness.json +2 -2
- package/package.json +3 -9
- package/skills/loop-agent/SKILL.md +0 -1
- package/skills/loop-agent/references/command-reference.md +0 -4
- package/dist/build-stamp.json +0 -6
- package/dist/commands/dag-request-interrupt.js +0 -20
- package/dist/worker/console/chat/assistant-content.js +0 -121
- package/dist/worker/console/chat/semantic-activity.js +0 -477
- package/dist/worker/console/operation-run-facts.js +0 -190
- package/dist/worker/console/operation-wait.js +0 -355
- package/dist/worker/console/recovery-error-copy.js +0 -198
- package/dist/worker/console/static/assets/abnfDiagram-N423BO3Z-DSvF6RXQ.js +0 -1
- package/dist/worker/console/static/assets/arc-DuI4ogtJ.js +0 -1
- package/dist/worker/console/static/assets/architectureDiagram-T3A2C74G-DdBbgD4y.js +0 -36
- package/dist/worker/console/static/assets/blockDiagram-VBNYF7ZC-xQC2HELm.js +0 -132
- package/dist/worker/console/static/assets/c4Diagram-5PPSVZJV-DPMSgwIZ.js +0 -10
- package/dist/worker/console/static/assets/channel-DLVz9TYW.js +0 -1
- package/dist/worker/console/static/assets/chunk-2GRJ4B5K-WTEKTxin.js +0 -1
- package/dist/worker/console/static/assets/chunk-2Q5K7J3B-B6vZ0Pv_.js +0 -1
- package/dist/worker/console/static/assets/chunk-5RXB4S5H-BrerNAix.js +0 -231
- package/dist/worker/console/static/assets/chunk-5VM5RSS4-D_ch2aaI.js +0 -15
- package/dist/worker/console/static/assets/chunk-6Q2QTUOP-VvfacNrq.js +0 -88
- package/dist/worker/console/static/assets/chunk-GF5L2VYU-B-uGFIg2.js +0 -206
- package/dist/worker/console/static/assets/chunk-JWPE2WC7-BlysCtod.js +0 -1
- package/dist/worker/console/static/assets/chunk-KBJHAD2P-BjAUAfcT.js +0 -1
- package/dist/worker/console/static/assets/chunk-RYQCIY6F-BeZnBmb-.js +0 -1
- package/dist/worker/console/static/assets/chunk-XXDRQBXY-Bbfe3UJG.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BeAuGcO9.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BeAuGcO9.js +0 -1
- package/dist/worker/console/static/assets/cose-bilkent-JH36ORCC-BKJQnYVM.js +0 -1
- package/dist/worker/console/static/assets/cynefin-VYW2F7L2-B1wtI3hU.js +0 -166
- package/dist/worker/console/static/assets/cynefinDiagram-MW4NZA55-DCF6DBSu.js +0 -62
- package/dist/worker/console/static/assets/cytoscape.esm-yzknjiTM.js +0 -321
- package/dist/worker/console/static/assets/dagre-VZM6K2ZE-BJyNGRlP.js +0 -4
- package/dist/worker/console/static/assets/defaultLocale-DX6XiGOO.js +0 -1
- package/dist/worker/console/static/assets/diagram-7IWD3JNH-B7j1-VsZ.js +0 -30
- package/dist/worker/console/static/assets/diagram-B4RE2ZJO-BREJ140a.js +0 -3
- package/dist/worker/console/static/assets/diagram-LBJQPF4R-CDPHmHGH.js +0 -24
- package/dist/worker/console/static/assets/diagram-Q27KOJAE-BtZLrez1.js +0 -24
- package/dist/worker/console/static/assets/diagram-UB23O5K3-mzybu8oU.js +0 -41
- package/dist/worker/console/static/assets/ebnfDiagram-BXEA7PRR-Dk3I2uO6.js +0 -1
- package/dist/worker/console/static/assets/erDiagram-JOGREHBK-BT97u_tQ.js +0 -85
- package/dist/worker/console/static/assets/flowDiagram-UKHOOZJN-CMOtYzui.js +0 -156
- package/dist/worker/console/static/assets/ganttDiagram-PKOTCBZU-DiNydkuY.js +0 -292
- package/dist/worker/console/static/assets/gitGraphDiagram-DS77QQ5N-Cwt6fLkl.js +0 -106
- package/dist/worker/console/static/assets/graph-DOmOIIwC.js +0 -1
- package/dist/worker/console/static/assets/index-DQxiso1w.js +0 -325
- package/dist/worker/console/static/assets/index-_j0Hzo69.css +0 -1
- package/dist/worker/console/static/assets/infoDiagram-6WML65LV-AsGIGKKB.js +0 -2
- package/dist/worker/console/static/assets/init-Gi6I4Gst.js +0 -1
- package/dist/worker/console/static/assets/ishikawaDiagram-WSZJBQD7-BL8ITZh3.js +0 -70
- package/dist/worker/console/static/assets/journeyDiagram-NVQOT4AX-VPKAUX8M.js +0 -139
- package/dist/worker/console/static/assets/kanban-definition-27J2QSJJ-BL56hfGp.js +0 -89
- package/dist/worker/console/static/assets/layout-D-LzfAck.js +0 -1
- package/dist/worker/console/static/assets/linear-BmSG3nIZ.js +0 -1
- package/dist/worker/console/static/assets/map-DxJ2ADlA.js +0 -1
- package/dist/worker/console/static/assets/mermaid.core-DWGK9kwP.js +0 -308
- package/dist/worker/console/static/assets/mindmap-definition-FAOFIHXS--vvKLjo0.js +0 -96
- package/dist/worker/console/static/assets/ordinal-Cboi1Yqb.js +0 -1
- package/dist/worker/console/static/assets/pegDiagram-VL7TDLO6-B41mxb2-.js +0 -1
- package/dist/worker/console/static/assets/pieDiagram-7S7Q4E2Y-DTlu77sw.js +0 -39
- package/dist/worker/console/static/assets/quadrantDiagram-CIZ2JOQS-Bk5A7alv.js +0 -7
- package/dist/worker/console/static/assets/railroadDiagram-AXF67PYL-Csf9jzQy.js +0 -1
- package/dist/worker/console/static/assets/requirementDiagram-LRYGKXZP-CeptoSNx.js +0 -84
- package/dist/worker/console/static/assets/sankeyDiagram-W5VNT64P-A-DLCLer.js +0 -40
- package/dist/worker/console/static/assets/sequenceDiagram-SI44F4Z6-22VbPdOI.js +0 -162
- package/dist/worker/console/static/assets/sizeCapture-X5ZJPWSS-DWvAyBC9.js +0 -1
- package/dist/worker/console/static/assets/stateDiagram-OKZ733FA-qICZ75yT.js +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DzKvfHTX.js +0 -1
- package/dist/worker/console/static/assets/swimlanes-SLNWSIFB-xi7lcMyp.js +0 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cxqr_qM1.js +0 -8
- package/dist/worker/console/static/assets/timeline-definition-Z64GVDOM-Bu6Nl6O2.js +0 -120
- package/dist/worker/console/static/assets/vennDiagram-T6HMQDX7-BzMz4Bn9.js +0 -34
- package/dist/worker/console/static/assets/wardleyDiagram-T6FBY63Y-CxaJnzc5.js +0 -78
- package/dist/worker/console/static/assets/xychartDiagram-ELKLHX3M-5JK-omQK.js +0 -7
- package/dist/worker/console/static/fonts/katex/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/worker/console/static/fonts/katex/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/worker/console/static-src/operator-chat/activity-journey.js +0 -125
- package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
- package/dist/worker/console/static-src/operator-chat/activity-references.js +0 -20
- package/dist/worker/console/static-src/operator-chat/slash-palette-layout.js +0 -24
- package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +0 -141
- package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
- package/dist/worker/observability/interrupt-eligibility.js +0 -264
- package/dist/workflows/dag/contract-output-registry.js +0 -14
- package/dist/workflows/dag/contract-validator-registrations.js +0 -8
- package/dist/workflows/dag/frontend-recovery-plan.js +0 -73
- package/dist/workflows/dag/frontend-recovery-root-manifest.js +0 -123
- package/dist/workflows/dag/frontend-recovery-run.js +0 -539
- package/dist/workflows/dag/frontend-writer-recovery.js +0 -106
- package/dist/workflows/dag/frontend-writer-rollback.js +0 -821
- package/dist/workflows/dag/interrupt-request.js +0 -559
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<link rel="stylesheet" href="/inspect/operator-chrome.css" />
|
|
8
8
|
<title>Loop 操作台 · Operator Console</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-M0BLEBfh.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-HX1pbOyl.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="root"></div>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { formatIneligibleRerunMessage, nextActionForIneligibleRerun, } from "../../recovery-error-copy.js";
|
|
2
1
|
/** Legacy step ids from older sessions map onto the merged contract step. */
|
|
3
2
|
export function normalizeWizardStep(step) {
|
|
4
3
|
if (step === "validate" || step === "apply" || step === "spine") {
|
|
@@ -58,7 +57,6 @@ export const RECOVERY_FACT_LABEL = {
|
|
|
58
57
|
"terminal-failed": "已终止(失败)",
|
|
59
58
|
"terminal-succeeded": "已终止(成功)",
|
|
60
59
|
"needs-reconcile": "需要对账",
|
|
61
|
-
"running-active": "正在运行",
|
|
62
60
|
};
|
|
63
61
|
export const LAYER_VALUE_LABEL = {
|
|
64
62
|
idle: "空闲",
|
|
@@ -110,20 +108,18 @@ export const LONG_RUNNING_ACTIONS = new Set([
|
|
|
110
108
|
"runDag",
|
|
111
109
|
"dagRerun",
|
|
112
110
|
"dagReconcileRun",
|
|
113
|
-
"dagRequestInterrupt",
|
|
114
111
|
"standaloneTaskRerun",
|
|
115
112
|
]);
|
|
116
|
-
export function
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
});
|
|
113
|
+
export function formatDagRerunIneligible(plan) {
|
|
114
|
+
const fromBlocked = (plan.blockedReasons ?? []).map(String);
|
|
115
|
+
const fromNodes = (plan.blockingNodes ?? []).map((n) => [n.nodeId, n.reasonCode].filter(Boolean).join(":"));
|
|
116
|
+
const reasons = [...fromBlocked, ...fromNodes].filter(Boolean);
|
|
117
|
+
if (reasons.length === 0) {
|
|
118
|
+
return "从节点重跑不具备安全资格(子图含 writer / unsafe shell / decision-gate 等)。可改用「完整重跑任务」,或另选只读安全子图的起始节点。";
|
|
119
|
+
}
|
|
120
|
+
return `从节点重跑不具备安全资格:${reasons.slice(0, 6).join("; ")}${reasons.length > 6 ? "…" : ""}。可改用「完整重跑任务」。`;
|
|
125
121
|
}
|
|
126
|
-
export async function waitForOperation(operationId, timeoutMs =
|
|
122
|
+
export async function waitForOperation(operationId, timeoutMs = 90_000) {
|
|
127
123
|
const started = Date.now();
|
|
128
124
|
while (Date.now() - started < timeoutMs) {
|
|
129
125
|
const res = await fetch(`/api/operator/v1/operations/${encodeURIComponent(operationId)}`, { credentials: "same-origin" });
|
|
@@ -6,8 +6,8 @@ import { confirmationToken, CONFIRMATION_HEADER, LONG_RUNNING_ACTIONS, postOpera
|
|
|
6
6
|
* seconds server-side (imports + intake). Prevents the "page looks frozen"
|
|
7
7
|
* gap between click and the terminal flash message. */
|
|
8
8
|
const ACTION_PROGRESS_COPY = {
|
|
9
|
-
bootstrapFromPrd: "正在导入 PRD 并创建任务:归档文档 → 确定性解析 →
|
|
10
|
-
importPrd: "正在导入 PRD:归档文档 → 确定性解析 →
|
|
9
|
+
bootstrapFromPrd: "正在导入 PRD 并创建任务:归档文档 → 确定性解析 → 语义结构化(约 10–60 秒,请勿关闭页面)",
|
|
10
|
+
importPrd: "正在导入 PRD:归档文档 → 确定性解析 → 语义结构化(约 10–60 秒,请勿关闭页面)",
|
|
11
11
|
interviewStart: "正在启动需求访谈…",
|
|
12
12
|
interviewTurn: "正在提交访谈回答…",
|
|
13
13
|
interviewSkip: "正在跳过访谈并生成评估…",
|
|
@@ -16,8 +16,6 @@ const ACTION_PROGRESS_COPY = {
|
|
|
16
16
|
contractApply: "正在应用契约(写入需求与执行约束)…",
|
|
17
17
|
spineCheck: "正在运行 Spine 审计…",
|
|
18
18
|
dagGenerate: "正在生成 DAG…",
|
|
19
|
-
standaloneTaskRerun: "正在完整重跑任务:服务端校验资格后启动新 run…",
|
|
20
|
-
workerTaskRetry: "正在重新排队 Worker Task…",
|
|
21
19
|
};
|
|
22
20
|
/** Central operator-action dispatcher: POST /api/operator/v1/operations with
|
|
23
21
|
* polling, long-running background waits, interview payload handoff and the
|
|
@@ -1,35 +1,10 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
2
|
import { isAutoRecoveryReason } from "../../recovery-selection.js";
|
|
3
|
-
import { formatOperatorUserError } from "../../operator-user-error.js";
|
|
4
3
|
import { formatDagRerunIneligible, postOperator, requestId, } from "./console-types.js";
|
|
5
|
-
/** Destructive reconcile still consumes a browser Human Gate receipt.
|
|
6
|
-
* Same-task rerun / Worker retry are autonomous and must not enter here. */
|
|
7
|
-
async function consumeMutationGateAndRun(input) {
|
|
8
|
-
const prep = await input.runAction("prepareMutationGate", {
|
|
9
|
-
action: input.action,
|
|
10
|
-
actionParams: input.actionParams,
|
|
11
|
-
});
|
|
12
|
-
if (!input.isActionSuccess(prep))
|
|
13
|
-
return;
|
|
14
|
-
const receiptSource = (prep?.result ?? prep);
|
|
15
|
-
const receipt = receiptSource.receiptId
|
|
16
|
-
? receiptSource
|
|
17
|
-
: (receiptSource.result ?? receiptSource);
|
|
18
|
-
if (!receipt.receiptId || !receipt.humanGateToken) {
|
|
19
|
-
input.setOpError("prepareMutationGate 未返回可消费的 Human Gate receipt");
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
await input.runAction(input.action, {
|
|
23
|
-
...input.actionParams,
|
|
24
|
-
confirmationId: receipt.receiptId,
|
|
25
|
-
humanGateToken: receipt.humanGateToken,
|
|
26
|
-
}, { clientRequestId: input.clientRequestId });
|
|
27
|
-
}
|
|
28
4
|
/** Recovery CTA dispatch: diagnose/report/inspect shortcuts, reason-gated
|
|
29
|
-
* confirm flow with dagRerunPlan preflight,
|
|
30
|
-
* Human Gate only for destructive reconcile. */
|
|
5
|
+
* confirm flow with dagRerunPlan preflight, and gated reruns/retries. */
|
|
31
6
|
export function useRecoveryActions(params) {
|
|
32
|
-
const { shell, actions, taskId, dagRunId, fromNodeId, featureId, recoveryReason, recoveryReasonTouched, recoveryConfirm, recoveryPlanSummary,
|
|
7
|
+
const { shell, actions, taskId, dagRunId, fromNodeId, featureId, recoveryReason, recoveryReasonTouched, recoveryConfirm, recoveryPlanSummary, setRecoveryConfirm, setRecoveryPlanSummary, setRecoveryReport, setRecoveryReason, setRecoveryReasonTouched, buildCurrentRecoveryReason, openFullCanvas, } = params;
|
|
33
8
|
const { setOpError, setOpErrorCode, setOpMessage, setBusy } = shell;
|
|
34
9
|
const { runAction, isActionSuccess } = actions;
|
|
35
10
|
const handleRecoveryCta = useCallback(async (cta) => {
|
|
@@ -108,7 +83,7 @@ export function useRecoveryActions(params) {
|
|
|
108
83
|
setOpMessage(null);
|
|
109
84
|
}
|
|
110
85
|
else if (plan.eligible === false) {
|
|
111
|
-
setOpError(
|
|
86
|
+
setOpError(body.error?.message ?? formatDagRerunIneligible(plan));
|
|
112
87
|
}
|
|
113
88
|
else {
|
|
114
89
|
setOpMessage(body.error?.message ??
|
|
@@ -175,7 +150,7 @@ export function useRecoveryActions(params) {
|
|
|
175
150
|
planHash = plan.planHash?.trim() || planHash;
|
|
176
151
|
planEligible = plan.eligible;
|
|
177
152
|
if (plan.eligible === false) {
|
|
178
|
-
setOpError(
|
|
153
|
+
setOpError(planBody?.error?.message ?? formatDagRerunIneligible(plan));
|
|
179
154
|
return;
|
|
180
155
|
}
|
|
181
156
|
if (planBody && planBody.ok === false && !planHash) {
|
|
@@ -185,7 +160,7 @@ export function useRecoveryActions(params) {
|
|
|
185
160
|
}
|
|
186
161
|
}
|
|
187
162
|
if (planEligible === false) {
|
|
188
|
-
setOpError(
|
|
163
|
+
setOpError(formatDagRerunIneligible(recoveryPlanSummary ?? {}));
|
|
189
164
|
return;
|
|
190
165
|
}
|
|
191
166
|
if (!planHash) {
|
|
@@ -201,10 +176,26 @@ export function useRecoveryActions(params) {
|
|
|
201
176
|
setOpError("完整重跑任务需要 DAG 运行 ID");
|
|
202
177
|
return;
|
|
203
178
|
}
|
|
204
|
-
|
|
179
|
+
const actionParams = {
|
|
205
180
|
runId,
|
|
206
181
|
reason,
|
|
207
182
|
...(taskId.trim() ? { taskId: taskId.trim() } : {}),
|
|
183
|
+
};
|
|
184
|
+
const prep = await runAction("prepareMutationGate", {
|
|
185
|
+
action: "standaloneTaskRerun",
|
|
186
|
+
actionParams,
|
|
187
|
+
});
|
|
188
|
+
if (!isActionSuccess(prep))
|
|
189
|
+
return;
|
|
190
|
+
const receipt = (prep?.result ?? prep);
|
|
191
|
+
if (!receipt.receiptId || !receipt.humanGateToken) {
|
|
192
|
+
setOpError("prepareMutationGate 未返回可消费的 Human Gate receipt");
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
await runAction("standaloneTaskRerun", {
|
|
196
|
+
...actionParams,
|
|
197
|
+
confirmationId: receipt.receiptId,
|
|
198
|
+
humanGateToken: receipt.humanGateToken,
|
|
208
199
|
}, { clientRequestId });
|
|
209
200
|
return;
|
|
210
201
|
}
|
|
@@ -214,35 +205,27 @@ export function useRecoveryActions(params) {
|
|
|
214
205
|
setOpError("重新排队 Worker Task 需要任务 ID");
|
|
215
206
|
return;
|
|
216
207
|
}
|
|
217
|
-
|
|
208
|
+
const actionParams = {
|
|
218
209
|
taskId: id,
|
|
219
210
|
reason,
|
|
220
211
|
...(featureId.trim() ? { featureId: featureId.trim() } : {}),
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (!
|
|
227
|
-
setOpError("中止运行需要 DAG 运行 ID");
|
|
212
|
+
};
|
|
213
|
+
const prep = await runAction("prepareMutationGate", {
|
|
214
|
+
action: "workerTaskRetry",
|
|
215
|
+
actionParams,
|
|
216
|
+
});
|
|
217
|
+
if (!isActionSuccess(prep))
|
|
228
218
|
return;
|
|
229
|
-
|
|
230
|
-
if (
|
|
231
|
-
setOpError("
|
|
219
|
+
const receipt = (prep?.result ?? prep);
|
|
220
|
+
if (!receipt.receiptId || !receipt.humanGateToken) {
|
|
221
|
+
setOpError("prepareMutationGate 未返回可消费的 Human Gate receipt");
|
|
232
222
|
return;
|
|
233
223
|
}
|
|
234
|
-
await
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
actionParams: {
|
|
240
|
-
runId,
|
|
241
|
-
reasonCode: interruptReasonCode.trim() || "operator-request",
|
|
242
|
-
reasonDetail: reason,
|
|
243
|
-
},
|
|
244
|
-
clientRequestId,
|
|
245
|
-
});
|
|
224
|
+
await runAction("workerTaskRetry", {
|
|
225
|
+
...actionParams,
|
|
226
|
+
confirmationId: receipt.receiptId,
|
|
227
|
+
humanGateToken: receipt.humanGateToken,
|
|
228
|
+
}, { clientRequestId });
|
|
246
229
|
return;
|
|
247
230
|
}
|
|
248
231
|
if (cta.id === "reconcile") {
|
|
@@ -254,18 +237,27 @@ export function useRecoveryActions(params) {
|
|
|
254
237
|
// Default supersede: orphan/interrupted runs should not be resumed.
|
|
255
238
|
// The browser Human Gate binds the destructive action + reason; the CLI
|
|
256
239
|
// still fail-closes when runner is not proven dead/stopped.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
240
|
+
const actionParams = {
|
|
241
|
+
runId,
|
|
242
|
+
reason,
|
|
243
|
+
reconcileAction: "supersede",
|
|
244
|
+
};
|
|
245
|
+
const prep = await runAction("prepareMutationGate", {
|
|
261
246
|
action: "dagReconcileRun",
|
|
262
|
-
actionParams
|
|
263
|
-
runId,
|
|
264
|
-
reason,
|
|
265
|
-
reconcileAction: "supersede",
|
|
266
|
-
},
|
|
267
|
-
clientRequestId,
|
|
247
|
+
actionParams,
|
|
268
248
|
});
|
|
249
|
+
if (!isActionSuccess(prep))
|
|
250
|
+
return;
|
|
251
|
+
const receipt = (prep?.result ?? prep);
|
|
252
|
+
if (!receipt.receiptId || !receipt.humanGateToken) {
|
|
253
|
+
setOpError("prepareMutationGate 未返回可消费的 Human Gate receipt");
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
await runAction("dagReconcileRun", {
|
|
257
|
+
...actionParams,
|
|
258
|
+
confirmationId: receipt.receiptId,
|
|
259
|
+
humanGateToken: receipt.humanGateToken,
|
|
260
|
+
}, { clientRequestId });
|
|
269
261
|
return;
|
|
270
262
|
}
|
|
271
263
|
setOpMessage(`${cta.label}:请经 CLI — ${cta.commandHint ?? ""}`);
|
|
@@ -276,7 +268,6 @@ export function useRecoveryActions(params) {
|
|
|
276
268
|
recoveryConfirm,
|
|
277
269
|
recoveryPlanSummary?.planHash,
|
|
278
270
|
recoveryReason,
|
|
279
|
-
interruptReasonCode,
|
|
280
271
|
runAction,
|
|
281
272
|
isActionSuccess,
|
|
282
273
|
setOpError,
|
|
@@ -16,16 +16,12 @@ export function useRecoveryConsole(params) {
|
|
|
16
16
|
const [recoveryReasonTouched, setRecoveryReasonTouched] = useState(false);
|
|
17
17
|
const [recoveryPlanSummary, setRecoveryPlanSummary] = useState(null);
|
|
18
18
|
const [recoveryConfirm, setRecoveryConfirm] = useState(null);
|
|
19
|
-
const [interruptIntent, setInterruptIntent] = useState(false);
|
|
20
|
-
const [interruptReasonCode, setInterruptReasonCode] = useState("operator-request");
|
|
21
|
-
const [interruptEligibility, setInterruptEligibility] = useState(null);
|
|
22
19
|
const [recoveryRuns, setRecoveryRuns] = useState([]);
|
|
23
20
|
const [recoveryNodes, setRecoveryNodes] = useState([]);
|
|
24
21
|
const [recoveryRunsLoading, setRecoveryRunsLoading] = useState(false);
|
|
25
22
|
const [recoveryNodesLoading, setRecoveryNodesLoading] = useState(false);
|
|
26
23
|
const [recoveryRunStatus, setRecoveryRunStatus] = useState(null);
|
|
27
24
|
const [recoveryFailureCategory, setRecoveryFailureCategory] = useState(null);
|
|
28
|
-
const [frontendRecovery, setFrontendRecovery] = useState(null);
|
|
29
25
|
const [manualRunId, setManualRunId] = useState(false);
|
|
30
26
|
const [manualNodeId, setManualNodeId] = useState(false);
|
|
31
27
|
const [recoveryReport, setRecoveryReport] = useState(null);
|
|
@@ -128,7 +124,6 @@ export function useRecoveryConsole(params) {
|
|
|
128
124
|
setRecoveryNodes([]);
|
|
129
125
|
setRecoveryRunStatus(null);
|
|
130
126
|
setRecoveryFailureCategory(null);
|
|
131
|
-
setFrontendRecovery(null);
|
|
132
127
|
return;
|
|
133
128
|
}
|
|
134
129
|
setRecoveryNodesLoading(true);
|
|
@@ -172,13 +167,11 @@ export function useRecoveryConsole(params) {
|
|
|
172
167
|
n.failureCategory &&
|
|
173
168
|
n.failureCategory !== "success")?.failureCategory;
|
|
174
169
|
setRecoveryFailureCategory(runFailure ?? nodeFailure ?? null);
|
|
175
|
-
setFrontendRecovery(body.frontendRecovery ?? null);
|
|
176
170
|
}
|
|
177
171
|
catch {
|
|
178
172
|
setRecoveryNodes([]);
|
|
179
173
|
setRecoveryRunStatus(null);
|
|
180
174
|
setRecoveryFailureCategory(null);
|
|
181
|
-
setFrontendRecovery(null);
|
|
182
175
|
}
|
|
183
176
|
finally {
|
|
184
177
|
setRecoveryNodesLoading(false);
|
|
@@ -211,37 +204,6 @@ export function useRecoveryConsole(params) {
|
|
|
211
204
|
return;
|
|
212
205
|
void loadRecoveryNodes(dagRunId);
|
|
213
206
|
}, [nav, dagRunId, loadRecoveryNodes]);
|
|
214
|
-
useEffect(() => {
|
|
215
|
-
if (nav !== "recovery")
|
|
216
|
-
return;
|
|
217
|
-
const runId = dagRunId.trim();
|
|
218
|
-
if (!runId) {
|
|
219
|
-
setInterruptEligibility(null);
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
let cancelled = false;
|
|
223
|
-
const load = async () => {
|
|
224
|
-
const { body } = await postOperator("dagInterruptEligibility", { runId });
|
|
225
|
-
if (cancelled)
|
|
226
|
-
return;
|
|
227
|
-
const result = (body.result ?? body);
|
|
228
|
-
setInterruptEligibility({
|
|
229
|
-
eligible: result.eligible === true,
|
|
230
|
-
ownerKind: result.ownerKind,
|
|
231
|
-
message: result.message,
|
|
232
|
-
interruptStatus: result.interruptStatus,
|
|
233
|
-
reasonCodes: result.reasonCodes,
|
|
234
|
-
targetOperationId: result.targetOperationId,
|
|
235
|
-
targetOperationState: result.targetOperationState,
|
|
236
|
-
});
|
|
237
|
-
};
|
|
238
|
-
void load();
|
|
239
|
-
const timer = window.setInterval(() => void load(), 4000);
|
|
240
|
-
return () => {
|
|
241
|
-
cancelled = true;
|
|
242
|
-
window.clearInterval(timer);
|
|
243
|
-
};
|
|
244
|
-
}, [nav, dagRunId]);
|
|
245
207
|
useEffect(() => {
|
|
246
208
|
if (nav !== "recovery")
|
|
247
209
|
return;
|
|
@@ -267,14 +229,7 @@ export function useRecoveryConsole(params) {
|
|
|
267
229
|
dagStatus: recoveryRunStatus,
|
|
268
230
|
failureCategory: recoveryFailureCategory,
|
|
269
231
|
});
|
|
270
|
-
const recoveryCtas = useMemo(() =>
|
|
271
|
-
const ctas = consoleRecoveryCtas(recoveryFact);
|
|
272
|
-
if (recoveryFact !== "running-active")
|
|
273
|
-
return ctas;
|
|
274
|
-
if (interruptEligibility?.eligible)
|
|
275
|
-
return ctas;
|
|
276
|
-
return ctas.filter((cta) => cta.id !== "interrupt");
|
|
277
|
-
}, [recoveryFact, interruptEligibility?.eligible]);
|
|
232
|
+
const recoveryCtas = useMemo(() => consoleRecoveryCtas(recoveryFact), [recoveryFact]);
|
|
278
233
|
const recoveryLanes = useMemo(() => partitionRecoveryCtas(recoveryCtas), [recoveryCtas]);
|
|
279
234
|
const recommendedCtaId = useMemo(() => recommendedRecoveryCtaId(recoveryFact), [recoveryFact]);
|
|
280
235
|
const selectedRecoveryNode = useMemo(() => recoveryNodes.find((n) => n.nodeId === fromNodeId.trim()), [recoveryNodes, fromNodeId]);
|
|
@@ -340,7 +295,6 @@ export function useRecoveryConsole(params) {
|
|
|
340
295
|
recoveryReasonTouched,
|
|
341
296
|
recoveryConfirm,
|
|
342
297
|
recoveryPlanSummary,
|
|
343
|
-
interruptReasonCode,
|
|
344
298
|
setRecoveryConfirm,
|
|
345
299
|
setRecoveryPlanSummary,
|
|
346
300
|
setRecoveryReport,
|
|
@@ -349,25 +303,6 @@ export function useRecoveryConsole(params) {
|
|
|
349
303
|
buildCurrentRecoveryReason,
|
|
350
304
|
openFullCanvas,
|
|
351
305
|
});
|
|
352
|
-
useEffect(() => {
|
|
353
|
-
if (nav !== "recovery" || !interruptIntent)
|
|
354
|
-
return;
|
|
355
|
-
if (!interruptEligibility?.eligible)
|
|
356
|
-
return;
|
|
357
|
-
const interruptCta = recoveryCtas.find((cta) => cta.id === "interrupt");
|
|
358
|
-
if (!interruptCta)
|
|
359
|
-
return;
|
|
360
|
-
setRecoveryConfirm(interruptCta);
|
|
361
|
-
setRecoveryReason(buildCurrentRecoveryReason(interruptCta.label));
|
|
362
|
-
setRecoveryReasonTouched(false);
|
|
363
|
-
setInterruptIntent(false);
|
|
364
|
-
}, [
|
|
365
|
-
nav,
|
|
366
|
-
interruptIntent,
|
|
367
|
-
interruptEligibility?.eligible,
|
|
368
|
-
recoveryCtas,
|
|
369
|
-
buildCurrentRecoveryReason,
|
|
370
|
-
]);
|
|
371
306
|
return {
|
|
372
307
|
dagRunId,
|
|
373
308
|
setDagRunId,
|
|
@@ -388,8 +323,6 @@ export function useRecoveryConsole(params) {
|
|
|
388
323
|
recoveryRunsLoading,
|
|
389
324
|
recoveryNodesLoading,
|
|
390
325
|
recoveryRunStatus,
|
|
391
|
-
recoveryFailureCategory,
|
|
392
|
-
frontendRecovery,
|
|
393
326
|
manualRunId,
|
|
394
327
|
setManualRunId,
|
|
395
328
|
manualNodeId,
|
|
@@ -412,11 +345,6 @@ export function useRecoveryConsole(params) {
|
|
|
412
345
|
recoveryCtas,
|
|
413
346
|
recoveryLanes,
|
|
414
347
|
recommendedCtaId,
|
|
415
|
-
interruptIntent,
|
|
416
|
-
setInterruptIntent,
|
|
417
|
-
interruptReasonCode,
|
|
418
|
-
setInterruptReasonCode,
|
|
419
|
-
interruptEligibility,
|
|
420
348
|
recoveryConfirmRef,
|
|
421
349
|
buildCurrentRecoveryReason,
|
|
422
350
|
handleRecoveryCta,
|