@tea-agent/loop-agent 0.39.2 → 0.40.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.
Files changed (215) hide show
  1. package/CHANGELOG.md +133 -92
  2. package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
  3. package/dist/adapters/context-transfer/pi-session.js +61 -0
  4. package/dist/build-stamp.json +3 -3
  5. package/dist/cli/command-definitions.js +12 -0
  6. package/dist/cli/program.js +23 -1
  7. package/dist/commands/dag-artifact.js +284 -0
  8. package/dist/commands/dag-context.js +184 -0
  9. package/dist/commands/dag-rerun.js +206 -1
  10. package/dist/executors/dag-pi-executor.js +108 -19
  11. package/dist/executors/pi-executor.js +4 -2
  12. package/dist/executors/pi-sdk-executor.js +49 -1
  13. package/dist/executors/pi-writer-tool-policy.js +57 -1
  14. package/dist/executors/shell-executor.js +42 -2
  15. package/dist/executors/workspace-write-snapshot.js +68 -0
  16. package/dist/{worker → infrastructure}/console/app-data.js +4 -0
  17. package/dist/infrastructure/console/artifact-revision-store.js +430 -0
  18. package/dist/infrastructure/console/context-export-store.js +160 -0
  19. package/dist/infrastructure/console/dir-lock.js +132 -0
  20. package/dist/infrastructure/harness/artifact-store.js +10 -1
  21. package/dist/infrastructure/harness/atomic-write.js +35 -2
  22. package/dist/shared/context-transfer/artifact-revision.js +172 -0
  23. package/dist/shared/context-transfer.js +418 -0
  24. package/dist/shared/operator/capabilities.js +14 -0
  25. package/dist/shared/operator/safe-run-summary.js +1 -0
  26. package/dist/shared/path-safety.js +93 -0
  27. package/dist/shared/preview.js +28 -4
  28. package/dist/task/config-types.js +10 -0
  29. package/dist/worker/console/chat/chat-event-store.js +77 -7
  30. package/dist/worker/console/chat/context-panel.js +7 -0
  31. package/dist/worker/console/chat/deferred-turn.js +12 -0
  32. package/dist/worker/console/chat/pi-runtime.js +331 -18
  33. package/dist/worker/console/chat/provider-error.js +98 -0
  34. package/dist/worker/console/chat/resource-preferences-store.js +1 -1
  35. package/dist/worker/console/chat/routes.js +389 -56
  36. package/dist/worker/console/chat/session-stats.js +179 -0
  37. package/dist/worker/console/chat/session-store.js +94 -64
  38. package/dist/worker/console/chat/todos.js +115 -0
  39. package/dist/worker/console/chat/tool-preview.js +42 -0
  40. package/dist/worker/console/chat/turn-process.js +20 -55
  41. package/dist/worker/console/chat/user-questions.js +266 -0
  42. package/dist/worker/console/chat/workspace-landing.js +79 -0
  43. package/dist/worker/console/console-update-runtime.js +1 -1
  44. package/dist/worker/console/context-transfer-diagnostics.js +198 -0
  45. package/dist/worker/console/dag-confirmation.js +1 -1
  46. package/dist/worker/console/dag-execution-receipt.js +1 -1
  47. package/dist/worker/console/doctor.js +1 -1
  48. package/dist/worker/console/draft-store.js +1 -1
  49. package/dist/worker/console/human-gate-token.js +1 -1
  50. package/dist/worker/console/index.js +3 -3
  51. package/dist/worker/console/interview/assessment.js +1 -1
  52. package/dist/worker/console/interview/session.js +1 -1
  53. package/dist/worker/console/native-directory-picker.js +13 -0
  54. package/dist/worker/console/operation-runner.js +45 -4
  55. package/dist/worker/console/operation-sse.js +1 -1
  56. package/dist/worker/console/operation-wait.js +1 -1
  57. package/dist/worker/console/operator-actions.js +104 -3
  58. package/dist/worker/console/operator-surface-health.js +1 -1
  59. package/dist/worker/console/operator-user-error.js +128 -0
  60. package/dist/worker/console/routes.js +927 -8
  61. package/dist/worker/console/security.js +39 -4
  62. package/dist/worker/console/server.js +532 -187
  63. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CTx1TrNa.js → abnfDiagram-N423BO3Z-CpWvwARc.js} +1 -1
  64. package/dist/worker/console/static/assets/{arc-B4i9cVxX.js → arc-DctXgO-g.js} +1 -1
  65. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BAXE8_Rl.js → architectureDiagram-T3A2C74G-D4mIkoQl.js} +1 -1
  66. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-C5Xh59at.js → blockDiagram-VBNYF7ZC-ClG0--KO.js} +1 -1
  67. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B_asOzAu.js → c4Diagram-5PPSVZJV-CwdLk78T.js} +1 -1
  68. package/dist/worker/console/static/assets/channel-C9VQZ-ru.js +1 -0
  69. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-wRO_iRNc.js → chunk-2GRJ4B5K-DKczcu-O.js} +1 -1
  70. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-ByOaSh_G.js → chunk-2Q5K7J3B-BV6F-vBI.js} +1 -1
  71. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLzudan.js → chunk-5RXB4S5H-DtojVnvA.js} +1 -1
  72. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-JCNGkXYT.js → chunk-5VM5RSS4-BjDQRGnO.js} +1 -1
  73. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BhrPXXMZ.js → chunk-6Q2QTUOP-I0fV6ngU.js} +1 -1
  74. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-TJ5JuEBT.js → chunk-GF5L2VYU-BM8C-mmC.js} +1 -1
  75. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-VVthn_mD.js → chunk-JWPE2WC7-BEK-a15e.js} +1 -1
  76. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-D60-Mny4.js → chunk-KBJHAD2P-CQsg_fSR.js} +1 -1
  77. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-zXv7aVye.js → chunk-RYQCIY6F-B-BcaUm3.js} +1 -1
  78. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-By9VQoi1.js → chunk-XXDRQBXY-D1Bu08fg.js} +1 -1
  79. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BsCkw5MF.js +1 -0
  80. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BsCkw5MF.js +1 -0
  81. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-C4zQLe-M.js → cose-bilkent-JH36ORCC-q8nwtxBR.js} +1 -1
  82. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-wh5N2ReN.js → cynefin-VYW2F7L2-CruhpURw.js} +1 -1
  83. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Dlu5wIqs.js → cynefinDiagram-MW4NZA55-CJne6iYF.js} +1 -1
  84. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CrDgthc6.js → dagre-VZM6K2ZE-CbeLvBU5.js} +1 -1
  85. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-zN1clg27.js → diagram-7IWD3JNH-DmCxH1Pe.js} +1 -1
  86. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BN-o7J7-.js → diagram-B4RE2ZJO-DJ5OYhtC.js} +1 -1
  87. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C8SuPt0d.js → diagram-LBJQPF4R-B-UN-hln.js} +1 -1
  88. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BoizuHbZ.js → diagram-Q27KOJAE-CcEro8Ey.js} +1 -1
  89. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BzUzXixG.js → diagram-UB23O5K3-BBBzDden.js} +1 -1
  90. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Ev3lA4Cf.js → ebnfDiagram-BXEA7PRR-xKEyH-oo.js} +1 -1
  91. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-GALUzRbs.js → erDiagram-JOGREHBK-C7xl63VC.js} +1 -1
  92. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CZJN65Sb.js → flowDiagram-UKHOOZJN-nthQQ9nR.js} +1 -1
  93. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-JLB9OESl.js → ganttDiagram-PKOTCBZU-CWN5mE33.js} +1 -1
  94. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CcvCr4GD.js → gitGraphDiagram-DS77QQ5N-Wn86tQ6N.js} +1 -1
  95. package/dist/worker/console/static/assets/index-D-0NVyMk.css +1 -0
  96. package/dist/worker/console/static/assets/index-gwyOxQiS.js +407 -0
  97. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-HG5z7aVg.js → infoDiagram-6WML65LV-_WQymGtW.js} +1 -1
  98. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BHEu9chR.js → ishikawaDiagram-WSZJBQD7-COBeivBm.js} +1 -1
  99. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Cp_Up8-a.js → journeyDiagram-NVQOT4AX-CwGOJl3Q.js} +1 -1
  100. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DvVeY-em.js → kanban-definition-27J2QSJJ-Ci0CJ5Vi.js} +1 -1
  101. package/dist/worker/console/static/assets/{linear-aGmcjgTn.js → linear-CPjMq6vN.js} +1 -1
  102. package/dist/worker/console/static/assets/{mermaid.core-Biyo-tqA.js → mermaid.core-Z0wGoe0b.js} +5 -5
  103. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DyxY2pIb.js → mindmap-definition-FAOFIHXS-dISked0d.js} +1 -1
  104. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CkdGuc50.js → pegDiagram-VL7TDLO6-BJxgof7Y.js} +1 -1
  105. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-NNQI9xVR.js → pieDiagram-7S7Q4E2Y-CIblU8eW.js} +1 -1
  106. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-PAJkuz_G.js → quadrantDiagram-CIZ2JOQS-vwYiqh8E.js} +1 -1
  107. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-ZwrQod0O.js → railroadDiagram-AXF67PYL-_iOsVeFm.js} +1 -1
  108. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D3ZfrzM2.js → requirementDiagram-LRYGKXZP-Dk0MLxO_.js} +1 -1
  109. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DDGFmWk5.js → sankeyDiagram-W5VNT64P-Dx7HtLVW.js} +1 -1
  110. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DO6mmXTA.js → sequenceDiagram-SI44F4Z6-DRuWjlpL.js} +1 -1
  111. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DMbCQiJt.js → sizeCapture-X5ZJPWSS-Bhy9DQAA.js} +1 -1
  112. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Di_YUEfC.js → stateDiagram-OKZ733FA-DAx9twnU.js} +1 -1
  113. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Dmdf8cGy.js +1 -0
  114. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-Bn2PphNJ.js → swimlanes-SLNWSIFB-okMlvVrM.js} +2 -2
  115. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-W1IcAFff.js +8 -0
  116. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DPh8pRsp.js → timeline-definition-Z64GVDOM-DXqCKe37.js} +1 -1
  117. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-GMfl26pW.js → vennDiagram-T6HMQDX7-CeIUkwBh.js} +1 -1
  118. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DTlmVrmF.js → wardleyDiagram-T6FBY63Y-BP76BKTN.js} +1 -1
  119. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-YGBjKAS5.js → xychartDiagram-ELKLHX3M-BpVI0OpF.js} +1 -1
  120. package/dist/worker/console/static/index.html +7 -2
  121. package/dist/worker/console/static-src/app/console-types.js +29 -4
  122. package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
  123. package/dist/worker/console/static-src/app/useOperatorActions.js +36 -6
  124. package/dist/worker/console/static-src/app/useRecoveryConsole.js +10 -11
  125. package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
  126. package/dist/worker/console/static-src/app/useTaskWizard.js +2 -2
  127. package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
  128. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +141 -8
  129. package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
  130. package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
  131. package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
  132. package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
  133. package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
  134. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
  135. package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
  136. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +181 -87
  137. package/dist/worker/console/static-src/operator-chat/useChatStream.js +159 -44
  138. package/dist/worker/console/static-src/operator-chat/useChatThread.js +177 -8
  139. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
  140. package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
  141. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
  142. package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
  143. package/dist/worker/console/static-src/shell/workspace-route.js +339 -0
  144. package/dist/worker/console/workspace-context.js +260 -0
  145. package/dist/worker/console/workspace-registry.js +214 -0
  146. package/dist/worker/continuation/worker-continuation.js +278 -0
  147. package/dist/worker/observe/health.js +1 -1
  148. package/dist/worker/observe/node-transparency.js +572 -0
  149. package/dist/worker/observe/routes.js +51 -1
  150. package/dist/worker/observe/server.js +4 -0
  151. package/dist/worker/observe/static/api.js +94 -10
  152. package/dist/worker/observe/static/app.js +18 -70
  153. package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
  154. package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
  155. package/dist/worker/observe/static/index.html +1 -1
  156. package/dist/worker/observe/static/inspect-workspace.js +307 -0
  157. package/dist/worker/observe/static/operator-chrome.css +145 -20
  158. package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
  159. package/dist/worker/observe/static/operator-chrome.js +330 -100
  160. package/dist/worker/observe/static/router.d.ts +46 -0
  161. package/dist/worker/observe/static/router.js +25 -1
  162. package/dist/worker/observe/static/state.d.ts +50 -0
  163. package/dist/worker/observe/static/state.js +175 -1
  164. package/dist/worker/observe/static/styles.css +1039 -128
  165. package/dist/worker/observe/static/views/dag-inspector.js +1218 -60
  166. package/dist/worker/observe/static/views/dag.js +2 -1
  167. package/dist/worker/observe/static/views/dashboard.js +6 -4
  168. package/dist/worker/observe/static/views/night.js +2 -2
  169. package/dist/worker/observe/static/views/pool.js +1 -0
  170. package/dist/worker/observe/static/views/run.js +3 -1
  171. package/dist/worker/observe/static/views/session-timeline.js +75 -10
  172. package/dist/worker/observe/static/views/task.js +1 -1
  173. package/dist/worker/pool/attempt-lease.js +97 -66
  174. package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
  175. package/dist/worker/pool/reconcile.js +46 -1
  176. package/dist/worker/pool/run-store.js +2 -0
  177. package/dist/worker/pool/state-projection.js +2 -0
  178. package/dist/workflows/dag/artifact-bindings.js +149 -0
  179. package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
  180. package/dist/workflows/dag/backend-test-pytest-collection.js +11 -10
  181. package/dist/workflows/dag/backend-test-writer-completeness.js +7 -12
  182. package/dist/workflows/dag/context-receipt.js +305 -0
  183. package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
  184. package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
  185. package/dist/workflows/dag/context-transfer/renderers.js +93 -0
  186. package/dist/workflows/dag/dynamic-runtime/map.js +1 -0
  187. package/dist/workflows/dag/init-hybrid.js +178 -47
  188. package/dist/workflows/dag/interrupt-request.js +3 -3
  189. package/dist/workflows/dag/lifecycle.js +3 -3
  190. package/dist/workflows/dag/node-execution.js +112 -27
  191. package/dist/workflows/dag/path-safety.js +1 -0
  192. package/dist/workflows/dag/prompt.js +29 -4
  193. package/dist/workflows/dag/rerun-plan.js +272 -0
  194. package/dist/workflows/dag/rerun-run.js +390 -12
  195. package/dist/workflows/dag/skill-snapshot.js +1 -0
  196. package/dist/workflows/dag/types.js +203 -8
  197. package/docs/README.md +1 -0
  198. package/docs/architecture/runtime-boundaries.md +6 -6
  199. package/docs/operations/local-development-environment.md +21 -0
  200. package/docs/templates/agent-dag.schema.json +50 -0
  201. package/docs/templates/backend-test-dag.json +265 -237
  202. package/harness.json +3 -3
  203. package/package.json +5 -1
  204. package/skills/loop-agent/references/command-reference.md +6 -0
  205. package/dist/worker/console/static/assets/channel-Dj_4Moei.js +0 -1
  206. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C0YYAyCa.js +0 -1
  207. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C0YYAyCa.js +0 -1
  208. package/dist/worker/console/static/assets/index-CW88Fjbw.js +0 -406
  209. package/dist/worker/console/static/assets/index-DP0ZJl39.css +0 -1
  210. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DrdDvela.js +0 -1
  211. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DPkEAULl.js +0 -8
  212. package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
  213. package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
  214. /package/dist/{worker → infrastructure}/console/operation-store.js +0 -0
  215. /package/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
@@ -1,8 +1,12 @@
1
1
  /** Fetch and artifact helpers (Observe UI R5). */
2
+ import {
3
+ fetchWithWorkspaceScope,
4
+ workspaceScope,
5
+ } from "./state.js";
2
6
 
3
7
  export async function fetchJson(url) {
4
8
  try {
5
- const res = await fetch(url);
9
+ const res = await fetchWithWorkspaceScope(url);
6
10
  if (!res.ok) return null;
7
11
  return await res.json();
8
12
  } catch {
@@ -18,7 +22,10 @@ export async function fetchJson(url) {
18
22
  export async function fetchJsonResult(url, options = {}) {
19
23
  const signal = options?.signal;
20
24
  try {
21
- const res = await fetch(url, signal ? { signal } : undefined);
25
+ const res = await fetchWithWorkspaceScope(
26
+ url,
27
+ signal ? { signal } : undefined,
28
+ );
22
29
  let body = null;
23
30
  try {
24
31
  body = await res.json();
@@ -77,6 +84,29 @@ export async function fetchDagNodeInput(runId, nodeId) {
77
84
  return fetchJsonResult(url);
78
85
  }
79
86
 
87
+ export async function fetchDagNodeContext(runId, nodeId, attempt) {
88
+ const params = new URLSearchParams();
89
+ if (attempt != null) params.set("attempt", String(attempt));
90
+ const query = params.toString();
91
+ const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/context${query ? `?${query}` : ""}`;
92
+ return fetchJsonResult(url);
93
+ }
94
+
95
+ export async function fetchDagNodeArtifacts(runId, nodeId) {
96
+ const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/artifacts`;
97
+ return fetchJsonResult(url);
98
+ }
99
+
100
+ export async function fetchDagNodeArtifactPreview(runId, nodeId, artifactId) {
101
+ const params = new URLSearchParams({ artifactId: String(artifactId ?? "") });
102
+ const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/artifacts/preview?${params.toString()}`;
103
+ return fetchJsonResult(url);
104
+ }
105
+
106
+ export async function fetchDagRunLineage(runId) {
107
+ return fetchJsonResult(`/api/dag-runs/${encodeURIComponent(runId)}/lineage`);
108
+ }
109
+
80
110
  export async function fetchDagNodeProcess(runId, nodeId, key) {
81
111
  const params = new URLSearchParams();
82
112
  if (key) params.set("key", String(key));
@@ -92,7 +122,7 @@ export async function fetchDagNodeProcess(runId, nodeId, key) {
92
122
  */
93
123
  export async function fetchSpecEvidenceFile(runId, nodeId, source, relPath) {
94
124
  const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/spec-evidence/file?source=${encodeURIComponent(source)}&path=${encodeURIComponent(relPath)}`;
95
- const res = await fetch(url);
125
+ const res = await fetchWithWorkspaceScope(url);
96
126
  let body = null;
97
127
  try {
98
128
  body = await res.json();
@@ -116,29 +146,57 @@ export function artifactUrl(artifactPath) {
116
146
  * Experimental (prompt-override rerun only): POST one allowlisted operator
117
147
  * action through the Console mutation gate using the SCOPED inspect token
118
148
  * (window.__INSPECT_MUTATION_TOKEN__). The server injects it into /inspect
119
- * HTML by default; HARNESS_DAG_RERUN_PROMPT_OVERRIDE=0|false|off disables
120
- * injection. The token only authorizes dagRerunPlan / dagRerun — never general
149
+ * HTML and into the Console SPA (which hosts the /inspect workspace) by
150
+ * default; HARNESS_DAG_RERUN_PROMPT_OVERRIDE=0|false|off disables injection.
151
+ * The token only authorizes dagRerunPlan / dagRerun — never general
121
152
  * Console mutations.
122
153
  * Absent token → the call is not attempted.
123
154
  */
124
- export async function postOperatorAction(action, actionParams = {}) {
155
+ export async function postOperatorAction(
156
+ action,
157
+ actionParams = {},
158
+ clientRequestId,
159
+ ) {
125
160
  const token = globalThis.__INSPECT_MUTATION_TOKEN__;
126
161
  if (!token) {
127
162
  return {
128
163
  ok: false,
129
164
  status: 0,
130
- body: { error: { code: "PROMPT_OVERRIDE_DISABLED", message: "提示词重启未启用(服务端未注入确认 token)" } },
165
+ body: {
166
+ error: {
167
+ code: "PROMPT_OVERRIDE_DISABLED",
168
+ message: "提示词重启未启用(服务端未注入确认 token)",
169
+ },
170
+ },
171
+ };
172
+ }
173
+ const workspaceId = workspaceScope();
174
+ if (!workspaceId) {
175
+ return {
176
+ ok: false,
177
+ status: 400,
178
+ body: {
179
+ error: {
180
+ code: "WORKSPACE_REQUIRED",
181
+ message: "workspaceId is required",
182
+ },
183
+ },
131
184
  };
132
185
  }
133
186
  try {
134
- const res = await fetch("/api/operator/v1/operations", {
187
+ const res = await fetchWithWorkspaceScope("/api/operator/v1/operations", {
135
188
  method: "POST",
136
189
  credentials: "same-origin",
137
190
  headers: {
138
191
  "Content-Type": "application/json",
139
192
  "x-loop-console-confirmation": token,
140
193
  },
141
- body: JSON.stringify({ action, actionParams }),
194
+ body: JSON.stringify({
195
+ workspaceId,
196
+ action,
197
+ actionParams,
198
+ clientRequestId,
199
+ }),
142
200
  });
143
201
  let body = null;
144
202
  try {
@@ -152,10 +210,36 @@ export async function postOperatorAction(action, actionParams = {}) {
152
210
  }
153
211
  }
154
212
 
213
+ export async function downloadContextExport(downloadUrl) {
214
+ const token = globalThis.__INSPECT_MUTATION_TOKEN__;
215
+ if (!token) throw new Error("导出下载能力未启用");
216
+ const res = await fetchWithWorkspaceScope(downloadUrl, {
217
+ method: "GET",
218
+ credentials: "same-origin",
219
+ headers: { "x-loop-console-confirmation": token },
220
+ });
221
+ if (!res.ok) {
222
+ let message = `下载失败:HTTP ${res.status}`;
223
+ try {
224
+ const body = await res.json();
225
+ message = body?.error?.message ?? message;
226
+ } catch {
227
+ // Preserve bounded local fallback copy.
228
+ }
229
+ throw new Error(message);
230
+ }
231
+ return {
232
+ blob: await res.blob(),
233
+ filename:
234
+ /filename="([^"]+)"/.exec(res.headers.get("content-disposition") ?? "")?.[1] ??
235
+ "context-bundle.zip",
236
+ };
237
+ }
238
+
155
239
  /** Poll a Console operation snapshot (read-only GET). */
156
240
  export async function fetchOperatorOperation(operationId) {
157
241
  try {
158
- const res = await fetch(
242
+ const res = await fetchWithWorkspaceScope(
159
243
  `/api/operator/v1/operations/${encodeURIComponent(operationId)}`,
160
244
  { credentials: "same-origin" },
161
245
  );
@@ -1,9 +1,8 @@
1
- /** Observe UI bootstrap: route wiring, listeners, compatibility re-exports. */
1
+ /** Observe UI bootstrap: standalone compatibility entry + re-exports. */
2
2
  import {
3
3
  parseHashRoute,
4
4
  parseHashRouteWithFilters,
5
5
  buildHashPath,
6
- parseRoute,
7
6
  } from "./router.js";
8
7
  import { parseArtifactPreviewResponse } from "./api.js";
9
8
  import {
@@ -15,7 +14,6 @@ import {
15
14
  } from "./relations.js";
16
15
  import { copyText, renderRecommendedCommand } from "./copy.js";
17
16
  import {
18
- isPageVisible,
19
17
  detailPollDelay,
20
18
  updateDagGraphViewportState,
21
19
  captureDagGraphViewportState,
@@ -25,11 +23,9 @@ import {
25
23
  shouldReuseDagDetailShell,
26
24
  shouldPreserveDiagnosticsOpen,
27
25
  isInteractiveGestureActive,
28
- stopTimers,
29
26
  renderViewState,
30
27
  mountViewState,
31
28
  viewStateDescriptor,
32
- uiState,
33
29
  } from "./state.js";
34
30
  import { sortPoolTasks, poolStatusCounts } from "./format-pool.js";
35
31
  import {
@@ -45,34 +41,22 @@ import {
45
41
  dashboardVisibleFeatures,
46
42
  findDagForRun,
47
43
  } from "./dag-model.js";
48
-
49
- import { renderFailures } from "./views/failures.js";
50
- import { startPoolView } from "./views/pool.js";
51
- import { startDashboardPolling } from "./views/dashboard.js";
52
- import { startDagsView } from "./views/dags.js";
53
- import { renderFeatureDetail } from "./views/feature.js";
54
- import { renderBatch } from "./views/batch.js";
55
- import { startTaskPolling } from "./views/task.js";
56
- import { startRunPolling } from "./views/run.js";
57
- import { startDagPolling } from "./views/dag.js";
58
44
  import { renderDagGraph } from "./views/dag-graph.js";
59
- import { renderNightJobs } from "./views/night.js";
60
45
  import {
61
46
  selectDagNode,
62
47
  closeDagInspector,
63
- closeDagInspectorOnOutsideClick,
64
48
  renderDagInspector,
65
49
  } from "./views/dag-inspector.js";
66
50
  import {
67
51
  mergeSessionEvents,
68
52
  renderSessionTimeline,
69
53
  } from "./views/session-timeline.js";
70
- import { mountOperatorChrome } from "./operator-chrome.js";
54
+ import {
55
+ route,
56
+ startStandaloneInspect,
57
+ tryCanonicalizeStandaloneInspect,
58
+ } from "./inspect-workspace.js";
71
59
 
72
- // Compatibility re-exports for poll-stable UI helpers (owned by state.js / views):
73
- // reuse-dag-detail-shell, reuse-dag-graph-wrap, existingGraphWrap?.parentNode === ranksEl,
74
- // existingDetails?.parentNode === metaEl, let pre = existingPre, computeFollowLatest,
75
- // updateDagOutputViewportState, isInteractiveGestureActive.
76
60
  export {
77
61
  detailPollDelay,
78
62
  parseMarkdownBlocks,
@@ -114,56 +98,20 @@ export {
114
98
  renderDagInspector,
115
99
  renderSessionTimeline,
116
100
  mergeSessionEvents,
101
+ route,
102
+ tryCanonicalizeStandaloneInspect,
117
103
  };
118
104
 
119
- function route() {
120
- stopTimers();
121
- const r = parseRoute();
122
- if (r.view === "dashboard") {
123
- startDashboardPolling(r.scrollTo);
124
- } else if (r.view === "dags") {
125
- void startDagsView();
126
- } else if (r.view === "batch") {
127
- void renderBatch(r.batchRunId);
128
- } else if (r.view === "run") {
129
- startRunPolling(r.workerRunId);
130
- } else if (r.view === "dag") {
131
- startDagPolling(r.dagRunId);
132
- } else if (r.view === "failures") {
133
- void renderFailures();
134
- } else if (r.view === "pool") {
135
- startPoolView();
136
- } else if (r.view === "night") {
137
- void renderNightJobs(r.scheduleId);
138
- } else if (r.view === "task") {
139
- startTaskPolling(r.featureId, r.taskId);
140
- } else if (r.view === "feature") {
141
- void renderFeatureDetail(r.featureId);
142
- }
143
- }
144
-
145
105
  if (typeof window !== "undefined") {
146
- // 先同步挂载共享壳,再启动路由;首个 snapshot 的新鲜度不会因异步挂载丢失。
147
- const chromeHost = document.getElementById("operator-chrome");
148
- if (chromeHost) {
149
- mountOperatorChrome(chromeHost, {
150
- mode: "inspect",
151
- liveLocation: true,
152
- healthUrl: "/api/health",
153
- readinessTitle: "Pi 状态(只读展示)。模型与认证管理在操作侧,点击进入。",
154
- });
106
+ // Compatibility listeners remain owned by inspect-workspace.js:
107
+ // window.addEventListener("hashchange", route)
108
+ // window.addEventListener("load", route)
109
+ // document.addEventListener("pointerdown", closeDagInspectorOnOutsideClick)
110
+ // document.addEventListener("visibilitychange", ...)
111
+ // reuse-dag-detail-shell, reuse-dag-graph-wrap, existingGraphWrap?.parentNode === ranksEl,
112
+ // existingDetails?.parentNode === metaEl, let pre = existingPre, computeFollowLatest,
113
+ // updateDagOutputViewportState, isInteractiveGestureActive.
114
+ if (!tryCanonicalizeStandaloneInspect(window.location)) {
115
+ startStandaloneInspect();
155
116
  }
156
- window.addEventListener("hashchange", route);
157
- window.addEventListener("load", route);
158
- document.addEventListener("pointerdown", closeDagInspectorOnOutsideClick);
159
- document.addEventListener("visibilitychange", () => {
160
- if (!isPageVisible()) return;
161
- const r = parseRoute();
162
- if (r.view === "dashboard") startDashboardPolling();
163
- // History page is manual-refresh only (no 5s dashboard polling).
164
- if (r.view === "run") startRunPolling(r.workerRunId, false);
165
- if (r.view === "dag") startDagPolling(r.dagRunId, false);
166
- if (r.view === "pool" && uiState.poolAutoRefresh) startPoolView();
167
- if (r.view === "task") startTaskPolling(r.featureId, r.taskId);
168
- });
169
117
  }
@@ -0,0 +1,9 @@
1
+ export function contextTransferReasonLabel(
2
+ reasonCode: string | null | undefined,
3
+ ): string | null;
4
+ export function formatContextTransferReasonList(
5
+ reasonCodes: readonly (string | null | undefined)[] | null | undefined,
6
+ ): string | null;
7
+ export function describeTransferError(
8
+ message: string | null | undefined,
9
+ ): string | null;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Context transfer / artifact revision 稳定 reason code 的操作者文案映射
3
+ * (Observe UI,exec-plan 2026-08-25-console-node-context-artifact-rerun W1.5)。
4
+ *
5
+ * 表驱动纯函数:已知 code 映射为中文业务术语,未知 code fail-closed 返回
6
+ * null(调用方保留原始 token 展示,不猜测、不解释为成功)。
7
+ * 冻结 code 清单见 src/shared/context-transfer.ts CONTEXT_TRANSFER_REASON_CODES;
8
+ * 附加条目为 Console operation / rerun 执行面会透传到 Inspector 的错误码。
9
+ */
10
+
11
+ const CONTEXT_TRANSFER_REASON_LABELS = {
12
+ CONTEXT_RECEIPT_MISSING: "该节点没有执行时上下文回执",
13
+ CONTEXT_COMPONENT_UNAVAILABLE: "部分上下文组件当前不可用",
14
+ CONTEXT_BUNDLE_INEXACT: "导出等级为近似恢复,不是精确重放",
15
+ CONTEXT_BUNDLE_TOO_LARGE: "导出内容超出体积上限",
16
+ RAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED: "原文导出需要显式确认敏感数据风险",
17
+ SECRET_SCAN_CONFIRMATION_REQUIRED: "候选文件疑似包含凭据,需确认后才能继续",
18
+ ARTIFACT_BINDING_UNAVAILABLE: "缺少结构化产物关系",
19
+ ARTIFACT_NOT_REVISION_ELIGIBLE: "该产物不允许修订替换",
20
+ ARTIFACT_IDENTITY_AMBIGUOUS: "产物身份不唯一,无法安全定位",
21
+ ARTIFACT_REVISION_SCHEMA_INVALID: "候选文件不符合声明的数据结构",
22
+ ARTIFACT_REVISION_PATH_INVALID: "候选目标路径无效",
23
+ ARTIFACT_REVISION_EXPIRED: "修订候选已过期,需要重新上传",
24
+ ARTIFACT_REVISION_DRIFT: "候选文件与登记内容不一致",
25
+ ARTIFACT_REVISION_QUOTA_EXCEEDED: "修订暂存区配额已满,请先清理或等待过期回收",
26
+ ARTIFACT_CONSUMER_UNKNOWN: "无法确定受影响的下游节点",
27
+ ARTIFACT_IMPACT_UNSAFE: "影响范围包含不能自动重跑的节点",
28
+ RERUN_PLAN_DRIFT: "继续运行计划与当前事实发生漂移",
29
+ WORKER_MANAGED_CONTINUATION_UNSUPPORTED: "由 Worker 托管的运行暂不支持派生继续",
30
+ WORKER_CONTINUATION_AUTHORITY_MISMATCH: "Worker 派生运行的归属事实不一致",
31
+ WORKER_CONTINUATION_NEEDS_RECONCILE: "Worker 派生运行已存在,需要先恢复核对",
32
+ WORKER_CONTINUATION_LEASE_CONFLICT: "该 Worker Task 已有运行占用",
33
+ INELIGIBLE: "当前不满足继续运行的条件",
34
+ PARENT_IMMUTABILITY_VIOLATION: "父运行事实发生变化,已阻止派生",
35
+ PARENT_LIFECYCLE: "父运行状态不允许派生继续",
36
+ PLAN_DRIFT: "计划与执行前校验不一致",
37
+ REQUEST_ID_REUSE_CONFLICT: "相同请求 ID 已被其他操作占用",
38
+ OPERATION_NEEDS_RECONCILE: "操作记录需要先恢复核对",
39
+ CONTEXT_EXPORT_FAILED: "上下文导出失败",
40
+ CONTEXT_EXPORT_UNAVAILABLE: "导出内容不存在或已过期",
41
+ LEASE_HELD: "资源正被其他操作占用",
42
+ NOT_FOUND: "目标不存在或已过期",
43
+ // Console operation 面会透传的通用错误码。
44
+ INVALID_INPUT: "请求参数不完整或不合法",
45
+ INTERNAL_ERROR: "内部错误,请重试;若持续失败请查看操作诊断",
46
+ OPERATION_NOT_FOUND: "操作不存在或已被清理",
47
+ OPERATION_NOT_TERMINAL: "操作尚未结束,请稍后查询",
48
+ };
49
+
50
+ // 非 reason-code 形态、但会透传到检查器状态行的运行时错误 → 中文语义。
51
+ const RUNTIME_ERROR_PATTERNS = [
52
+ {
53
+ pattern: /controller identity changed|package fingerprint changed/i,
54
+ copy:
55
+ "控制器版本已变更:Console 启动后代码被重新构建。请重启 Console 进程加载当前构建后重试本操作。",
56
+ },
57
+ {
58
+ pattern:
59
+ /invalid (?:confirmation header |boot capability )?token|mutation requires (?:boot capability cookie|confirmation header token)/i,
60
+ copy:
61
+ "页面凭证已失效(Console 可能已重启,或页面是重启前的旧缓存)。请强制刷新页面(Cmd/Ctrl+Shift+R)后重试。",
62
+ },
63
+ {
64
+ pattern: /context receipt missing/i,
65
+ copy: "该节点没有执行时上下文回执,无法生成交接包。",
66
+ },
67
+ ];
68
+
69
+ /**
70
+ * 已知 reason code → 中文业务术语;未知或缺失返回 null(调用方应原样展示
71
+ * 原始 token,保持诚实降级)。
72
+ */
73
+ export function contextTransferReasonLabel(reasonCode) {
74
+ const key = String(reasonCode ?? "");
75
+ if (!key) return null;
76
+ return CONTEXT_TRANSFER_REASON_LABELS[key] ?? null;
77
+ }
78
+
79
+ /**
80
+ * reason code 列表 → 面向操作者的展示串:已知项输出「中文(CODE)」,
81
+ * 未知项原样保留;空输入返回 null 供调用方守卫。
82
+ */
83
+ export function formatContextTransferReasonList(reasonCodes) {
84
+ const codes = (Array.isArray(reasonCodes) ? reasonCodes : [])
85
+ .map((code) => String(code ?? ""))
86
+ .filter((code) => code.length > 0);
87
+ if (codes.length === 0) return null;
88
+ return codes
89
+ .map((code) => {
90
+ const label = contextTransferReasonLabel(code);
91
+ return label ? `${label}(${code})` : code;
92
+ })
93
+ .join(";");
94
+ }
95
+
96
+ const REASON_CODE_SCAN_PATTERN = new RegExp(
97
+ `\\b(?:${Object.keys(CONTEXT_TRANSFER_REASON_LABELS).join("|")})\\b`,
98
+ );
99
+
100
+ /**
101
+ * 任意错误信息 → 面向操作者的语义化文案。扫描消息中嵌入的已知 reason
102
+ * code,命中时以中文业务术语开头并保留原码与原始信息;未命中已知 code
103
+ * 返回 null(调用方原样展示,不猜测成功、不编造解释)。
104
+ */
105
+ export function describeTransferError(message) {
106
+ const raw = String(message ?? "").trim();
107
+ if (!raw) return null;
108
+ for (const entry of RUNTIME_ERROR_PATTERNS) {
109
+ if (entry.pattern.test(raw)) return entry.copy;
110
+ }
111
+ const match = REASON_CODE_SCAN_PATTERN.exec(raw);
112
+ if (!match) return null;
113
+ const label = contextTransferReasonLabel(match[0]);
114
+ if (!label) return null;
115
+ if (raw === match[0]) return `${label}(${match[0]})`;
116
+ const rest = raw.replace(match[0], "").replace(/^[\s::-]+/, "").trim();
117
+ return rest
118
+ ? `${label}(${match[0]});原始信息:${rest}`
119
+ : `${label}(${match[0]})`;
120
+ }
@@ -210,7 +210,7 @@
210
210
  >
211
211
  刷新
212
212
  </button>
213
- <a class="page-action-btn" href="/#/night">在操作台管理 →</a>
213
+ <a class="page-action-btn" href="/#/operate/night">在操作台管理 →</a>
214
214
  </div>
215
215
  </header>
216
216
  <section