@tea-agent/loop-agent 0.43.0-next.17 → 0.43.0-next.3

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 (187) hide show
  1. package/CHANGELOG.md +9 -140
  2. package/dist/application/task-lifecycle/advance.js +4 -17
  3. package/dist/application/task-lifecycle/observe.js +29 -43
  4. package/dist/application/task-lifecycle/plan-transitions.js +4 -5
  5. package/dist/build-stamp.json +3 -3
  6. package/dist/commands/client-recovery.js +55 -20
  7. package/dist/commands/new-task.js +5 -0
  8. package/dist/commands/status.js +57 -0
  9. package/dist/commands/task-contract.js +269 -0
  10. package/dist/executors/dag-pi-executor.js +230 -269
  11. package/dist/executors/pi-executor.js +0 -2
  12. package/dist/executors/pi-sdk-executor.js +39 -77
  13. package/dist/executors/shell-executor.js +2 -3
  14. package/dist/executors/shell-write-guard.js +32 -27
  15. package/dist/shared/pi-context-pressure/extension.js +16 -26
  16. package/dist/shared/pi-retry-settings.js +0 -40
  17. package/dist/shared/prompts.js +26 -0
  18. package/dist/task/config.js +2 -0
  19. package/dist/task/contract/validate-draft.js +106 -0
  20. package/dist/task/goal.js +3 -0
  21. package/dist/task/index.js +12 -0
  22. package/dist/task/lifecycle.js +1 -0
  23. package/dist/task/operator/capabilities.js +6 -0
  24. package/dist/task/operator/envelope.js +2 -0
  25. package/dist/task/operator/index.js +5 -0
  26. package/dist/task/operator/registry.js +2 -0
  27. package/dist/task/operator/types.js +1 -0
  28. package/dist/task/paths.js +1 -0
  29. package/dist/task/source-prepare/source-fidelity-pi.js +2 -2
  30. package/dist/task/source-references.js +23 -48
  31. package/dist/task/source-state.js +1 -0
  32. package/dist/task/subagent-guidance.js +1 -0
  33. package/dist/worker/console/chat/assistant-content.js +2 -23
  34. package/dist/worker/console/chat/explore-tools.js +0 -13
  35. package/dist/worker/console/chat/pi-runtime.js +1182 -221
  36. package/dist/worker/console/chat/routes.js +71 -213
  37. package/dist/worker/console/chat/sdd-data-alignment.js +9 -65
  38. package/dist/worker/console/chat/session-catalog.js +0 -32
  39. package/dist/worker/console/chat/session-store.js +6 -22
  40. package/dist/worker/console/chat/shortcuts.js +0 -6
  41. package/dist/worker/console/chat/sift-bridge.js +1 -0
  42. package/dist/worker/console/chat/tool-preview.js +0 -11
  43. package/dist/worker/console/chat/tools.js +0 -6
  44. package/dist/worker/console/console-update-and-init.js +19 -1
  45. package/dist/worker/console/console-update-runtime.js +20 -5
  46. package/dist/worker/console/index.js +20 -0
  47. package/dist/worker/console/operator-actions.js +1 -13
  48. package/dist/worker/console/routes.js +0 -8
  49. package/dist/worker/console/server.js +29 -11
  50. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4NXyedy.js → abnfDiagram-N423BO3Z-hUmM_GRf.js} +1 -1
  51. package/dist/worker/console/static/assets/{arc-NZ3qXvBI.js → arc-Bt-xuieW.js} +1 -1
  52. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-COZSRvml.js → architectureDiagram-T3A2C74G-DTqkL4DJ.js} +1 -1
  53. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Ck0Gxi9C.js → blockDiagram-VBNYF7ZC-Cy0MNnzV.js} +1 -1
  54. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BX5HQ4Ox.js → c4Diagram-5PPSVZJV-DDdlT0Pd.js} +1 -1
  55. package/dist/worker/console/static/assets/channel-BpzRnZmU.js +1 -0
  56. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CoviemSL.js → chunk-2GRJ4B5K-3JawwNZ6.js} +1 -1
  57. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DbOdOkbZ.js → chunk-2Q5K7J3B-DoTp7Cri.js} +1 -1
  58. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BsG2pmdQ.js → chunk-5RXB4S5H-CcirhZaS.js} +1 -1
  59. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DGdvrNm8.js → chunk-5VM5RSS4-VrG21gnP.js} +1 -1
  60. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BAy7Yd6y.js → chunk-6Q2QTUOP-DDOgIS70.js} +1 -1
  61. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D9UA7hUb.js → chunk-GF5L2VYU-CBjmgvJ_.js} +1 -1
  62. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DPz7SZ8V.js → chunk-JWPE2WC7-CCQSht8M.js} +1 -1
  63. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BmuEOIh7.js → chunk-KBJHAD2P-BpGMkUUV.js} +1 -1
  64. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CIhBWnd8.js → chunk-RYQCIY6F-DNDT41QL.js} +1 -1
  65. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CScR6mDD.js → chunk-XXDRQBXY-euXnDFbn.js} +1 -1
  66. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BhlMVqCc.js +1 -0
  67. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BhlMVqCc.js +1 -0
  68. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BjpfWaUr.js → cose-bilkent-JH36ORCC-BJ6NAeql.js} +1 -1
  69. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BFQohJgT.js → cynefin-VYW2F7L2-F5JKIvIq.js} +1 -1
  70. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-D3gzRJnS.js → cynefinDiagram-MW4NZA55-Cwmkl_Gi.js} +1 -1
  71. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-5eojkhoA.js → dagre-VZM6K2ZE-BmCZ8815.js} +1 -1
  72. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CpD8LWu_.js → diagram-7IWD3JNH-zWA3hUnX.js} +1 -1
  73. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B8_4qJ2a.js → diagram-B4RE2ZJO-BzA-888F.js} +1 -1
  74. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-HOsXf0eu.js → diagram-LBJQPF4R-tPNheoch.js} +1 -1
  75. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BqwRwiWP.js → diagram-Q27KOJAE-Cdi7Fyqp.js} +1 -1
  76. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BRVCNZe1.js → diagram-UB23O5K3-DFK9VBf1.js} +1 -1
  77. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Cvb1TgGh.js → ebnfDiagram-BXEA7PRR-xCUr1kpg.js} +1 -1
  78. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DS0O0qG9.js → erDiagram-JOGREHBK-BANQHY_A.js} +1 -1
  79. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BHIRvRr3.js → flowDiagram-UKHOOZJN-VHJYEMkP.js} +1 -1
  80. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DcCJ1JWx.js → ganttDiagram-PKOTCBZU-DiyZQ0C6.js} +1 -1
  81. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-B9ia5ony.js → gitGraphDiagram-DS77QQ5N-CZtIeBBa.js} +1 -1
  82. package/dist/worker/console/static/assets/index-BlN6ytLr.css +1 -0
  83. package/dist/worker/console/static/assets/index-CA-jfWlE.js +449 -0
  84. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-3ogpgegn.js → infoDiagram-6WML65LV-BuSspC0X.js} +1 -1
  85. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-4tgpQ5SL.js → ishikawaDiagram-WSZJBQD7-DRJZyPFy.js} +1 -1
  86. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DNfgHqFx.js → journeyDiagram-NVQOT4AX-DIfXIVuE.js} +1 -1
  87. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Dz7ngC8z.js → kanban-definition-27J2QSJJ-CT10_7Lt.js} +1 -1
  88. package/dist/worker/console/static/assets/{linear-DI7Jv62E.js → linear-ufemj74H.js} +1 -1
  89. package/dist/worker/console/static/assets/{mermaid.core-CQA4Nzmo.js → mermaid.core-DEQe8-_m.js} +5 -5
  90. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CtsMc8Mf.js → mindmap-definition-FAOFIHXS-BRLUrbrC.js} +1 -1
  91. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-ByppE9yH.js → pegDiagram-VL7TDLO6-BgibKtiF.js} +1 -1
  92. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B5PtgFgt.js → pieDiagram-7S7Q4E2Y-D3eyfdV9.js} +1 -1
  93. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Cq4p0k2K.js → quadrantDiagram-CIZ2JOQS-DXeTk5Px.js} +1 -1
  94. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DjfkyljN.js → railroadDiagram-AXF67PYL-BgXdFEe7.js} +1 -1
  95. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DzynNRSl.js → requirementDiagram-LRYGKXZP-CseC2A7R.js} +1 -1
  96. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cj7TCpTJ.js → sankeyDiagram-W5VNT64P-D80PFzfJ.js} +1 -1
  97. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-C73C6ykA.js → sequenceDiagram-SI44F4Z6-BWzHW7LS.js} +1 -1
  98. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BiNLgN2x.js → sizeCapture-X5ZJPWSS-xWQYTLAn.js} +1 -1
  99. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-UwvjS64-.js → stateDiagram-OKZ733FA-CLxtpZeL.js} +1 -1
  100. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-CiVoq4G-.js +1 -0
  101. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CC7DH98r.js → swimlanes-SLNWSIFB-DwugtmWV.js} +2 -2
  102. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BkdgdpfR.js +8 -0
  103. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-LSBXTR70.js → timeline-definition-Z64GVDOM-DHEOwHIe.js} +1 -1
  104. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BAuxWwGP.js → vennDiagram-T6HMQDX7-pmbZKlBK.js} +1 -1
  105. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y--E5_gjZx.js → wardleyDiagram-T6FBY63Y-CivHoM5q.js} +1 -1
  106. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-dJWNmyzF.js → xychartDiagram-ELKLHX3M-BfHIE7o6.js} +1 -1
  107. package/dist/worker/console/static/index.html +2 -2
  108. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +10 -122
  109. package/dist/worker/console/static-src/operator-chat/compaction-message.js +0 -7
  110. package/dist/worker/console/static-src/operator-chat/pending-user-message.js +15 -35
  111. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +62 -136
  112. package/dist/worker/console/static-src/operator-chat/useChatStream.js +68 -159
  113. package/dist/worker/console/static-src/operator-chat/useChatThread.js +56 -75
  114. package/dist/worker/console/static-src/operator-chat/useComposer.js +78 -206
  115. package/dist/worker/console/workspace-context.js +1 -21
  116. package/dist/worker/observe/static/router.js +1 -1
  117. package/dist/worker/observe/static/styles.css +4 -7
  118. package/dist/worker/observe/static/views/dag-inspector.js +19 -12
  119. package/dist/worker/observe/static/views/dag.js +2 -2
  120. package/dist/worker/scheduler/index.js +25 -0
  121. package/dist/workflows/dag/facts.js +4 -0
  122. package/dist/workflows/dag/frontend-closeout.js +1 -1
  123. package/dist/workflows/dag/frontend-design-policy.js +1 -2
  124. package/dist/workflows/dag/frontend-implementation-contract.js +4 -8
  125. package/dist/workflows/dag/frontend-prewrite-gate.js +3 -3
  126. package/dist/workflows/dag/frontend-repair.js +76 -55
  127. package/dist/workflows/dag/frontend-review-context.js +1 -2
  128. package/dist/workflows/dag/frontend-review-scopes.js +12 -34
  129. package/dist/workflows/dag/frontend-shape-facts.js +2 -12
  130. package/dist/workflows/dag/frontend-verification-trace.js +42 -8
  131. package/dist/workflows/dag/index.js +6 -0
  132. package/dist/workflows/dag/init-hybrid.js +160 -97
  133. package/dist/workflows/dynamic/index.js +7 -0
  134. package/docs/architecture/runtime-boundaries.md +3 -3
  135. package/docs/templates/frontend-implementation-dag.json +8 -9
  136. package/package.json +3 -7
  137. package/skills/frontend-bounded-implement/SKILL.md +3 -4
  138. package/skills/frontend-bounded-implement/references/code-standards.md +3 -3
  139. package/skills/frontend-contract/references/contract-protocol.md +1 -3
  140. package/skills/frontend-design-review/SKILL.md +7 -12
  141. package/skills/frontend-design-review/references/review-checklist.md +7 -7
  142. package/skills/frontend-plan/SKILL.md +0 -19
  143. package/skills/frontend-plan/references/decision-contract.md +19 -26
  144. package/skills/frontend-review/SKILL.md +18 -12
  145. package/skills/frontend-review/references/review-findings.md +43 -24
  146. package/dist/shared/pi-provider-recovery.js +0 -182
  147. package/dist/worker/console/chat/browser-automation.js +0 -363
  148. package/dist/worker/console/chat/browser-policy.js +0 -113
  149. package/dist/worker/console/chat/browser-routes.js +0 -162
  150. package/dist/worker/console/chat/pi-runtime/custom-tools/ask-user-question.js +0 -44
  151. package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +0 -89
  152. package/dist/worker/console/chat/pi-runtime/custom-tools/explore-tools.js +0 -202
  153. package/dist/worker/console/chat/pi-runtime/custom-tools/goal-tools.js +0 -79
  154. package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +0 -86
  155. package/dist/worker/console/chat/pi-runtime/custom-tools/todo-write.js +0 -38
  156. package/dist/worker/console/chat/pi-runtime/inspection-types.js +0 -28
  157. package/dist/worker/console/chat/pi-runtime/inspection.js +0 -439
  158. package/dist/worker/console/chat/pi-runtime/sdk-bindings.js +0 -153
  159. package/dist/worker/console/chat/pi-runtime/sdk-session.js +0 -5
  160. package/dist/worker/console/chat/scm-routes.js +0 -217
  161. package/dist/worker/console/chat/scm-service.js +0 -283
  162. package/dist/worker/console/chat/scm-tools.js +0 -111
  163. package/dist/worker/console/chat/session-mode-view.js +0 -49
  164. package/dist/worker/console/chat/session-mode.js +0 -220
  165. package/dist/worker/console/chat/terminal-routes.js +0 -216
  166. package/dist/worker/console/chat/terminal-sessions.js +0 -348
  167. package/dist/worker/console/chat/terminal-tools.js +0 -211
  168. package/dist/worker/console/static/assets/channel-BxdTlb_5.js +0 -1
  169. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-_ByA1Nf8.js +0 -1
  170. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-_ByA1Nf8.js +0 -1
  171. package/dist/worker/console/static/assets/index-B9goN3S5.css +0 -1
  172. package/dist/worker/console/static/assets/index-wXlQohNs.js +0 -469
  173. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-nLgMZ0D3.js +0 -1
  174. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BcYqTady.js +0 -8
  175. package/dist/worker/console/static-src/operator-chat/active-turn-tail.js +0 -10
  176. package/dist/worker/console/static-src/operator-chat/chat-link.js +0 -94
  177. package/dist/worker/console/static-src/operator-chat/chat-scroll-position.js +0 -24
  178. package/dist/worker/console/static-src/operator-chat/composer-session-ledger.js +0 -192
  179. package/dist/worker/console/static-src/operator-chat/process-label.js +0 -41
  180. package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +0 -13
  181. package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +0 -10
  182. package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +0 -51
  183. package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +0 -21
  184. package/dist/worker/console/workspace-initialization.js +0 -209
  185. package/dist/workflows/dag/frontend-capacity.js +0 -9
  186. package/dist/workflows/dag/frontend-plan-completeness.js +0 -186
  187. package/dist/workflows/dag/frontend-plan-recovery-policy.js +0 -18
@@ -16,7 +16,6 @@ import { randomUUID } from "node:crypto";
16
16
  import { access } from "node:fs/promises";
17
17
  import { parseAssistantContent } from "./assistant-content.js";
18
18
  import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, } from "./tools.js";
19
- import { InvalidChatSessionModeError, SESSION_MODE_ACTION_DENIED_CODE, SESSION_MODE_ACTION_DENIED_MESSAGE, SESSION_MODE_IMMUTABLE_CODE, UnknownChatSessionModeError, isWorkflowSessionMode, parseCreateSessionMode, readStoredSessionMode, shouldAcceptOperatorSnapshot, } from "./session-mode.js";
20
19
  import { buildModelCallableToolSchemas } from "./tool-adapter.js";
21
20
  import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
22
21
  import { hashChatTurnPayload, projectChatToolEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
@@ -45,80 +44,11 @@ import { buildGoalCompactionInstructions, buildGoalContinuationContext, } from "
45
44
  import { classifyGoalRoundAdmission, } from "./goal-round-driver.js";
46
45
  import { isTerminalOperationState } from "../../../infrastructure/console/operation-store.js";
47
46
  import { SddDataAlignmentError, } from "./sdd-data-alignment.js";
48
- import { TerminalSessionRegistry } from "./terminal-sessions.js";
49
- import { handleTerminalRequest } from "./terminal-routes.js";
50
- import { handleScmRequest } from "./scm-routes.js";
51
- import { handleBrowserRequest } from "./browser-routes.js";
52
47
  function projectBrowserChatSession(record) {
53
48
  const { telemetrySessionId, ...projected } = record;
54
49
  void telemetrySessionId;
55
50
  return projected;
56
51
  }
57
- function reopenInitFromRecord(record) {
58
- return {
59
- sessionId: record.sessionId,
60
- sessionFile: record.sessionFile,
61
- ...(record.modelProvider && record.modelId
62
- ? { model: { provider: record.modelProvider, modelId: record.modelId } }
63
- : {}),
64
- sessionMode: record.sessionMode,
65
- };
66
- }
67
- async function readChatSessionMode(deps, sessionId) {
68
- let record;
69
- try {
70
- record = await deps.store.get(sessionId);
71
- }
72
- catch (error) {
73
- if (error instanceof UnknownChatSessionModeError) {
74
- return {
75
- ok: false,
76
- status: 409,
77
- code: error.code,
78
- message: error.message,
79
- };
80
- }
81
- throw error;
82
- }
83
- if (!record) {
84
- return {
85
- ok: false,
86
- status: 404,
87
- code: "NOT_FOUND",
88
- message: `chat session not found: ${sessionId}`,
89
- };
90
- }
91
- // Normalize: the store contract always fills sessionMode, but handler-level
92
- // fakes / partial records may omit it — treat missing as workflow (the
93
- // stock-record read rule), while a present-but-unknown value still fails
94
- // closed in the store layer.
95
- return {
96
- ok: true,
97
- record,
98
- sessionMode: readStoredSessionMode(record.sessionMode),
99
- };
100
- }
101
- async function requireWorkflowSession(res, deps, sessionId) {
102
- const resolved = await readChatSessionMode(deps, sessionId);
103
- if (!resolved.ok) {
104
- sendJson(res, resolved.status, {
105
- ok: false,
106
- error: { code: resolved.code, message: resolved.message },
107
- });
108
- return undefined;
109
- }
110
- if (!isWorkflowSessionMode(resolved.sessionMode)) {
111
- sendJson(res, 409, {
112
- ok: false,
113
- error: {
114
- code: SESSION_MODE_ACTION_DENIED_CODE,
115
- message: SESSION_MODE_ACTION_DENIED_MESSAGE,
116
- },
117
- });
118
- return undefined;
119
- }
120
- return resolved.record;
121
- }
122
52
  /**
123
53
  * Reattach the durable event-ring order to session-store rows. The session
124
54
  * store remains the content authority; the ring only supplies chronology.
@@ -635,22 +565,6 @@ workspaceId) {
635
565
  });
636
566
  return;
637
567
  }
638
- let sessionMode;
639
- try {
640
- sessionMode = parseCreateSessionMode(body.sessionMode);
641
- }
642
- catch (error) {
643
- sendJson(res, 400, {
644
- ok: false,
645
- error: {
646
- code: error instanceof InvalidChatSessionModeError
647
- ? error.code
648
- : "INVALID_SESSION_MODE",
649
- message: error instanceof Error ? error.message : String(error),
650
- },
651
- });
652
- return;
653
- }
654
568
  const provider = typeof body.modelProvider === "string" ? body.modelProvider : undefined;
655
569
  const modelId = typeof body.modelId === "string" ? body.modelId : undefined;
656
570
  const snapshotInput = body.snapshot;
@@ -672,16 +586,6 @@ workspaceId) {
672
586
  let createdSessionId;
673
587
  let persisted = false;
674
588
  try {
675
- if (snapshotInput !== undefined && !shouldAcceptOperatorSnapshot(sessionMode)) {
676
- sendJson(res, 409, {
677
- ok: false,
678
- error: {
679
- code: SESSION_MODE_ACTION_DENIED_CODE,
680
- message: "Operator snapshots cannot be imported into Pi sessions",
681
- },
682
- });
683
- return;
684
- }
685
589
  const snapshot = snapshotInput === undefined ? undefined : projectCompactSnapshot(snapshotInput);
686
590
  // A Console record promises that its Pi JSONL can be reopened after a
687
591
  // Console restart. Do not make that promise until Pi has finished
@@ -689,7 +593,6 @@ workspaceId) {
689
593
  // future JSONL path, leaving an unrecoverable orphan when init failed or
690
594
  // the process restarted in that window.
691
595
  const handle = await deps.runtime.createSession({
692
- sessionMode,
693
596
  ...(provider && modelId ? { model: { provider, modelId } } : {}),
694
597
  ...(snapshot
695
598
  ? {
@@ -716,7 +619,6 @@ workspaceId) {
716
619
  sessionFile: handle.sessionFile,
717
620
  modelProvider: selection.model?.provider ?? handle.model?.provider,
718
621
  modelId: selection.model?.modelId ?? handle.model?.modelId,
719
- sessionMode,
720
622
  // AC-R7-002: explicit parameter from the dispatcher — the runtime
721
623
  // store.create wrapper is gone; body workspaceId (if any) only acts as
722
624
  // a fallback for direct (non-dispatcher) handler tests.
@@ -787,7 +689,6 @@ export async function handleForkChatSession(req, res, deps, sourceSessionId) {
787
689
  try {
788
690
  const handle = await deps.runtime.forkSession({
789
691
  sourceSessionFile: source.sessionFile ?? "",
790
- sessionMode: source.sessionMode,
791
692
  ...(source.modelProvider && source.modelId
792
693
  ? { model: { provider: source.modelProvider, modelId: source.modelId } }
793
694
  : {}),
@@ -854,7 +755,10 @@ export async function handleBranchChatSession(req, res, deps, sessionId) {
854
755
  }
855
756
  try {
856
757
  if (!deps.runtime.hasSession(sessionId)) {
857
- const reopened = await deps.runtime.reopenSession(reopenInitFromRecord(record));
758
+ const reopened = await deps.runtime.reopenSession({
759
+ sessionId,
760
+ sessionFile: record.sessionFile,
761
+ });
858
762
  if (!reopened.ok) {
859
763
  const mapped = await mapFailedReopen(deps, sessionId, reopened);
860
764
  sendJson(res, mapped.status, {
@@ -1327,8 +1231,13 @@ export async function handleChatGoal(req, res, deps, sessionId) {
1327
1231
  });
1328
1232
  return;
1329
1233
  }
1330
- if (!(await requireChatSession(res, deps, sessionId)))
1234
+ if (!(await deps.store.get(sessionId))) {
1235
+ sendJson(res, 404, {
1236
+ ok: false,
1237
+ error: { code: "NOT_FOUND", message: `chat session not found: ${sessionId}` },
1238
+ });
1331
1239
  return;
1240
+ }
1332
1241
  if (req.method === "GET") {
1333
1242
  sendJson(res, 200, { ok: true, goal: registry.get(sessionId) });
1334
1243
  return;
@@ -1542,7 +1451,6 @@ export async function listChatSessionSummaries(deps, ownerWorkspaceId) {
1542
1451
  ...(session.thinkingLevel !== undefined
1543
1452
  ? { thinkingLevel: session.thinkingLevel }
1544
1453
  : {}),
1545
- sessionMode: session.sessionMode,
1546
1454
  activeTurnId: active?.turnId,
1547
1455
  turnPhase: active?.abortRequestedAt
1548
1456
  ? "stopping"
@@ -1566,16 +1474,6 @@ export async function handlePatchChatSession(req, res, deps, sessionId) {
1566
1474
  }
1567
1475
  try {
1568
1476
  const body = await readJsonBody(req);
1569
- if ("sessionMode" in body) {
1570
- sendJson(res, 409, {
1571
- ok: false,
1572
- error: {
1573
- code: SESSION_MODE_IMMUTABLE_CODE,
1574
- message: "sessionMode cannot be changed after create",
1575
- },
1576
- });
1577
- return;
1578
- }
1579
1477
  let record;
1580
1478
  if (typeof body.title === "string")
1581
1479
  record = await deps.store.rename(sessionId, body.title);
@@ -1634,7 +1532,13 @@ export async function handleReopenChatSession(req, res, deps, sessionId) {
1634
1532
  });
1635
1533
  return;
1636
1534
  }
1637
- const result = await deps.runtime.reopenSession(reopenInitFromRecord(record));
1535
+ const result = await deps.runtime.reopenSession({
1536
+ sessionId,
1537
+ sessionFile: record.sessionFile,
1538
+ ...(record.modelProvider && record.modelId
1539
+ ? { model: { provider: record.modelProvider, modelId: record.modelId } }
1540
+ : {}),
1541
+ });
1638
1542
  if (!result.ok) {
1639
1543
  const mapped = await mapFailedReopen(deps, sessionId, result);
1640
1544
  sendJson(res, mapped.status, {
@@ -1714,7 +1618,13 @@ export async function handleChatPrompt(req, res, deps, sessionId) {
1714
1618
  });
1715
1619
  return;
1716
1620
  }
1717
- const reopen = await deps.runtime.reopenSession(reopenInitFromRecord(record));
1621
+ const reopen = await deps.runtime.reopenSession({
1622
+ sessionId,
1623
+ sessionFile: record.sessionFile,
1624
+ ...(record.modelProvider && record.modelId
1625
+ ? { model: { provider: record.modelProvider, modelId: record.modelId } }
1626
+ : {}),
1627
+ });
1718
1628
  if (!reopen.ok) {
1719
1629
  const mapped = await mapFailedReopen(deps, sessionId, reopen);
1720
1630
  sendJson(res, mapped.status, {
@@ -1978,7 +1888,13 @@ export async function handleCreateChatTurn(req, res, deps, sessionId, trustedPay
1978
1888
  });
1979
1889
  return;
1980
1890
  }
1981
- const reopen = await deps.runtime.reopenSession(reopenInitFromRecord(record));
1891
+ const reopen = await deps.runtime.reopenSession({
1892
+ sessionId,
1893
+ sessionFile: record.sessionFile,
1894
+ ...(record.modelProvider && record.modelId
1895
+ ? { model: { provider: record.modelProvider, modelId: record.modelId } }
1896
+ : {}),
1897
+ });
1982
1898
  if (!reopen.ok) {
1983
1899
  const mapped = await mapFailedReopen(deps, sessionId, reopen);
1984
1900
  sendJson(res, mapped.status, {
@@ -2904,7 +2820,6 @@ export async function handleChatCommands(res, deps, sessionId) {
2904
2820
  const warning = typeof listed.warning === "string" && listed.warning.trim()
2905
2821
  ? listed.warning.trim().slice(0, 160)
2906
2822
  : undefined;
2907
- const resolvedMode = await readChatSessionMode(deps, sessionId);
2908
2823
  res.statusCode = 200;
2909
2824
  res.setHeader("content-type", "application/json; charset=utf-8");
2910
2825
  res.end(JSON.stringify({
@@ -2912,25 +2827,18 @@ export async function handleChatCommands(res, deps, sessionId) {
2912
2827
  commands,
2913
2828
  capabilities: {
2914
2829
  sddBingo: Boolean(await deps.sddDataAlignment?.isEligible()),
2915
- ...(resolvedMode.ok ? { sessionMode: resolvedMode.sessionMode } : {}),
2916
2830
  },
2917
2831
  ...(warning ? { warning } : {}),
2918
2832
  }));
2919
2833
  }
2920
2834
  catch (error) {
2921
2835
  // Whole-list / readiness failures stay fail-soft with empty commands + warning.
2922
- // Keep the two capability shapes symmetric: the fallback mode mirrors the
2923
- // client-side prop fallback in useComposer.
2924
- const fallbackMode = await readChatSessionMode(deps, sessionId).catch(() => undefined);
2925
2836
  res.statusCode = 200;
2926
2837
  res.setHeader("content-type", "application/json; charset=utf-8");
2927
2838
  res.end(JSON.stringify({
2928
2839
  ok: true,
2929
2840
  commands: [],
2930
- capabilities: {
2931
- sddBingo: false,
2932
- ...(fallbackMode?.ok ? { sessionMode: fallbackMode.sessionMode } : {}),
2933
- },
2841
+ capabilities: { sddBingo: false },
2934
2842
  warning: error instanceof Error ? error.message : "commands unavailable",
2935
2843
  }));
2936
2844
  }
@@ -3175,7 +3083,13 @@ export async function ensureActiveSession(deps, sessionId) {
3175
3083
  message: `chat session not found: ${sessionId}`,
3176
3084
  };
3177
3085
  }
3178
- const reopened = await deps.runtime.reopenSession(reopenInitFromRecord(record));
3086
+ const reopened = await deps.runtime.reopenSession({
3087
+ sessionId,
3088
+ sessionFile: record.sessionFile,
3089
+ ...(record.modelProvider && record.modelId
3090
+ ? { model: { provider: record.modelProvider, modelId: record.modelId } }
3091
+ : {}),
3092
+ });
3179
3093
  if (!reopened.ok) {
3180
3094
  return { ok: false, ...(await mapFailedReopen(deps, sessionId, reopened)) };
3181
3095
  }
@@ -3504,7 +3418,7 @@ async function handleStartInterview(req, res, deps, sessionId) {
3504
3418
  });
3505
3419
  return;
3506
3420
  }
3507
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3421
+ if (!(await requireChatSession(res, deps, sessionId)))
3508
3422
  return;
3509
3423
  try {
3510
3424
  const body = await readJsonBody(req);
@@ -3546,7 +3460,7 @@ async function handleAnswerInterview(req, res, deps, sessionId, interviewSession
3546
3460
  });
3547
3461
  return;
3548
3462
  }
3549
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3463
+ if (!(await requireChatSession(res, deps, sessionId)))
3550
3464
  return;
3551
3465
  try {
3552
3466
  const body = await readJsonBody(req);
@@ -3582,7 +3496,7 @@ async function handleAnswerInterview(req, res, deps, sessionId, interviewSession
3582
3496
  }
3583
3497
  }
3584
3498
  async function handleGetInterviewFact(res, deps, sessionId, interviewSessionId, fact) {
3585
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3499
+ if (!(await requireChatSession(res, deps, sessionId)))
3586
3500
  return;
3587
3501
  const state = await new ChatInterviewAdapter(deps.appData, deps.events).get(interviewSessionId);
3588
3502
  if (!state || state.interview.operatorSessionId !== sessionId) {
@@ -3680,7 +3594,7 @@ async function handleContractApplyHumanGate(req, res, deps, sessionId, step) {
3680
3594
  });
3681
3595
  return;
3682
3596
  }
3683
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3597
+ if (!(await requireChatSession(res, deps, sessionId)))
3684
3598
  return;
3685
3599
  const ctx = deps.runtime.actionContext;
3686
3600
  if (!ctx) {
@@ -3862,7 +3776,7 @@ async function handleDagHumanGate(req, res, deps, sessionId, step) {
3862
3776
  });
3863
3777
  return;
3864
3778
  }
3865
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3779
+ if (!(await requireChatSession(res, deps, sessionId)))
3866
3780
  return;
3867
3781
  const ctx = deps.runtime.actionContext;
3868
3782
  if (!ctx) {
@@ -3971,7 +3885,7 @@ async function handleMutationHumanGate(req, res, deps, sessionId) {
3971
3885
  });
3972
3886
  return;
3973
3887
  }
3974
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3888
+ if (!(await requireChatSession(res, deps, sessionId)))
3975
3889
  return;
3976
3890
  const ctx = deps.runtime.actionContext;
3977
3891
  if (!ctx) {
@@ -4060,7 +3974,7 @@ async function handleConfirmTaskKind(req, res, deps, sessionId, interviewSession
4060
3974
  });
4061
3975
  return;
4062
3976
  }
4063
- if (!(await requireWorkflowSession(res, deps, sessionId)))
3977
+ if (!(await requireChatSession(res, deps, sessionId)))
4064
3978
  return;
4065
3979
  try {
4066
3980
  const body = await readJsonBody(req);
@@ -4116,7 +4030,13 @@ export async function handleChatCompact(req, res, deps, sessionId) {
4116
4030
  return;
4117
4031
  }
4118
4032
  if (!deps.runtime.hasSession(sessionId)) {
4119
- const reopened = await deps.runtime.reopenSession(reopenInitFromRecord(record));
4033
+ const reopened = await deps.runtime.reopenSession({
4034
+ sessionId,
4035
+ sessionFile: record.sessionFile,
4036
+ ...(record.modelProvider && record.modelId
4037
+ ? { model: { provider: record.modelProvider, modelId: record.modelId } }
4038
+ : {}),
4039
+ });
4120
4040
  if (!reopened.ok) {
4121
4041
  const mapped = await mapFailedReopen(deps, sessionId, reopened);
4122
4042
  sendJson(res, mapped.status, {
@@ -4140,9 +4060,7 @@ export async function handleChatCompact(req, res, deps, sessionId) {
4140
4060
  const rawInstructions = typeof body.instructions === "string" ? body.instructions : undefined;
4141
4061
  const currentTodos = projectCurrentTodos(deps.events.snapshot(sessionId));
4142
4062
  const todoInstructions = buildTodoCompactionInstructions(rawInstructions, currentTodos);
4143
- const customInstructions = isWorkflowSessionMode(record.sessionMode)
4144
- ? buildGoalCompactionInstructions(todoInstructions, deps.goalRegistry?.get(sessionId) ?? null)
4145
- : todoInstructions;
4063
+ const customInstructions = buildGoalCompactionInstructions(todoInstructions, deps.goalRegistry?.get(sessionId) ?? null);
4146
4064
  const turnId = deps.events.latestTurnId(sessionId) ?? `${sessionId}:compact`;
4147
4065
  const compactionId = `${sessionId}:compaction:${randomUUID()}`;
4148
4066
  deps.events.append(sessionId, turnId, {
@@ -4157,42 +4075,27 @@ export async function handleChatCompact(req, res, deps, sessionId) {
4157
4075
  });
4158
4076
  try {
4159
4077
  const snapshot = await deps.runtime.compact(sessionId, customInstructions);
4160
- const completedAt = new Date().toISOString();
4161
- const completedData = {
4162
- schemaVersion: 1,
4163
- compactionId,
4164
- reason: "manual",
4165
- status: "completed",
4166
- summary: snapshot.summary,
4167
- ...(snapshot.firstKeptEntryId
4168
- ? { firstKeptEntryId: snapshot.firstKeptEntryId }
4169
- : {}),
4170
- ...(snapshot.tokensBefore === undefined
4171
- ? {}
4172
- : { tokensBefore: snapshot.tokensBefore }),
4173
- ...(snapshot.estimatedTokensAfter === undefined
4174
- ? {}
4175
- : { estimatedTokensAfter: snapshot.estimatedTokensAfter }),
4176
- willRetry: false,
4177
- };
4178
4078
  const event = deps.events.append(sessionId, turnId, {
4179
4079
  kind: "compaction_end",
4180
- at: completedAt,
4181
- data: completedData,
4182
- });
4183
- sendJson(res, 200, {
4184
- ok: true,
4185
- snapshot,
4186
- eventId: event.eventId,
4187
- compaction: {
4188
- eventId: event.eventId,
4189
- kind: "compaction_end",
4190
- at: completedAt,
4191
- seq: event.seq,
4192
- turnId,
4193
- data: completedData,
4080
+ data: {
4081
+ schemaVersion: 1,
4082
+ compactionId,
4083
+ reason: "manual",
4084
+ status: "completed",
4085
+ summary: snapshot.summary,
4086
+ ...(snapshot.firstKeptEntryId
4087
+ ? { firstKeptEntryId: snapshot.firstKeptEntryId }
4088
+ : {}),
4089
+ ...(snapshot.tokensBefore === undefined
4090
+ ? {}
4091
+ : { tokensBefore: snapshot.tokensBefore }),
4092
+ ...(snapshot.estimatedTokensAfter === undefined
4093
+ ? {}
4094
+ : { estimatedTokensAfter: snapshot.estimatedTokensAfter }),
4095
+ willRetry: false,
4194
4096
  },
4195
4097
  });
4098
+ sendJson(res, 200, { ok: true, snapshot, eventId: event.eventId });
4196
4099
  }
4197
4100
  catch (error) {
4198
4101
  const classified = classifyChatCompactionFailure(error);
@@ -4243,51 +4146,6 @@ export async function handleChatMessages(res, deps, sessionId, url) {
4243
4146
  export async function handleChatRequest(req, res, deps, pathname, workspaceScope) {
4244
4147
  if (!deps)
4245
4148
  return false;
4246
- try {
4247
- return await dispatchChatRequest(req, res, deps, pathname, workspaceScope);
4248
- }
4249
- catch (error) {
4250
- // Store-level fail-closed for corrupt sessionMode: bounded 409 instead of
4251
- // a generic 500, for any handler that reads the record without its own
4252
- // UnknownChatSessionModeError mapping (readChatSessionMode covers the rest).
4253
- if (error instanceof UnknownChatSessionModeError) {
4254
- sendJson(res, 409, {
4255
- ok: false,
4256
- error: { code: error.code, message: error.message },
4257
- });
4258
- return true;
4259
- }
4260
- throw error;
4261
- }
4262
- }
4263
- async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
4264
- // Terminal management API (model + Console UI shared PTY registry).
4265
- if (await handleTerminalRequest(req, res, {
4266
- terminals: deps.terminals ?? new TerminalSessionRegistry(),
4267
- gateMutation: (r) => gateMutation(r, deps),
4268
- // Terminals open in the workspace repo root, not the Console process cwd.
4269
- defaultCwd: deps.appData.repoRoot,
4270
- }, pathname)) {
4271
- return true;
4272
- }
4273
- // Source control API (model + Console UI shared workspace ScmService).
4274
- if (deps.scm) {
4275
- if (await handleScmRequest(req, res, {
4276
- scm: deps.scm,
4277
- gateMutation: (r) => gateMutation(r, deps),
4278
- }, pathname)) {
4279
- return true;
4280
- }
4281
- }
4282
- // Browser probe API (read-only; explains iframe refusals to the panel).
4283
- if (await handleBrowserRequest(req, res, {
4284
- automation: deps.browserAutomation,
4285
- requireWorkspace: () => workspaceScope
4286
- ? { ok: true, workspaceId: workspaceScope }
4287
- : { ok: false },
4288
- }, pathname)) {
4289
- return true;
4290
- }
4291
4149
  if (!pathname.startsWith("/api/operator/v1/chat/") &&
4292
4150
  !pathname.startsWith("/api/operator/v1/pi/"))
4293
4151
  return false;
@@ -1,4 +1,4 @@
1
- import { createDecipheriv, randomBytes } from "node:crypto";
1
+ import { randomBytes } from "node:crypto";
2
2
  import { readFile, stat } from "node:fs/promises";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
@@ -10,49 +10,8 @@ export const SDD_SKILL_NAMES = [
10
10
  /** Backward-compatible name for callers that need a stable representative value. */
11
11
  export const SDD_DEFAULT_SKILL_NAME = "SDD-implementation-test-review";
12
12
  export const SDD_TELEMETRY_URL = "https://wizard-ai.paic.com.cn/code_pilot/api/skill-usage-log";
13
- /** SM4 key hex; also the SDD telemetry `ws-sign` value. */
14
- export const DEFAULT_AI_MA_PUB_SALT_KEY = "52aad0c09e6b46818a11ee702d6fe0ba";
15
- export const SDD_TELEMETRY_SIGN = DEFAULT_AI_MA_PUB_SALT_KEY;
16
- export const AIMAX_AUTH_TOKEN_ENV = "AIMAX_AUTH_TOKEN";
13
+ export const SDD_TELEMETRY_SIGN = "52aad0c09e6b46818a11ee702d6fe0ba";
17
14
  export const WIZARD_LOCAL_DEFAULT_USER_AGENT = "Builder/OpenCode ai-sdk/provider-utils/4.0.21 runtime/bun/1.3.11";
18
- const SM4_V1_PREFIX = "sm4:v1:";
19
- /** Decode a plaintext ticket or `sm4:v1:` ciphertext. Unknown prefixes and crypto errors fail closed. */
20
- export function decodeAimaxAuthToken(raw, keyHex = DEFAULT_AI_MA_PUB_SALT_KEY) {
21
- const candidate = raw.trim();
22
- if (!candidate)
23
- return undefined;
24
- if (!candidate.startsWith("sm4:"))
25
- return candidate;
26
- if (!candidate.startsWith(SM4_V1_PREFIX))
27
- return undefined;
28
- const hex = candidate.slice(SM4_V1_PREFIX.length);
29
- if (!hex || hex.length % 2 !== 0 || /[^0-9a-fA-F]/.test(hex))
30
- return undefined;
31
- const key = Buffer.from(keyHex.trim(), "hex");
32
- if (key.length !== 16)
33
- return undefined;
34
- try {
35
- const encrypted = Buffer.from(hex, "hex");
36
- if (encrypted.length === 0 || encrypted.length % 16 !== 0)
37
- return undefined;
38
- const decipher = createDecipheriv("sm4-ecb", key, null);
39
- decipher.setAutoPadding(true);
40
- const plain = Buffer.concat([decipher.update(encrypted), decipher.final()])
41
- .toString("utf8")
42
- .trim();
43
- return plain || undefined;
44
- }
45
- catch {
46
- return undefined;
47
- }
48
- }
49
- /** Set or delete `AIMAX_AUTH_TOKEN`. Empty string is treated as absent. */
50
- export function syncAimaxAuthTokenEnv(env, token) {
51
- if (token)
52
- env[AIMAX_AUTH_TOKEN_ENV] = token;
53
- else
54
- delete env[AIMAX_AUTH_TOKEN_ENV];
55
- }
56
15
  function sameAuthFileVersion(left, right) {
57
16
  if (!left.exists || !right.exists)
58
17
  return left.exists === right.exists;
@@ -62,22 +21,9 @@ function sameAuthFileVersion(left, right) {
62
21
  /** Reads ~/.aima-go/auth.json with metadata-based parse caching and fail-closed semantics. */
63
22
  export class AimaxAuthReader {
64
23
  authFile;
65
- env;
66
24
  cached;
67
- constructor(authFile = path.join(os.homedir(), ".aima-go", "auth.json"), env = process.env) {
25
+ constructor(authFile = path.join(os.homedir(), ".aima-go", "auth.json")) {
68
26
  this.authFile = authFile;
69
- this.env = env;
70
- }
71
- resolveKeyHex() {
72
- const injected = typeof this.env.AI_MA_PUB_SALT_KEY === "string" ? this.env.AI_MA_PUB_SALT_KEY.trim() : "";
73
- if (injected)
74
- return injected;
75
- const host = process.env.AI_MA_PUB_SALT_KEY?.trim();
76
- return host || DEFAULT_AI_MA_PUB_SALT_KEY;
77
- }
78
- finish(token) {
79
- syncAimaxAuthTokenEnv(this.env, token);
80
- return token;
81
27
  }
82
28
  async getToken() {
83
29
  let version;
@@ -88,24 +34,22 @@ export class AimaxAuthReader {
88
34
  }
89
35
  catch {
90
36
  this.cached = { version: { exists: false } };
91
- return this.finish(undefined);
92
- }
93
- if (this.cached && sameAuthFileVersion(this.cached.version, version)) {
94
- return this.finish(this.cached.token);
37
+ return undefined;
95
38
  }
39
+ if (this.cached && sameAuthFileVersion(this.cached.version, version))
40
+ return this.cached.token;
96
41
  let token;
97
42
  try {
98
43
  const parsed = JSON.parse(await readFile(this.authFile, "utf8"));
99
44
  const candidate = parsed["aimax-auth-token"];
100
- if (typeof candidate === "string" && candidate.trim()) {
101
- token = decodeAimaxAuthToken(candidate, this.resolveKeyHex());
102
- }
45
+ if (typeof candidate === "string" && candidate.trim())
46
+ token = candidate;
103
47
  }
104
48
  catch {
105
49
  // Malformed or unreadable files are intentionally ineligible.
106
50
  }
107
51
  this.cached = { version, ...(token ? { token } : {}) };
108
- return this.finish(token);
52
+ return token;
109
53
  }
110
54
  async isEligible() {
111
55
  return Boolean(await this.getToken());
@@ -1,36 +1,5 @@
1
1
  import { isBlankChatSession } from "./session-store.js";
2
2
  import { projectDeferredTurnSummaries, projectDeferredTurnSummary, } from "./deferred-turn.js";
3
- /** Sidebar / global GET /chat/sessions projection. Must include sessionMode. */
4
- export function projectChatSessionCatalogListItem(entry, active) {
5
- return {
6
- sessionId: entry.sessionId,
7
- ...(entry.workspaceId ? { workspaceId: entry.workspaceId } : {}),
8
- state: entry.state,
9
- createdAt: entry.createdAt,
10
- updatedAt: entry.updatedAt,
11
- ...(entry.title !== undefined ? { title: entry.title } : {}),
12
- ...(entry.displayTitle !== undefined
13
- ? { displayTitle: entry.displayTitle }
14
- : {}),
15
- ...(entry.modelProvider !== undefined
16
- ? { modelProvider: entry.modelProvider }
17
- : {}),
18
- ...(entry.modelId !== undefined ? { modelId: entry.modelId } : {}),
19
- ...(entry.thinkingLevel !== undefined
20
- ? { thinkingLevel: entry.thinkingLevel }
21
- : {}),
22
- sessionMode: entry.sessionMode,
23
- activeTurnId: active?.turnId,
24
- turnPhase: active?.abortRequestedAt
25
- ? "stopping"
26
- : active
27
- ? "running"
28
- : "idle",
29
- deferredTurn: entry.deferredTurn,
30
- deferredTurns: entry.deferredTurns,
31
- isBlank: entry.isBlank && !active,
32
- };
33
- }
34
3
  /**
35
4
  * Process-wide Session baseline, mirroring DSH's independent session.list.
36
5
  * Full records stay in their fingerprint-isolated stores; this catalog only
@@ -67,7 +36,6 @@ export class ChatSessionCatalog {
67
36
  deferredTurns: projectDeferredTurnSummaries(record.deferredTurns ?? []),
68
37
  isBlank: isBlankChatSession(record),
69
38
  ...(workspaceId ? { workspaceId } : {}),
70
- sessionMode: record.sessionMode,
71
39
  });
72
40
  }
73
41
  remove(sessionId) {