@tea-agent/loop-agent 0.40.0-next.1 → 0.40.0-next.11

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 (213) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +114 -109
  3. package/README.md +2 -2
  4. package/dist/application/dag/generate-task-dag.js +6 -2
  5. package/dist/application/task-lifecycle/advance.js +12 -0
  6. package/dist/build-stamp.json +3 -3
  7. package/dist/cli/update/runtime-activity.js +1 -29
  8. package/dist/commands/dag-rerun.js +1 -1
  9. package/dist/executors/dag-pi-executor.js +69 -7
  10. package/dist/executors/pi-executor.js +4 -2
  11. package/dist/executors/pi-sdk-executor.js +46 -1
  12. package/dist/executors/pi-writer-tool-policy.js +57 -1
  13. package/dist/executors/shell-executor.js +107 -20
  14. package/dist/executors/workspace-write-snapshot.js +68 -0
  15. package/dist/governance/checks.js +1 -0
  16. package/dist/infrastructure/harness/atomic-write.js +23 -0
  17. package/dist/shared/dag-prompt-override.js +4 -5
  18. package/dist/shared/update/npm-client.js +33 -11
  19. package/dist/task/config-types.js +10 -0
  20. package/dist/task/contract/apply.js +11 -1
  21. package/dist/task/contract/constants.js +2 -0
  22. package/dist/task/contract/hash.js +3 -0
  23. package/dist/task/contract/observe.js +25 -4
  24. package/dist/task/contract/paths.js +2 -1
  25. package/dist/task/contract/project.js +15 -1
  26. package/dist/task/contract/schema.js +2 -0
  27. package/dist/task/contract/transaction.js +12 -0
  28. package/dist/task/source-prepare/completeness.js +188 -0
  29. package/dist/task/source-prepare/fragment-inventory.js +474 -0
  30. package/dist/task/source-prepare/index.js +3 -0
  31. package/dist/task/source-prepare/ledger-reconciliation.js +127 -0
  32. package/dist/task/source-prepare/ledger-review.js +214 -0
  33. package/dist/task/source-prepare/ledger.js +545 -0
  34. package/dist/task/source-prepare/prepare.js +262 -1
  35. package/dist/task/source-prepare/semantic-intake.js +19 -3
  36. package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
  37. package/dist/task/source-prepare/types.js +22 -0
  38. package/dist/worker/cli.js +12 -26
  39. package/dist/worker/console/chat/chat-event-store.js +75 -5
  40. package/dist/worker/console/chat/context-panel.js +7 -0
  41. package/dist/worker/console/chat/deferred-turn.js +12 -0
  42. package/dist/worker/console/chat/pi-runtime.js +331 -18
  43. package/dist/worker/console/chat/provider-error.js +98 -0
  44. package/dist/worker/console/chat/routes.js +389 -56
  45. package/dist/worker/console/chat/session-stats.js +179 -0
  46. package/dist/worker/console/chat/session-store.js +93 -63
  47. package/dist/worker/console/chat/todos.js +115 -0
  48. package/dist/worker/console/chat/tool-preview.js +42 -0
  49. package/dist/worker/console/chat/turn-process.js +20 -55
  50. package/dist/worker/console/chat/user-questions.js +266 -0
  51. package/dist/worker/console/chat/workspace-landing.js +79 -0
  52. package/dist/worker/console/console-handoff.js +82 -0
  53. package/dist/worker/console/console-update-and-init.js +115 -0
  54. package/dist/worker/console/console-update-runtime.js +84 -0
  55. package/dist/worker/console/dag-execution-receipt.js +20 -2
  56. package/dist/worker/console/draft-store.js +49 -0
  57. package/dist/worker/console/native-directory-picker.js +13 -0
  58. package/dist/worker/console/operation-store.js +1 -1
  59. package/dist/worker/console/operator-actions.js +133 -7
  60. package/dist/worker/console/operator-surface-health.js +1 -0
  61. package/dist/worker/console/prd-intake-bridge.js +13 -0
  62. package/dist/worker/console/routes.js +312 -1
  63. package/dist/worker/console/security.js +4 -4
  64. package/dist/worker/console/server.js +583 -172
  65. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Br92EGb7.js → abnfDiagram-N423BO3Z-Bs-CDAXM.js} +1 -1
  66. package/dist/worker/console/static/assets/{arc-oulImtQq.js → arc-CAkA3We3.js} +1 -1
  67. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-tyHc6aqO.js → architectureDiagram-T3A2C74G-DEmI_zqr.js} +1 -1
  68. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CY86BSpT.js → blockDiagram-VBNYF7ZC-uDHANebE.js} +1 -1
  69. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BKKsDmNs.js → c4Diagram-5PPSVZJV-Bv97b4_B.js} +1 -1
  70. package/dist/worker/console/static/assets/channel-amxUpk7o.js +1 -0
  71. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CXZdjl3B.js → chunk-2GRJ4B5K-shmQKsFz.js} +1 -1
  72. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B-aIFDQ5.js → chunk-2Q5K7J3B-BAraNvcN.js} +1 -1
  73. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BDgAW_B2.js → chunk-5RXB4S5H-BirhxUop.js} +1 -1
  74. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DABa4UPR.js → chunk-5VM5RSS4-C9LgUJpR.js} +1 -1
  75. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-aGbysVOx.js → chunk-6Q2QTUOP-DrU-s-t7.js} +1 -1
  76. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-B8MSZDVs.js → chunk-GF5L2VYU-Tx-H_FA2.js} +1 -1
  77. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CpelV73g.js → chunk-JWPE2WC7-BjLtNFrR.js} +1 -1
  78. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BE04ty3z.js → chunk-KBJHAD2P-UNLVwSsy.js} +1 -1
  79. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BUxTkaaR.js → chunk-RYQCIY6F-CBEUX8XD.js} +1 -1
  80. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CYYBVKfX.js → chunk-XXDRQBXY-WTL7IZOq.js} +1 -1
  81. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +1 -0
  82. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +1 -0
  83. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CEQF_xmQ.js → cose-bilkent-JH36ORCC-CkHG6W3s.js} +1 -1
  84. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CqpxN5IT.js → cynefin-VYW2F7L2-BRzFqTaL.js} +1 -1
  85. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-B3PzanVi.js → cynefinDiagram-MW4NZA55-2_CFp_i7.js} +1 -1
  86. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BSUGCNx1.js → dagre-VZM6K2ZE-BJtsmdkE.js} +1 -1
  87. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CdLevU5T.js → diagram-7IWD3JNH-DNEFFo6w.js} +1 -1
  88. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BjpF_Kok.js → diagram-B4RE2ZJO-B_IWV7eo.js} +1 -1
  89. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C4I6NJny.js → diagram-LBJQPF4R-DvvRx2dz.js} +1 -1
  90. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C8hecCr5.js → diagram-Q27KOJAE-CsibsWLg.js} +1 -1
  91. package/dist/worker/console/static/assets/{diagram-UB23O5K3-Daod6tOS.js → diagram-UB23O5K3-les_djBQ.js} +1 -1
  92. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BvvmazGv.js → ebnfDiagram-BXEA7PRR-BEm2n7qJ.js} +1 -1
  93. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DeN_vfV4.js → erDiagram-JOGREHBK-BI7vHHVm.js} +1 -1
  94. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-D6dq1t9z.js → flowDiagram-UKHOOZJN-CUFCERrB.js} +1 -1
  95. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DziIdNY4.js → ganttDiagram-PKOTCBZU-wxyLiGWt.js} +1 -1
  96. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dy4s5CXr.js → gitGraphDiagram-DS77QQ5N-Bt897K8Z.js} +1 -1
  97. package/dist/worker/console/static/assets/index-BHhUOTri.css +1 -0
  98. package/dist/worker/console/static/assets/index-DqJbO3-p.js +407 -0
  99. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czv5eYx2.js → infoDiagram-6WML65LV-DYNx_IPv.js} +1 -1
  100. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Bsk3nFRT.js → ishikawaDiagram-WSZJBQD7-CzpLNEu6.js} +1 -1
  101. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DxGmNj5K.js → journeyDiagram-NVQOT4AX-97f9owNU.js} +1 -1
  102. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CYCFqkO_.js → kanban-definition-27J2QSJJ-BxM9hyBn.js} +1 -1
  103. package/dist/worker/console/static/assets/{linear-B0YzRwrd.js → linear-ByuxcHvp.js} +1 -1
  104. package/dist/worker/console/static/assets/{mermaid.core-t3EZtIGh.js → mermaid.core-DwPGvpCv.js} +5 -5
  105. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BTXpTv0T.js → mindmap-definition-FAOFIHXS-DCoqG9RT.js} +1 -1
  106. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DU8UkKqA.js → pegDiagram-VL7TDLO6-BLSBmBMx.js} +1 -1
  107. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DP4y8ohp.js → pieDiagram-7S7Q4E2Y-B0t_0oJW.js} +1 -1
  108. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-B07vNaYR.js → quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js} +1 -1
  109. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-xDWktb2i.js → railroadDiagram-AXF67PYL-B3jRdATC.js} +1 -1
  110. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BLNMKqeS.js → requirementDiagram-LRYGKXZP-D-cTtXEN.js} +1 -1
  111. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-n0adalxH.js → sankeyDiagram-W5VNT64P-B25igJRE.js} +1 -1
  112. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BbnS-2DL.js → sequenceDiagram-SI44F4Z6-jW_lM1_D.js} +1 -1
  113. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4uPpCLu.js → sizeCapture-X5ZJPWSS-CrzTgsHE.js} +1 -1
  114. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA--MMbB0fX.js → stateDiagram-OKZ733FA-B01MvlqE.js} +1 -1
  115. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +1 -0
  116. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BXUgp2QY.js → swimlanes-SLNWSIFB-YcF12FiU.js} +2 -2
  117. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +8 -0
  118. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CsaMxki7.js → timeline-definition-Z64GVDOM-ClnRcg2s.js} +1 -1
  119. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-C2IuG9iH.js → vennDiagram-T6HMQDX7-B6gr_z-q.js} +1 -1
  120. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CmEWOXCW.js → wardleyDiagram-T6FBY63Y-CvSgguGH.js} +1 -1
  121. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-D_9LE0MG.js → xychartDiagram-ELKLHX3M-23OtSZCb.js} +1 -1
  122. package/dist/worker/console/static/index.html +2 -2
  123. package/dist/worker/console/static-src/app/console-types.js +68 -4
  124. package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
  125. package/dist/worker/console/static-src/app/useOperatorActions.js +41 -6
  126. package/dist/worker/console/static-src/app/useRecoveryConsole.js +10 -11
  127. package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
  128. package/dist/worker/console/static-src/app/useTaskWizard.js +74 -2
  129. package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
  130. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +141 -8
  131. package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
  132. package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
  133. package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
  134. package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
  135. package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
  136. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
  137. package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
  138. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +181 -87
  139. package/dist/worker/console/static-src/operator-chat/useChatStream.js +159 -44
  140. package/dist/worker/console/static-src/operator-chat/useChatThread.js +177 -8
  141. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
  142. package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
  143. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
  144. package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
  145. package/dist/worker/console/static-src/shell/workspace-route.js +339 -0
  146. package/dist/worker/console/workspace-context.js +234 -0
  147. package/dist/worker/console/workspace-registry.js +214 -0
  148. package/dist/worker/observability/init-runtime-activity.js +26 -0
  149. package/dist/worker/observe/node-input.js +88 -2
  150. package/dist/worker/observe/routes.js +188 -0
  151. package/dist/worker/observe/server.js +4 -0
  152. package/dist/worker/observe/static/api.js +29 -9
  153. package/dist/worker/observe/static/app.js +18 -70
  154. package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
  155. package/dist/worker/observe/static/dag-node-purpose.js +203 -0
  156. package/dist/worker/observe/static/format.js +37 -0
  157. package/dist/worker/observe/static/index.html +6 -1
  158. package/dist/worker/observe/static/inspect-workspace.js +307 -0
  159. package/dist/worker/observe/static/operator-chrome.css +145 -20
  160. package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
  161. package/dist/worker/observe/static/operator-chrome.js +330 -100
  162. package/dist/worker/observe/static/prompt-restart-candidates.d.ts +18 -0
  163. package/dist/worker/observe/static/prompt-restart-candidates.js +36 -0
  164. package/dist/worker/observe/static/router.d.ts +46 -0
  165. package/dist/worker/observe/static/router.js +25 -1
  166. package/dist/worker/observe/static/state.d.ts +50 -0
  167. package/dist/worker/observe/static/state.js +174 -2
  168. package/dist/worker/observe/static/styles.css +357 -35
  169. package/dist/worker/observe/static/views/dag-graph.js +4 -2
  170. package/dist/worker/observe/static/views/dag-inspector.js +533 -79
  171. package/dist/worker/observe/static/views/dag.d.ts +13 -0
  172. package/dist/worker/observe/static/views/dag.js +6 -4
  173. package/dist/worker/observe/static/views/dashboard.js +6 -4
  174. package/dist/worker/observe/static/views/night.js +2 -2
  175. package/dist/worker/observe/static/views/pool.js +1 -0
  176. package/dist/worker/observe/static/views/run.js +3 -1
  177. package/dist/worker/observe/static/views/task.js +56 -1
  178. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +186 -8
  179. package/dist/workflows/dag/backend-test-markdown-workflow.js +176 -1
  180. package/dist/workflows/dag/backend-test-pytest-collection.js +168 -16
  181. package/dist/workflows/dag/backend-test-result-contract.js +4 -0
  182. package/dist/workflows/dag/backend-test-scenario-param.js +339 -53
  183. package/dist/workflows/dag/backend-test-writer-completeness.js +28 -17
  184. package/dist/workflows/dag/dynamic-runtime/map.js +1 -0
  185. package/dist/workflows/dag/frontend-implementation-contract.js +88 -2
  186. package/dist/workflows/dag/frontend-plan-render.js +24 -0
  187. package/dist/workflows/dag/frontend-prewrite-gate.js +197 -0
  188. package/dist/workflows/dag/frontend-review-context.js +92 -10
  189. package/dist/workflows/dag/init-hybrid.js +239 -52
  190. package/dist/workflows/dag/interrupt-request.js +3 -3
  191. package/dist/workflows/dag/lifecycle.js +3 -3
  192. package/dist/workflows/dag/node-execution.js +45 -0
  193. package/dist/workflows/dag/types.js +62 -12
  194. package/docs/README.md +2 -0
  195. package/docs/architecture/evolution.md +45 -0
  196. package/docs/init-surface.manifest.json +1 -0
  197. package/docs/operations/local-development-environment.md +21 -0
  198. package/docs/templates/README.md +1 -1
  199. package/docs/templates/agent-dag.schema.json +18 -0
  200. package/docs/templates/backend-test-dag.json +267 -238
  201. package/docs/templates/frontend-implementation-contract.schema.json +681 -24
  202. package/harness.json +3 -3
  203. package/package.json +3 -1
  204. package/skills/loop-agent/references/hybrid-dag.md +7 -0
  205. package/dist/worker/console/static/assets/channel-TY36zt-i.js +0 -1
  206. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Dk7QCChM.js +0 -1
  207. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Dk7QCChM.js +0 -1
  208. package/dist/worker/console/static/assets/index-C3GgHg-g.css +0 -1
  209. package/dist/worker/console/static/assets/index-Ci8ksvBm.js +0 -406
  210. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BqOigMQ4.js +0 -1
  211. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Caxz9UA2.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
@@ -0,0 +1,122 @@
1
+ function resolveDagId(id) {
2
+ const value = typeof id === "function" ? id() : id;
3
+ return value?.trim() || null;
4
+ }
5
+ export function createDetailsDagActions(params) {
6
+ const fetchImpl = params.fetchFn ?? fetch;
7
+ let pending = false;
8
+ let error = null;
9
+ const completionListeners = new Set();
10
+ const emitState = () => params.onStateChange?.({ pending, error });
11
+ const emitCompletion = (outcome, identity, message) => {
12
+ for (const listener of [...completionListeners]) {
13
+ try {
14
+ listener(outcome, identity, message);
15
+ }
16
+ catch {
17
+ // a listener throwing must never break the request path
18
+ }
19
+ }
20
+ };
21
+ const run = (action, issue) => {
22
+ const sessionId = resolveDagId(params.sessionId);
23
+ const operationId = resolveDagId(params.operationId);
24
+ if (!sessionId || !operationId || pending)
25
+ return false;
26
+ const identity = {
27
+ action,
28
+ workspaceId: resolveDagId(params.workspaceId ?? null),
29
+ sessionId,
30
+ operationId,
31
+ };
32
+ pending = true;
33
+ error = null;
34
+ emitState();
35
+ void (async () => {
36
+ try {
37
+ const result = await issue(identity);
38
+ if (!result.ok) {
39
+ error = result.message ?? `DAG 关联操作失败`;
40
+ params.onFailure?.(identity, error);
41
+ emitCompletion("failure", identity, error);
42
+ return;
43
+ }
44
+ params.onSuccess?.(identity);
45
+ emitCompletion("success", identity);
46
+ }
47
+ catch (err) {
48
+ error = err instanceof Error ? err.message : String(err);
49
+ params.onFailure?.(identity, error);
50
+ emitCompletion("failure", identity, error);
51
+ }
52
+ finally {
53
+ pending = false;
54
+ emitState();
55
+ }
56
+ })();
57
+ return true;
58
+ };
59
+ return {
60
+ get pending() {
61
+ return pending;
62
+ },
63
+ get error() {
64
+ return error;
65
+ },
66
+ subscribe(listener) {
67
+ completionListeners.add(listener);
68
+ return () => completionListeners.delete(listener);
69
+ },
70
+ onAddDag() {
71
+ return run("add", async (identity) => {
72
+ // AC-002: session-scoped mutations carry the session's durable
73
+ // owning workspace so a global active-workspace switch can never
74
+ // retarget the link to another workspace's store.
75
+ const ownerQuery = identity.workspaceId
76
+ ? `?workspaceId=${encodeURIComponent(identity.workspaceId)}`
77
+ : "";
78
+ const res = await fetchImpl(`/api/operator/v1/chat/sessions/${encodeURIComponent(identity.sessionId)}/operation-links${ownerQuery}`, {
79
+ method: "POST",
80
+ credentials: "same-origin",
81
+ headers: {
82
+ "Content-Type": "application/json",
83
+ "x-loop-console-confirmation": params.confirmationToken(),
84
+ },
85
+ body: JSON.stringify({ operationId: identity.operationId }),
86
+ });
87
+ if (!res.ok) {
88
+ const body = (await res.json().catch(() => ({})));
89
+ return {
90
+ ok: false,
91
+ message: body.error?.message ??
92
+ `添加 DAG 关联失败(HTTP ${res.status})`,
93
+ };
94
+ }
95
+ return { ok: true };
96
+ });
97
+ },
98
+ onRemoveDag() {
99
+ return run("remove", async (identity) => {
100
+ const ownerQuery = identity.workspaceId
101
+ ? `?workspaceId=${encodeURIComponent(identity.workspaceId)}`
102
+ : "";
103
+ const res = await fetchImpl(`/api/operator/v1/chat/sessions/${encodeURIComponent(identity.sessionId)}/operation-links/${encodeURIComponent(identity.operationId)}${ownerQuery}`, {
104
+ method: "DELETE",
105
+ credentials: "same-origin",
106
+ headers: {
107
+ "x-loop-console-confirmation": params.confirmationToken(),
108
+ },
109
+ });
110
+ if (!res.ok && res.status !== 404) {
111
+ const body = (await res.json().catch(() => ({})));
112
+ return {
113
+ ok: false,
114
+ message: body.error?.message ??
115
+ `移除 DAG 关联失败(HTTP ${res.status})`,
116
+ };
117
+ }
118
+ return { ok: true };
119
+ });
120
+ },
121
+ };
122
+ }
@@ -24,6 +24,7 @@ export function useChatRefs() {
24
24
  const abortPostedTurnIdsRef = useRef(new Set());
25
25
  const releasedClientRequestIdsRef = useRef(new Set());
26
26
  const usageResponseKeysRef = useRef(new Set());
27
+ const unlinkedOperationIdsRef = useRef(new Map());
27
28
  const isComposingRef = useRef(false);
28
29
  const compositionEndedAtRef = useRef(0);
29
30
  // Keep the bag identity stable: individual refs never change, so domain
@@ -53,6 +54,7 @@ export function useChatRefs() {
53
54
  abortPostedTurnIdsRef,
54
55
  releasedClientRequestIdsRef,
55
56
  usageResponseKeysRef,
57
+ unlinkedOperationIdsRef,
56
58
  isComposingRef,
57
59
  compositionEndedAtRef,
58
60
  }), [
@@ -80,6 +82,7 @@ export function useChatRefs() {
80
82
  abortPostedTurnIdsRef,
81
83
  releasedClientRequestIdsRef,
82
84
  usageResponseKeysRef,
85
+ unlinkedOperationIdsRef,
83
86
  isComposingRef,
84
87
  compositionEndedAtRef,
85
88
  ]);
@@ -0,0 +1,27 @@
1
+ import { formatModelRef } from "../../chat/runtime-selection.js";
2
+ const THINKING_SHORT_LABELS = {
3
+ auto: "Auto",
4
+ off: "Off",
5
+ minimal: "Minimal",
6
+ low: "Low",
7
+ medium: "Medium",
8
+ high: "High",
9
+ xhigh: "XHigh",
10
+ max: "Max",
11
+ };
12
+ export function formatThinkingSelectionLabel(selection, effective) {
13
+ const normalized = selection || "auto";
14
+ const label = THINKING_SHORT_LABELS[normalized] ?? normalized;
15
+ if (normalized !== "auto" || !effective)
16
+ return label;
17
+ return `${label} · ${THINKING_SHORT_LABELS[effective] ?? effective}`;
18
+ }
19
+ export function resolveModelDisplayName(models, activeModelRef) {
20
+ if (!activeModelRef)
21
+ return "选择模型";
22
+ const current = models.find((model) => formatModelRef(model.provider, model.id) === activeModelRef);
23
+ if (current)
24
+ return current.name?.trim() || current.id;
25
+ const slash = activeModelRef.indexOf("/");
26
+ return slash === -1 ? activeModelRef : activeModelRef.slice(slash + 1);
27
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Mutual-exclusion state for large spatial overlays in Operator Chat.
3
- * At most one of: sidebar drawer, process, runtime context, tools, activity.
3
+ * At most one of: sidebar drawer, process, runtime context, tools.
4
4
  * Small composer menus (model/thinking) are out of scope.
5
5
  */
6
6
  export function createSpatialOverlayState(active = "none") {
@@ -33,6 +33,5 @@ export function spatialOverlayFlags(state) {
33
33
  processOpen: state.active === "process",
34
34
  runtimeContextOpen: state.active === "runtime-context",
35
35
  toolsOpen: state.active === "tools",
36
- activityOpen: state.active === "activity",
37
36
  };
38
37
  }
@@ -38,6 +38,15 @@ export function turnPhaseFromOwnership(bag) {
38
38
  return "running";
39
39
  return "idle";
40
40
  }
41
+ /**
42
+ * DSH-style visual projection: Stop immediately releases the composer while
43
+ * the ownership projection remains `stopping` for deferred-send routing and
44
+ * duplicate-Turn prevention.
45
+ */
46
+ export function visualTurnPhaseFromOwnership(bag) {
47
+ const phase = turnPhaseFromOwnership(bag);
48
+ return phase === "stopping" ? "idle" : phase;
49
+ }
41
50
  export function createTurnOwnershipBag(seed) {
42
51
  return {
43
52
  submitInFlight: false,
@@ -394,6 +403,9 @@ export function classifyAbortResponse(input) {
394
403
  isTerminalTurnState(terminalState)) {
395
404
  return { action: "terminal-idle", turnId: input.turnId };
396
405
  }
406
+ if (input.httpOk && input.body.accepted === true) {
407
+ return { action: "abort-accepted-background" };
408
+ }
397
409
  if (input.body.error?.code === "TURN_ABORT_PENDING") {
398
410
  return { action: "abort-pending-notice" };
399
411
  }
@@ -416,6 +428,10 @@ export function applyAbortDecision(bag, decision, notice, opts) {
416
428
  if (!current)
417
429
  return;
418
430
  bag.settledTurnIds.add(decision.turnId);
431
+ if (bag.pendingSubmission) {
432
+ releaseSubmitOwnership(bag, bag.pendingSubmission.clientRequestId);
433
+ }
434
+ clearStopRequested(bag);
419
435
  bag.streaming = false;
420
436
  bag.activeTurnId = null;
421
437
  bag.assistantId = null;
@@ -423,6 +439,11 @@ export function applyAbortDecision(bag, decision, notice, opts) {
423
439
  opts?.markIdle?.();
424
440
  return;
425
441
  }
442
+ if (decision.action === "abort-accepted-background") {
443
+ // Visual idle is projected by the caller. Hidden ownership deliberately
444
+ // remains stopping until terminal SSE or /state evidence releases it.
445
+ return;
446
+ }
426
447
  if (decision.action === "abort-pending-notice") {
427
448
  // Non-fatal; keep busy.
428
449
  notice.showNotice(ABORT_PENDING_NOTICE);
@@ -436,6 +457,10 @@ export function applyAbortDecision(bag, decision, notice, opts) {
436
457
  bag.settledTurnIds.add(bag.stoppingTurnId);
437
458
  }
438
459
  bag.streaming = false;
460
+ if (bag.pendingSubmission) {
461
+ releaseSubmitOwnership(bag, bag.pendingSubmission.clientRequestId);
462
+ }
463
+ clearStopRequested(bag);
439
464
  bag.activeTurnId = null;
440
465
  bag.assistantId = null;
441
466
  bag.stoppingTurnId = null;
@@ -40,8 +40,9 @@ export function reconcileDeferredSubmissionFromState(input) {
40
40
  const { clientRequestId, blockedByTurnId, state } = input;
41
41
  if (!state)
42
42
  return { action: "hold" };
43
- if (state.deferredTurn?.clientRequestId === clientRequestId) {
44
- return { action: "deferred", deferredTurn: state.deferredTurn };
43
+ const queued = state.deferredTurns?.find((item) => item.clientRequestId === clientRequestId) ?? (state.deferredTurn?.clientRequestId === clientRequestId ? state.deferredTurn : undefined);
44
+ if (queued) {
45
+ return { action: "deferred", deferredTurn: queued };
45
46
  }
46
47
  if (state.activeTurn?.clientRequestId === clientRequestId) {
47
48
  return { action: "accepted", turn: state.activeTurn };