factory-factory 0.3.7 → 0.3.9

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 (553) hide show
  1. package/dist/client/assets/{_basePickBy-BsuMuaCZ.js → _basePickBy-CoLLbaiQ.js} +1 -1
  2. package/dist/client/assets/{_baseUniq-BDd8f52s.js → _baseUniq-xRgxfXUW.js} +1 -1
  3. package/dist/client/assets/{arc-BWbaJQoA.js → arc-De4Ny3V9.js} +1 -1
  4. package/dist/client/assets/{architectureDiagram-VXUJARFQ-C_FQG3JS.js → architectureDiagram-VXUJARFQ-DM0j158z.js} +1 -1
  5. package/dist/client/assets/{blockDiagram-VD42YOAC-CLwvH-wA.js → blockDiagram-VD42YOAC-DKBZN-sz.js} +1 -1
  6. package/dist/client/assets/{c4Diagram-YG6GDRKO-Ba80_haP.js → c4Diagram-YG6GDRKO-CIA6AVRp.js} +1 -1
  7. package/dist/client/assets/channel-DW2o9xrZ.js +1 -0
  8. package/dist/client/assets/{chunk-4BX2VUAB-CSlDSMiy.js → chunk-4BX2VUAB-BrHsCtgI.js} +1 -1
  9. package/dist/client/assets/{chunk-55IACEB6-Dm3keBAf.js → chunk-55IACEB6-DLwlJB2L.js} +1 -1
  10. package/dist/client/assets/{chunk-B4BG7PRW-BSrvNYuP.js → chunk-B4BG7PRW-cqTY9ldj.js} +1 -1
  11. package/dist/client/assets/{chunk-DI55MBZ5-DFQPoLQZ.js → chunk-DI55MBZ5-PAp7fYLU.js} +1 -1
  12. package/dist/client/assets/{chunk-FMBD7UC4-C1KS438H.js → chunk-FMBD7UC4-CsvpScij.js} +1 -1
  13. package/dist/client/assets/{chunk-QN33PNHL-4rPPxHo4.js → chunk-QN33PNHL-DmkkCoc-.js} +1 -1
  14. package/dist/client/assets/{chunk-QZHKN3VN-B_sF5IzV.js → chunk-QZHKN3VN-Ds5Tjlpo.js} +1 -1
  15. package/dist/client/assets/{chunk-TZMSLE5B-L-qbjoBp.js → chunk-TZMSLE5B-4Gu0uKkR.js} +1 -1
  16. package/dist/client/assets/classDiagram-2ON5EDUG-CUeZuC6S.js +1 -0
  17. package/dist/client/assets/classDiagram-v2-WZHVMYZB-CUeZuC6S.js +1 -0
  18. package/dist/client/assets/clone-Df9JDgIw.js +1 -0
  19. package/dist/client/assets/{cose-bilkent-S5V4N54A-DB7lwAnl.js → cose-bilkent-S5V4N54A-CQJ_MgcD.js} +1 -1
  20. package/dist/client/assets/{dagre-6UL2VRFP-z2fl_1iD.js → dagre-6UL2VRFP-CfyncTju.js} +1 -1
  21. package/dist/client/assets/{diagram-PSM6KHXK-BL2iv8II.js → diagram-PSM6KHXK-BL2QA0bQ.js} +1 -1
  22. package/dist/client/assets/{diagram-QEK2KX5R-DgMZW0D1.js → diagram-QEK2KX5R-BDcBrJO4.js} +1 -1
  23. package/dist/client/assets/{diagram-S2PKOQOG-Ct2QBl2c.js → diagram-S2PKOQOG-BxofoMik.js} +1 -1
  24. package/dist/client/assets/{erDiagram-Q2GNP2WA-DII-pqkb.js → erDiagram-Q2GNP2WA-CDGe-bUA.js} +1 -1
  25. package/dist/client/assets/{flowDiagram-NV44I4VS-BV4CMZAZ.js → flowDiagram-NV44I4VS-CodDw20I.js} +1 -1
  26. package/dist/client/assets/{ganttDiagram-JELNMOA3-Dfj064tE.js → ganttDiagram-JELNMOA3-BHJlNcF5.js} +1 -1
  27. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-Cg2b-j3t.js → gitGraphDiagram-V2S2FVAM-DsFPFnxn.js} +1 -1
  28. package/dist/client/assets/{graph-wzICjOO_.js → graph-DtyTGYVa.js} +1 -1
  29. package/dist/client/assets/index-BkwQogmx.css +1 -0
  30. package/dist/client/assets/index-CSanKe06.js +436 -0
  31. package/dist/client/assets/{infoDiagram-HS3SLOUP-D09mbfgG.js → infoDiagram-HS3SLOUP-CczckdeY.js} +1 -1
  32. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-BebsQbuf.js → journeyDiagram-XKPGCS4Q-CIDlGmYi.js} +1 -1
  33. package/dist/client/assets/{kanban-definition-3W4ZIXB7-DOuawTNU.js → kanban-definition-3W4ZIXB7-Dvuu9eqr.js} +1 -1
  34. package/dist/client/assets/{layout-Bj6cMfF5.js → layout-Cth5sJm6.js} +1 -1
  35. package/dist/client/assets/{linear-B58HS9F4.js → linear-DRv-Y17x.js} +1 -1
  36. package/dist/client/assets/{mindmap-definition-VGOIOE7T-hSFgcTL2.js → mindmap-definition-VGOIOE7T-AXsc24V4.js} +1 -1
  37. package/dist/client/assets/{mobile-baseline-CmdjqYSm.js → mobile-baseline-DXBPdrir.js} +1 -1
  38. package/dist/client/assets/{pieDiagram-ADFJNKIX-D1vkoKs3.js → pieDiagram-ADFJNKIX-oIn8Bgi4.js} +1 -1
  39. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-pMQj9xcS.js → quadrantDiagram-AYHSOK5B-rGTqNh3q.js} +1 -1
  40. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-DvRtxnIi.js → requirementDiagram-UZGBJVZJ-DgE2dYES.js} +1 -1
  41. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-BWoDxXkR.js → sankeyDiagram-TZEHDZUN-BWRLa217.js} +1 -1
  42. package/dist/client/assets/{sequenceDiagram-WL72ISMW-Dz5i1ly3.js → sequenceDiagram-WL72ISMW-lYEkh9VX.js} +1 -1
  43. package/dist/client/assets/{stateDiagram-FKZM4ZOC-BFd_gXUo.js → stateDiagram-FKZM4ZOC-CV9VCuVK.js} +1 -1
  44. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-DQ10FejB.js +1 -0
  45. package/dist/client/assets/{terminal-instance-BTIzq32H.js → terminal-instance-C3nwiweh.js} +1 -1
  46. package/dist/client/assets/{timeline-definition-IT6M3QCI-BFEIWW6m.js → timeline-definition-IT6M3QCI-Bzm_qoWF.js} +1 -1
  47. package/dist/client/assets/{treemap-GDKQZRPO-CC2Fh6RQ.js → treemap-GDKQZRPO-gouxKMUq.js} +1 -1
  48. package/dist/client/assets/{xychartDiagram-PRI3JC2R-DFygXQrm.js → xychartDiagram-PRI3JC2R-DqSTMw-l.js} +1 -1
  49. package/dist/client/index.html +2 -2
  50. package/dist/prisma/generated/enums.d.ts +1 -0
  51. package/dist/prisma/generated/enums.d.ts.map +1 -1
  52. package/dist/prisma/generated/enums.js +1 -0
  53. package/dist/prisma/generated/enums.js.map +1 -1
  54. package/dist/prisma/generated/internal/class.js +4 -4
  55. package/dist/prisma/generated/internal/class.js.map +1 -1
  56. package/dist/prisma/generated/internal/prismaNamespace.d.ts +1 -0
  57. package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
  58. package/dist/prisma/generated/internal/prismaNamespace.js +1 -0
  59. package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
  60. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +1 -0
  61. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
  62. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +1 -0
  63. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  64. package/dist/prisma/generated/models/Workspace.d.ts +44 -1
  65. package/dist/prisma/generated/models/Workspace.d.ts.map +1 -1
  66. package/dist/src/backend/app-context.d.ts +2 -1
  67. package/dist/src/backend/app-context.d.ts.map +1 -1
  68. package/dist/src/backend/app-context.js +22 -5
  69. package/dist/src/backend/app-context.js.map +1 -1
  70. package/dist/src/backend/domains/github/github-cli/mappers.d.ts +1 -1
  71. package/dist/src/backend/domains/github/github-cli/mappers.d.ts.map +1 -1
  72. package/dist/src/backend/domains/github/github-cli/mappers.js +2 -37
  73. package/dist/src/backend/domains/github/github-cli/mappers.js.map +1 -1
  74. package/dist/src/backend/domains/github/github-cli.service.test.js +20 -0
  75. package/dist/src/backend/domains/github/github-cli.service.test.js.map +1 -1
  76. package/dist/src/backend/domains/linear/linear-state-sync.service.d.ts.map +1 -1
  77. package/dist/src/backend/domains/linear/linear-state-sync.service.js.map +1 -1
  78. package/dist/src/backend/domains/ratchet/bridges.d.ts +4 -0
  79. package/dist/src/backend/domains/ratchet/bridges.d.ts.map +1 -1
  80. package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.d.ts +15 -0
  81. package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.d.ts.map +1 -0
  82. package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.js +126 -0
  83. package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.js.map +1 -0
  84. package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.d.ts +14 -0
  85. package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.d.ts.map +1 -0
  86. package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.js +55 -0
  87. package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.js.map +1 -0
  88. package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.d.ts +107 -0
  89. package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.d.ts.map +1 -0
  90. package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.js +246 -0
  91. package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.js.map +1 -0
  92. package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.d.ts +16 -0
  93. package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.d.ts.map +1 -0
  94. package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.js +52 -0
  95. package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.js.map +1 -0
  96. package/dist/src/backend/domains/ratchet/ratchet.service.d.ts +6 -40
  97. package/dist/src/backend/domains/ratchet/ratchet.service.d.ts.map +1 -1
  98. package/dist/src/backend/domains/ratchet/ratchet.service.js +99 -426
  99. package/dist/src/backend/domains/ratchet/ratchet.service.js.map +1 -1
  100. package/dist/src/backend/domains/ratchet/ratchet.types.d.ts +86 -0
  101. package/dist/src/backend/domains/ratchet/ratchet.types.d.ts.map +1 -0
  102. package/dist/src/backend/domains/ratchet/ratchet.types.js +2 -0
  103. package/dist/src/backend/domains/ratchet/ratchet.types.js.map +1 -0
  104. package/dist/src/backend/domains/ratchet/reconciliation.service.d.ts.map +1 -1
  105. package/dist/src/backend/domains/ratchet/reconciliation.service.js +1 -2
  106. package/dist/src/backend/domains/ratchet/reconciliation.service.js.map +1 -1
  107. package/dist/src/backend/domains/ratchet/reconciliation.service.test.js +8 -10
  108. package/dist/src/backend/domains/ratchet/reconciliation.service.test.js.map +1 -1
  109. package/dist/src/backend/domains/run-script/index.d.ts +1 -1
  110. package/dist/src/backend/domains/run-script/index.d.ts.map +1 -1
  111. package/dist/src/backend/domains/run-script/index.js +1 -1
  112. package/dist/src/backend/domains/run-script/index.js.map +1 -1
  113. package/dist/src/backend/domains/run-script/run-script-domain-exports.test.js +5 -4
  114. package/dist/src/backend/domains/run-script/run-script-domain-exports.test.js.map +1 -1
  115. package/dist/src/backend/domains/run-script/run-script.service.d.ts +13 -1
  116. package/dist/src/backend/domains/run-script/run-script.service.d.ts.map +1 -1
  117. package/dist/src/backend/domains/run-script/run-script.service.js +175 -10
  118. package/dist/src/backend/domains/run-script/run-script.service.js.map +1 -1
  119. package/dist/src/backend/domains/run-script/run-script.service.test.js +204 -0
  120. package/dist/src/backend/domains/run-script/run-script.service.test.js.map +1 -1
  121. package/dist/src/backend/domains/session/acp/acp-event-translator.d.ts +13 -1
  122. package/dist/src/backend/domains/session/acp/acp-event-translator.d.ts.map +1 -1
  123. package/dist/src/backend/domains/session/acp/acp-event-translator.js +86 -1
  124. package/dist/src/backend/domains/session/acp/acp-event-translator.js.map +1 -1
  125. package/dist/src/backend/domains/session/acp/acp-event-translator.test.js +39 -0
  126. package/dist/src/backend/domains/session/acp/acp-event-translator.test.js.map +1 -1
  127. package/dist/src/backend/domains/session/acp/acp-runtime-manager.d.ts +5 -0
  128. package/dist/src/backend/domains/session/acp/acp-runtime-manager.d.ts.map +1 -1
  129. package/dist/src/backend/domains/session/acp/acp-runtime-manager.js +16 -13
  130. package/dist/src/backend/domains/session/acp/acp-runtime-manager.js.map +1 -1
  131. package/dist/src/backend/domains/session/acp/acp-runtime-manager.test.js +3 -12
  132. package/dist/src/backend/domains/session/acp/acp-runtime-manager.test.js.map +1 -1
  133. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.d.ts +24 -0
  134. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.d.ts.map +1 -0
  135. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.js +79 -0
  136. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.js.map +1 -0
  137. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.d.ts +97 -0
  138. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.d.ts.map +1 -0
  139. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.js +2 -0
  140. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.js.map +1 -0
  141. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts +17 -39
  142. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts.map +1 -1
  143. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js +109 -1694
  144. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js.map +1 -1
  145. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.test.js +0 -191
  146. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.test.js.map +1 -1
  147. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-zod.d.ts +3 -3
  148. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.d.ts +16 -0
  149. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.d.ts.map +1 -0
  150. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.js +292 -0
  151. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.js.map +1 -0
  152. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.d.ts +2 -0
  153. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.d.ts.map +1 -0
  154. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.js +56 -0
  155. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.js.map +1 -0
  156. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.d.ts +19 -0
  157. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.d.ts.map +1 -0
  158. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.js +369 -0
  159. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.js.map +1 -0
  160. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.d.ts +2 -0
  161. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.d.ts.map +1 -0
  162. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.js +91 -0
  163. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.js.map +1 -0
  164. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.d.ts +16 -0
  165. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.d.ts.map +1 -0
  166. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.js +53 -0
  167. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.js.map +1 -0
  168. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.d.ts +20 -0
  169. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.d.ts.map +1 -0
  170. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.js +341 -0
  171. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.js.map +1 -0
  172. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.d.ts +41 -0
  173. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.d.ts.map +1 -0
  174. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.js +137 -0
  175. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.js.map +1 -0
  176. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.d.ts +25 -0
  177. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.d.ts.map +1 -0
  178. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.js +47 -0
  179. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.js.map +1 -0
  180. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.d.ts +8 -0
  181. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.d.ts.map +1 -0
  182. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.js +37 -0
  183. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.js.map +1 -0
  184. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.d.ts +53 -0
  185. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.d.ts.map +1 -0
  186. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.js +419 -0
  187. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.js.map +1 -0
  188. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.d.ts +2 -0
  189. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.d.ts.map +1 -0
  190. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.js +95 -0
  191. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.js.map +1 -0
  192. package/dist/src/backend/domains/session/acp/index.d.ts +1 -1
  193. package/dist/src/backend/domains/session/acp/index.d.ts.map +1 -1
  194. package/dist/src/backend/domains/session/acp/index.js +1 -1
  195. package/dist/src/backend/domains/session/acp/index.js.map +1 -1
  196. package/dist/src/backend/domains/session/bridges.d.ts +5 -0
  197. package/dist/src/backend/domains/session/bridges.d.ts.map +1 -1
  198. package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.d.ts.map +1 -1
  199. package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.js +2 -2
  200. package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.js.map +1 -1
  201. package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.test.js +1 -1
  202. package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.test.js.map +1 -1
  203. package/dist/src/backend/domains/session/chat/chat-message-handlers.service.js +2 -2
  204. package/dist/src/backend/domains/session/chat/chat-message-handlers.service.js.map +1 -1
  205. package/dist/src/backend/domains/session/data/codex-session-history-loader.service.d.ts.map +1 -1
  206. package/dist/src/backend/domains/session/data/codex-session-history-loader.service.js +77 -24
  207. package/dist/src/backend/domains/session/data/codex-session-history-loader.service.js.map +1 -1
  208. package/dist/src/backend/domains/session/data/session-data.service.d.ts +2 -0
  209. package/dist/src/backend/domains/session/data/session-data.service.d.ts.map +1 -1
  210. package/dist/src/backend/domains/session/data/{claude-session-history-loader.service.d.ts → session-history-loader.service.d.ts} +1 -1
  211. package/dist/src/backend/domains/session/data/session-history-loader.service.d.ts.map +1 -0
  212. package/dist/src/backend/domains/session/data/{claude-session-history-loader.service.js → session-history-loader.service.js} +23 -9
  213. package/dist/src/backend/domains/session/data/session-history-loader.service.js.map +1 -0
  214. package/dist/src/backend/domains/session/data/session-history-loader.service.test.d.ts +2 -0
  215. package/dist/src/backend/domains/session/data/session-history-loader.service.test.d.ts.map +1 -0
  216. package/dist/src/backend/domains/session/data/{claude-session-history-loader.service.test.js → session-history-loader.service.test.js} +6 -3
  217. package/dist/src/backend/domains/session/data/session-history-loader.service.test.js.map +1 -0
  218. package/dist/src/backend/domains/session/index.d.ts +3 -1
  219. package/dist/src/backend/domains/session/index.d.ts.map +1 -1
  220. package/dist/src/backend/domains/session/index.js +2 -1
  221. package/dist/src/backend/domains/session/index.js.map +1 -1
  222. package/dist/src/backend/domains/session/interceptor.bridge.d.ts +8 -0
  223. package/dist/src/backend/domains/session/interceptor.bridge.d.ts.map +1 -0
  224. package/dist/src/backend/domains/session/interceptor.bridge.js +7 -0
  225. package/dist/src/backend/domains/session/interceptor.bridge.js.map +1 -0
  226. package/dist/src/backend/domains/session/lifecycle/acp-event-processor.d.ts +71 -0
  227. package/dist/src/backend/domains/session/lifecycle/acp-event-processor.d.ts.map +1 -0
  228. package/dist/src/backend/domains/session/lifecycle/acp-event-processor.js +404 -0
  229. package/dist/src/backend/domains/session/lifecycle/acp-event-processor.js.map +1 -0
  230. package/dist/src/backend/domains/session/lifecycle/session.config.service.d.ts +59 -0
  231. package/dist/src/backend/domains/session/lifecycle/session.config.service.d.ts.map +1 -0
  232. package/dist/src/backend/domains/session/lifecycle/session.config.service.js +635 -0
  233. package/dist/src/backend/domains/session/lifecycle/session.config.service.js.map +1 -0
  234. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.d.ts +2 -0
  235. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.d.ts.map +1 -0
  236. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.js +552 -0
  237. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.js.map +1 -0
  238. package/dist/src/backend/domains/session/lifecycle/session.permission.service.d.ts +17 -0
  239. package/dist/src/backend/domains/session/lifecycle/session.permission.service.d.ts.map +1 -0
  240. package/dist/src/backend/domains/session/lifecycle/session.permission.service.js +86 -0
  241. package/dist/src/backend/domains/session/lifecycle/session.permission.service.js.map +1 -0
  242. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.d.ts +2 -0
  243. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.d.ts.map +1 -0
  244. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.js +137 -0
  245. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.js.map +1 -0
  246. package/dist/src/backend/domains/session/lifecycle/session.repository.d.ts +0 -2
  247. package/dist/src/backend/domains/session/lifecycle/session.repository.d.ts.map +1 -1
  248. package/dist/src/backend/domains/session/lifecycle/session.repository.js +0 -3
  249. package/dist/src/backend/domains/session/lifecycle/session.repository.js.map +1 -1
  250. package/dist/src/backend/domains/session/lifecycle/session.repository.test.js +0 -1
  251. package/dist/src/backend/domains/session/lifecycle/session.repository.test.js.map +1 -1
  252. package/dist/src/backend/domains/session/lifecycle/session.service.d.ts +24 -56
  253. package/dist/src/backend/domains/session/lifecycle/session.service.d.ts.map +1 -1
  254. package/dist/src/backend/domains/session/lifecycle/session.service.js +140 -1083
  255. package/dist/src/backend/domains/session/lifecycle/session.service.js.map +1 -1
  256. package/dist/src/backend/domains/session/lifecycle/session.service.test.js +62 -689
  257. package/dist/src/backend/domains/session/lifecycle/session.service.test.js.map +1 -1
  258. package/dist/src/backend/domains/session/logging/acp-trace-logger.service.d.ts.map +1 -1
  259. package/dist/src/backend/domains/session/logging/acp-trace-logger.service.js +2 -13
  260. package/dist/src/backend/domains/session/logging/acp-trace-logger.service.js.map +1 -1
  261. package/dist/src/backend/domains/session/logging/acp-trace-logger.service.test.js +15 -3
  262. package/dist/src/backend/domains/session/logging/acp-trace-logger.service.test.js.map +1 -1
  263. package/dist/src/backend/domains/session/logging/session-file-logger.service.js +1 -1
  264. package/dist/src/backend/domains/session/logging/session-file-logger.service.js.map +1 -1
  265. package/dist/src/backend/domains/session/logging/session-file-logger.service.test.js +3 -0
  266. package/dist/src/backend/domains/session/logging/session-file-logger.service.test.js.map +1 -1
  267. package/dist/src/backend/domains/session/session-domain.service.d.ts +1 -2
  268. package/dist/src/backend/domains/session/session-domain.service.d.ts.map +1 -1
  269. package/dist/src/backend/domains/session/session-domain.service.js +21 -2
  270. package/dist/src/backend/domains/session/session-domain.service.js.map +1 -1
  271. package/dist/src/backend/domains/session/session-domain.service.test.js +34 -0
  272. package/dist/src/backend/domains/session/session-domain.service.test.js.map +1 -1
  273. package/dist/src/backend/domains/session/store/file-lock.service.d.ts.map +1 -1
  274. package/dist/src/backend/domains/session/store/file-lock.service.js +25 -6
  275. package/dist/src/backend/domains/session/store/file-lock.service.js.map +1 -1
  276. package/dist/src/backend/domains/session/store/file-lock.service.test.js +3 -0
  277. package/dist/src/backend/domains/session/store/file-lock.service.test.js.map +1 -1
  278. package/dist/src/backend/domains/session/zod-issue-summary.d.ts +3 -0
  279. package/dist/src/backend/domains/session/zod-issue-summary.d.ts.map +1 -0
  280. package/dist/src/backend/domains/session/zod-issue-summary.js +7 -0
  281. package/dist/src/backend/domains/session/zod-issue-summary.js.map +1 -0
  282. package/dist/src/backend/domains/workspace/index.d.ts +0 -1
  283. package/dist/src/backend/domains/workspace/index.d.ts.map +1 -1
  284. package/dist/src/backend/domains/workspace/index.js +0 -1
  285. package/dist/src/backend/domains/workspace/index.js.map +1 -1
  286. package/dist/src/backend/domains/workspace/lifecycle/creation.service.d.ts +7 -0
  287. package/dist/src/backend/domains/workspace/lifecycle/creation.service.d.ts.map +1 -1
  288. package/dist/src/backend/domains/workspace/lifecycle/creation.service.js +98 -85
  289. package/dist/src/backend/domains/workspace/lifecycle/creation.service.js.map +1 -1
  290. package/dist/src/backend/domains/workspace/lifecycle/creation.service.test.js +41 -1
  291. package/dist/src/backend/domains/workspace/lifecycle/creation.service.test.js.map +1 -1
  292. package/dist/src/backend/domains/workspace/lifecycle/data.service.d.ts +9 -1
  293. package/dist/src/backend/domains/workspace/lifecycle/data.service.d.ts.map +1 -1
  294. package/dist/src/backend/domains/workspace/lifecycle/data.service.js +2 -1
  295. package/dist/src/backend/domains/workspace/lifecycle/data.service.js.map +1 -1
  296. package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.d.ts +8 -0
  297. package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.d.ts.map +1 -1
  298. package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.js +47 -5
  299. package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.js.map +1 -1
  300. package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.test.js +117 -22
  301. package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.test.js.map +1 -1
  302. package/dist/src/backend/domains/workspace/query/project-management.service.d.ts +2 -0
  303. package/dist/src/backend/domains/workspace/query/project-management.service.d.ts.map +1 -1
  304. package/dist/src/backend/domains/workspace/query/workspace-query.service.d.ts +4 -1
  305. package/dist/src/backend/domains/workspace/query/workspace-query.service.d.ts.map +1 -1
  306. package/dist/src/backend/domains/workspace/query/workspace-query.service.js +51 -36
  307. package/dist/src/backend/domains/workspace/query/workspace-query.service.js.map +1 -1
  308. package/dist/src/backend/domains/workspace/query/workspace-query.service.test.js +141 -44
  309. package/dist/src/backend/domains/workspace/query/workspace-query.service.test.js.map +1 -1
  310. package/dist/src/backend/domains/workspace/state/flow-state.d.ts +2 -2
  311. package/dist/src/backend/domains/workspace/state/flow-state.d.ts.map +1 -1
  312. package/dist/src/backend/domains/workspace/state/flow-state.js.map +1 -1
  313. package/dist/src/backend/domains/workspace/state/init-policy.js +1 -1
  314. package/dist/src/backend/domains/workspace/state/init-policy.js.map +1 -1
  315. package/dist/src/backend/domains/workspace/state/kanban-state.d.ts +2 -1
  316. package/dist/src/backend/domains/workspace/state/kanban-state.d.ts.map +1 -1
  317. package/dist/src/backend/domains/workspace/state/kanban-state.js +9 -5
  318. package/dist/src/backend/domains/workspace/state/kanban-state.js.map +1 -1
  319. package/dist/src/backend/domains/workspace/state/kanban-state.test.js +23 -0
  320. package/dist/src/backend/domains/workspace/state/kanban-state.test.js.map +1 -1
  321. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.d.ts +3 -6
  322. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.d.ts.map +1 -1
  323. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.js +7 -116
  324. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.js.map +1 -1
  325. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.test.js +38 -65
  326. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.test.js.map +1 -1
  327. package/dist/src/backend/interceptors/conversation-rename.interceptor.d.ts.map +1 -1
  328. package/dist/src/backend/interceptors/conversation-rename.interceptor.js +22 -6
  329. package/dist/src/backend/interceptors/conversation-rename.interceptor.js.map +1 -1
  330. package/dist/src/backend/interceptors/conversation-rename.interceptor.test.js +25 -13
  331. package/dist/src/backend/interceptors/conversation-rename.interceptor.test.js.map +1 -1
  332. package/dist/src/backend/interceptors/index.d.ts +2 -0
  333. package/dist/src/backend/interceptors/index.d.ts.map +1 -1
  334. package/dist/src/backend/interceptors/index.js +6 -0
  335. package/dist/src/backend/interceptors/index.js.map +1 -1
  336. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.d.ts.map +1 -1
  337. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js +8 -0
  338. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js.map +1 -1
  339. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js +5 -1
  340. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js.map +1 -1
  341. package/dist/src/backend/interceptors/pre-push-rename.interceptor.d.ts.map +1 -1
  342. package/dist/src/backend/interceptors/pre-push-rename.interceptor.js +3 -0
  343. package/dist/src/backend/interceptors/pre-push-rename.interceptor.js.map +1 -1
  344. package/dist/src/backend/interceptors/registry.d.ts +5 -0
  345. package/dist/src/backend/interceptors/registry.d.ts.map +1 -1
  346. package/dist/src/backend/interceptors/registry.js +51 -0
  347. package/dist/src/backend/interceptors/registry.js.map +1 -1
  348. package/dist/src/backend/interceptors/types.d.ts +2 -0
  349. package/dist/src/backend/interceptors/types.d.ts.map +1 -1
  350. package/dist/src/backend/lib/file-helpers.d.ts +2 -0
  351. package/dist/src/backend/lib/file-helpers.d.ts.map +1 -1
  352. package/dist/src/backend/lib/file-helpers.js +64 -1
  353. package/dist/src/backend/lib/file-helpers.js.map +1 -1
  354. package/dist/src/backend/lib/workspace-derived-state.d.ts +47 -0
  355. package/dist/src/backend/lib/workspace-derived-state.d.ts.map +1 -0
  356. package/dist/src/backend/lib/workspace-derived-state.js +31 -0
  357. package/dist/src/backend/lib/workspace-derived-state.js.map +1 -0
  358. package/dist/src/backend/lib/workspace-derived-state.test.d.ts +2 -0
  359. package/dist/src/backend/lib/workspace-derived-state.test.d.ts.map +1 -0
  360. package/dist/src/backend/lib/workspace-derived-state.test.js +66 -0
  361. package/dist/src/backend/lib/workspace-derived-state.test.js.map +1 -0
  362. package/dist/src/backend/middleware/cors.middleware.d.ts +1 -2
  363. package/dist/src/backend/middleware/cors.middleware.d.ts.map +1 -1
  364. package/dist/src/backend/middleware/cors.middleware.js +0 -2
  365. package/dist/src/backend/middleware/cors.middleware.js.map +1 -1
  366. package/dist/src/backend/middleware/index.d.ts +1 -1
  367. package/dist/src/backend/middleware/index.d.ts.map +1 -1
  368. package/dist/src/backend/middleware/index.js +1 -1
  369. package/dist/src/backend/middleware/index.js.map +1 -1
  370. package/dist/src/backend/orchestration/data-backup.service.test.js +1 -0
  371. package/dist/src/backend/orchestration/data-backup.service.test.js.map +1 -1
  372. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts +26 -1
  373. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
  374. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +24 -1
  375. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
  376. package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js +19 -1
  377. package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js.map +1 -1
  378. package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts +8 -1
  379. package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts.map +1 -1
  380. package/dist/src/backend/orchestration/event-collector.orchestrator.js +41 -21
  381. package/dist/src/backend/orchestration/event-collector.orchestrator.js.map +1 -1
  382. package/dist/src/backend/orchestration/event-collector.orchestrator.test.js +19 -4
  383. package/dist/src/backend/orchestration/event-collector.orchestrator.test.js.map +1 -1
  384. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts +6 -2
  385. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts.map +1 -1
  386. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js +8 -3
  387. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js.map +1 -1
  388. package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts +19 -1
  389. package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts.map +1 -1
  390. package/dist/src/backend/orchestration/workspace-archive.orchestrator.js +21 -13
  391. package/dist/src/backend/orchestration/workspace-archive.orchestrator.js.map +1 -1
  392. package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js +103 -77
  393. package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js.map +1 -1
  394. package/dist/src/backend/orchestration/workspace-init-script-pipeline.d.ts +18 -0
  395. package/dist/src/backend/orchestration/workspace-init-script-pipeline.d.ts.map +1 -0
  396. package/dist/src/backend/orchestration/workspace-init-script-pipeline.js +75 -0
  397. package/dist/src/backend/orchestration/workspace-init-script-pipeline.js.map +1 -0
  398. package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts.map +1 -1
  399. package/dist/src/backend/orchestration/workspace-init.orchestrator.js +105 -106
  400. package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
  401. package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js +137 -18
  402. package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js.map +1 -1
  403. package/dist/src/backend/resource_accessors/project.accessor.js +1 -1
  404. package/dist/src/backend/resource_accessors/project.accessor.js.map +1 -1
  405. package/dist/src/backend/resource_accessors/workspace.accessor.d.ts +1 -0
  406. package/dist/src/backend/resource_accessors/workspace.accessor.d.ts.map +1 -1
  407. package/dist/src/backend/resource_accessors/workspace.accessor.js.map +1 -1
  408. package/dist/src/backend/routers/websocket/index.d.ts +1 -0
  409. package/dist/src/backend/routers/websocket/index.d.ts.map +1 -1
  410. package/dist/src/backend/routers/websocket/index.js +1 -0
  411. package/dist/src/backend/routers/websocket/index.js.map +1 -1
  412. package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts +9 -0
  413. package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts.map +1 -0
  414. package/dist/src/backend/routers/websocket/post-run-logs.handler.js +52 -0
  415. package/dist/src/backend/routers/websocket/post-run-logs.handler.js.map +1 -0
  416. package/dist/src/backend/routers/websocket/snapshots.handler.d.ts.map +1 -1
  417. package/dist/src/backend/routers/websocket/snapshots.handler.js +17 -6
  418. package/dist/src/backend/routers/websocket/snapshots.handler.js.map +1 -1
  419. package/dist/src/backend/routers/websocket/snapshots.handler.test.js +40 -5
  420. package/dist/src/backend/routers/websocket/snapshots.handler.test.js.map +1 -1
  421. package/dist/src/backend/routers/websocket/websocket.integration.test.js +1 -0
  422. package/dist/src/backend/routers/websocket/websocket.integration.test.js.map +1 -1
  423. package/dist/src/backend/server.d.ts.map +1 -1
  424. package/dist/src/backend/server.js +16 -6
  425. package/dist/src/backend/server.js.map +1 -1
  426. package/dist/src/backend/server.upgrade.test.js +4 -0
  427. package/dist/src/backend/server.upgrade.test.js.map +1 -1
  428. package/dist/src/backend/services/check-single-writer.test.d.ts +2 -0
  429. package/dist/src/backend/services/check-single-writer.test.d.ts.map +1 -0
  430. package/dist/src/backend/services/check-single-writer.test.js +132 -0
  431. package/dist/src/backend/services/check-single-writer.test.js.map +1 -0
  432. package/dist/src/backend/services/config.service.d.ts +14 -6
  433. package/dist/src/backend/services/config.service.d.ts.map +1 -1
  434. package/dist/src/backend/services/config.service.js +31 -9
  435. package/dist/src/backend/services/config.service.js.map +1 -1
  436. package/dist/src/backend/services/env-schemas.d.ts +7 -3
  437. package/dist/src/backend/services/env-schemas.d.ts.map +1 -1
  438. package/dist/src/backend/services/env-schemas.js +19 -3
  439. package/dist/src/backend/services/env-schemas.js.map +1 -1
  440. package/dist/src/backend/services/run-script-config-persistence.service.d.ts +37 -0
  441. package/dist/src/backend/services/run-script-config-persistence.service.d.ts.map +1 -0
  442. package/dist/src/backend/services/run-script-config-persistence.service.js +73 -0
  443. package/dist/src/backend/services/run-script-config-persistence.service.js.map +1 -0
  444. package/dist/src/backend/services/run-script-config-persistence.service.test.d.ts +2 -0
  445. package/dist/src/backend/services/run-script-config-persistence.service.test.d.ts.map +1 -0
  446. package/dist/src/backend/services/run-script-config-persistence.service.test.js +111 -0
  447. package/dist/src/backend/services/run-script-config-persistence.service.test.js.map +1 -0
  448. package/dist/src/backend/services/run-script-proxy.service.d.ts.map +1 -1
  449. package/dist/src/backend/services/run-script-proxy.service.js +2 -1
  450. package/dist/src/backend/services/run-script-proxy.service.js.map +1 -1
  451. package/dist/src/backend/services/run-script-proxy.service.test.js +4 -0
  452. package/dist/src/backend/services/run-script-proxy.service.test.js.map +1 -1
  453. package/dist/src/backend/services/workspace-snapshot-store.service.d.ts +5 -3
  454. package/dist/src/backend/services/workspace-snapshot-store.service.d.ts.map +1 -1
  455. package/dist/src/backend/services/workspace-snapshot-store.service.js +20 -15
  456. package/dist/src/backend/services/workspace-snapshot-store.service.js.map +1 -1
  457. package/dist/src/backend/services/workspace-snapshot-store.service.test.js +3 -0
  458. package/dist/src/backend/services/workspace-snapshot-store.service.test.js.map +1 -1
  459. package/dist/src/backend/trpc/admin.router.test.js +0 -2
  460. package/dist/src/backend/trpc/admin.router.test.js.map +1 -1
  461. package/dist/src/backend/trpc/admin.trpc.d.ts +2 -7
  462. package/dist/src/backend/trpc/admin.trpc.d.ts.map +1 -1
  463. package/dist/src/backend/trpc/admin.trpc.js +2 -3
  464. package/dist/src/backend/trpc/admin.trpc.js.map +1 -1
  465. package/dist/src/backend/trpc/index.d.ts +49 -14
  466. package/dist/src/backend/trpc/index.d.ts.map +1 -1
  467. package/dist/src/backend/trpc/project.trpc.d.ts +17 -3
  468. package/dist/src/backend/trpc/project.trpc.d.ts.map +1 -1
  469. package/dist/src/backend/trpc/project.trpc.js +22 -0
  470. package/dist/src/backend/trpc/project.trpc.js.map +1 -1
  471. package/dist/src/backend/trpc/session.router.test.js +1 -0
  472. package/dist/src/backend/trpc/session.router.test.js.map +1 -1
  473. package/dist/src/backend/trpc/session.trpc.d.ts +4 -0
  474. package/dist/src/backend/trpc/session.trpc.d.ts.map +1 -1
  475. package/dist/src/backend/trpc/session.trpc.js +2 -2
  476. package/dist/src/backend/trpc/session.trpc.js.map +1 -1
  477. package/dist/src/backend/trpc/workspace/files.trpc.d.ts.map +1 -1
  478. package/dist/src/backend/trpc/workspace/files.trpc.js +1 -64
  479. package/dist/src/backend/trpc/workspace/files.trpc.js.map +1 -1
  480. package/dist/src/backend/trpc/workspace/init.router.test.js +1 -1
  481. package/dist/src/backend/trpc/workspace/init.router.test.js.map +1 -1
  482. package/dist/src/backend/trpc/workspace/init.trpc.d.ts +1 -0
  483. package/dist/src/backend/trpc/workspace/init.trpc.d.ts.map +1 -1
  484. package/dist/src/backend/trpc/workspace/init.trpc.js +2 -3
  485. package/dist/src/backend/trpc/workspace/init.trpc.js.map +1 -1
  486. package/dist/src/backend/trpc/workspace/run-script.router.test.js +31 -4
  487. package/dist/src/backend/trpc/workspace/run-script.router.test.js.map +1 -1
  488. package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts +2 -0
  489. package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts.map +1 -1
  490. package/dist/src/backend/trpc/workspace/run-script.trpc.js +8 -8
  491. package/dist/src/backend/trpc/workspace/run-script.trpc.js.map +1 -1
  492. package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts +2 -0
  493. package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts.map +1 -1
  494. package/dist/src/backend/trpc/workspace.router.test.js +45 -1
  495. package/dist/src/backend/trpc/workspace.router.test.js.map +1 -1
  496. package/dist/src/backend/trpc/workspace.trpc.d.ts +26 -4
  497. package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
  498. package/dist/src/backend/trpc/workspace.trpc.js +25 -16
  499. package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
  500. package/dist/src/cli/index.js +17 -5
  501. package/dist/src/cli/index.js.map +1 -1
  502. package/dist/src/shared/core/ci-status.d.ts +6 -4
  503. package/dist/src/shared/core/ci-status.d.ts.map +1 -1
  504. package/dist/src/shared/core/ci-status.js +47 -13
  505. package/dist/src/shared/core/ci-status.js.map +1 -1
  506. package/dist/src/shared/core/enums.d.ts +1 -0
  507. package/dist/src/shared/core/enums.d.ts.map +1 -1
  508. package/dist/src/shared/core/enums.js +1 -0
  509. package/dist/src/shared/core/enums.js.map +1 -1
  510. package/dist/src/shared/core/index.d.ts +1 -1
  511. package/dist/src/shared/core/index.d.ts.map +1 -1
  512. package/dist/src/shared/core/index.js +1 -1
  513. package/dist/src/shared/core/index.js.map +1 -1
  514. package/dist/src/shared/schemas/export-data.schema.d.ts +2 -0
  515. package/dist/src/shared/schemas/export-data.schema.d.ts.map +1 -1
  516. package/dist/src/shared/schemas/factory-config.schema.d.ts +1 -0
  517. package/dist/src/shared/schemas/factory-config.schema.d.ts.map +1 -1
  518. package/dist/src/shared/schemas/factory-config.schema.js +1 -0
  519. package/dist/src/shared/schemas/factory-config.schema.js.map +1 -1
  520. package/dist/src/shared/schemas/issue-tracker-config.schema.d.ts +2 -2
  521. package/dist/src/shared/schemas/persisted-stores.schema.d.ts +0 -2
  522. package/dist/src/shared/schemas/persisted-stores.schema.d.ts.map +1 -1
  523. package/dist/src/shared/schemas/persisted-stores.schema.js +0 -1
  524. package/dist/src/shared/schemas/persisted-stores.schema.js.map +1 -1
  525. package/dist/src/shared/workspace-flow-state.d.ts +3 -0
  526. package/dist/src/shared/workspace-flow-state.d.ts.map +1 -0
  527. package/dist/src/shared/workspace-flow-state.js +2 -0
  528. package/dist/src/shared/workspace-flow-state.js.map +1 -0
  529. package/dist/tsconfig.backend.tsbuildinfo +1 -1
  530. package/package.json +1 -1
  531. package/prisma/migrations/20260222120000_add_post_run_command/migration.sql +1 -0
  532. package/prisma/migrations/20260224150000_add_workspace_archiving_state/migration.sql +4 -0
  533. package/prisma/schema.prisma +2 -0
  534. package/dist/client/assets/channel-B2z94T-9.js +0 -1
  535. package/dist/client/assets/classDiagram-2ON5EDUG-B2LoFG_o.js +0 -1
  536. package/dist/client/assets/classDiagram-v2-WZHVMYZB-B2LoFG_o.js +0 -1
  537. package/dist/client/assets/clone-C8LA0zQQ.js +0 -1
  538. package/dist/client/assets/index-DvtmO7DV.css +0 -1
  539. package/dist/client/assets/index-EVrp_NXm.js +0 -429
  540. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-CO6XGRkL.js +0 -1
  541. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.d.ts.map +0 -1
  542. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.js.map +0 -1
  543. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.test.d.ts +0 -2
  544. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.test.d.ts.map +0 -1
  545. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.test.js.map +0 -1
  546. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.d.ts +0 -10
  547. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.d.ts.map +0 -1
  548. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.js +0 -24
  549. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.js.map +0 -1
  550. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.d.ts +0 -2
  551. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.d.ts.map +0 -1
  552. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.js +0 -17
  553. package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.js.map +0 -1
@@ -1,147 +1,17 @@
1
1
  import { Readable, Writable } from 'node:stream';
2
2
  import { AgentSideConnection, ndJsonStream, PROTOCOL_VERSION, RequestError, } from '@agentclientprotocol/sdk';
3
+ import { asString, dedupeStrings, extractLocations, isRecord, resolveToolCallId, } from './acp-adapter-utils.js';
3
4
  import { CodexRequestError, CodexRpcClient } from './codex-rpc-client.js';
4
- import { collaborationModeListResponseSchema, configRequirementsReadResponseSchema, knownCodexNotificationSchema, knownCodexServerRequestSchema, modelListResponseSchema, threadReadResponseSchema, threadResumeResponseSchema, threadStartResponseSchema, turnStartResponseSchema, } from './codex-zod.js';
5
+ import { turnStartResponseSchema } from './codex-zod.js';
6
+ import { resolveCommandDisplay } from './command-metadata.js';
7
+ import { handleCodexServerPermissionRequest } from './protocol-permission-handler.js';
8
+ import { attachCloseWatcherWithRetry } from './retry-logic.js';
9
+ import { buildConfigOptions, createSandboxPolicyFromMode, getCollaborationModeValues, getExecutionPresets, isKnownModel, isReasoningEffortSupportedForModel, resolveCollaborationModeLabel, resolveDefaultCollaborationMode, resolveDefaultModel, resolveReasoningEffortForModel, resolveSandboxPolicy, resolveSessionModel, resolveTurnCollaborationMode, } from './session-config-resolver.js';
10
+ import { loadCollaborationModes, loadConfigRequirements, loadModelCatalog, negotiateNewSession, negotiateSessionResume, } from './session-negotiation.js';
11
+ import { CodexAdapterSessionStateContainer } from './session-state-container.js';
12
+ import { ShapeDriftReporter } from './shape-drift-reporter.js';
13
+ import { CodexStreamEventHandler } from './stream-event-handler.js';
5
14
  const PENDING_TURN_ID = '__pending_turn__';
6
- const MAX_CLOSE_WATCHER_ATTACH_RETRIES = 50;
7
- const DEFAULT_APPROVAL_POLICIES = ['on-failure', 'on-request', 'never'];
8
- const DEFAULT_SANDBOX_MODES = ['read-only', 'workspace-write', 'danger-full-access'];
9
- const SHAPE_DRIFT_DETAILS_LIMIT = 700;
10
- const COMMAND_EXECUTION_SESSION_HANDOFF_LINE_PATTERN = /^process running with session id(?:\s*[:#-]?\s*[a-z0-9_-]+)?\.?$/i;
11
- function toTurnItemKey(turnId, itemId) {
12
- return `${turnId}:${itemId}`;
13
- }
14
- function toShapeDriftDetails(value) {
15
- try {
16
- const text = JSON.stringify(value);
17
- if (typeof text !== 'string') {
18
- return '[unserializable]';
19
- }
20
- return text.length > SHAPE_DRIFT_DETAILS_LIMIT
21
- ? `${text.slice(0, SHAPE_DRIFT_DETAILS_LIMIT)}...`
22
- : text;
23
- }
24
- catch {
25
- return '[unserializable]';
26
- }
27
- }
28
- function isNonEmptyString(value) {
29
- return typeof value === 'string' && value.trim().length > 0;
30
- }
31
- function dedupeStrings(values) {
32
- return Array.from(new Set(values));
33
- }
34
- function humanizeToken(value) {
35
- return value
36
- .split(/[-_]/)
37
- .filter((part) => part.length > 0)
38
- .map((part) => part.slice(0, 1).toUpperCase() + part.slice(1))
39
- .join(' ');
40
- }
41
- function sanitizeModeName(mode) {
42
- return mode
43
- .split('_')
44
- .map((part) => part.slice(0, 1).toUpperCase() + part.slice(1))
45
- .join(' ');
46
- }
47
- function formatApprovalPolicyLabel(policy) {
48
- if (policy === 'on-request') {
49
- return 'On Request';
50
- }
51
- if (policy === 'on-failure') {
52
- return 'On Failure';
53
- }
54
- if (policy === 'never') {
55
- return 'Never Ask';
56
- }
57
- if (policy === 'untrusted') {
58
- return 'Untrusted';
59
- }
60
- return humanizeToken(policy);
61
- }
62
- function formatSandboxModeLabel(mode) {
63
- if (mode === 'workspace-write') {
64
- return 'Workspace Write';
65
- }
66
- if (mode === 'read-only') {
67
- return 'Read-only';
68
- }
69
- if (mode === 'danger-full-access') {
70
- return 'Full Access';
71
- }
72
- return humanizeToken(mode);
73
- }
74
- function formatExecutionPresetName(approvalPolicy, sandboxMode) {
75
- if (approvalPolicy === 'never' && sandboxMode === 'danger-full-access') {
76
- return 'YOLO (Full Access)';
77
- }
78
- return `${formatApprovalPolicyLabel(approvalPolicy)} (${formatSandboxModeLabel(sandboxMode)})`;
79
- }
80
- function createWorkspaceWriteSandboxPolicy(cwd) {
81
- return {
82
- type: 'workspaceWrite',
83
- writableRoots: [cwd],
84
- readOnlyAccess: { type: 'fullAccess' },
85
- networkAccess: true,
86
- excludeTmpdirEnvVar: false,
87
- excludeSlashTmp: false,
88
- };
89
- }
90
- function createDangerFullAccessSandboxPolicy() {
91
- return {
92
- type: 'dangerFullAccess',
93
- };
94
- }
95
- function parseSandboxModeFromPolicy(policy) {
96
- if (!isRecord(policy)) {
97
- return null;
98
- }
99
- const policyType = asString(policy.type);
100
- if (policyType === 'workspaceWrite') {
101
- return 'workspace-write';
102
- }
103
- if (policyType === 'readOnly') {
104
- return 'read-only';
105
- }
106
- if (policyType === 'dangerFullAccess') {
107
- return 'danger-full-access';
108
- }
109
- return null;
110
- }
111
- function createSandboxPolicyFromMode(mode, cwd) {
112
- if (mode === 'danger-full-access') {
113
- return createDangerFullAccessSandboxPolicy();
114
- }
115
- if (mode === 'read-only') {
116
- return {
117
- type: 'readOnly',
118
- access: { type: 'fullAccess' },
119
- };
120
- }
121
- return createWorkspaceWriteSandboxPolicy(cwd);
122
- }
123
- function toSessionId(threadId) {
124
- return `sess_${threadId}`;
125
- }
126
- function toThreadId(sessionId) {
127
- return sessionId.startsWith('sess_') ? sessionId.slice('sess_'.length) : sessionId;
128
- }
129
- function extractToolCallIdFromUnknown(value) {
130
- if (!isRecord(value)) {
131
- return null;
132
- }
133
- return asString(value.callId) ?? asString(value.call_id) ?? null;
134
- }
135
- function resolveToolCallId(params) {
136
- return extractToolCallIdFromUnknown(params.source) ?? params.itemId;
137
- }
138
- function isCommandExecutionSessionHandoffOutput(output) {
139
- const trimmedOutput = output.trim();
140
- if (trimmedOutput.length === 0 || /[\r\n]/.test(trimmedOutput)) {
141
- return false;
142
- }
143
- return COMMAND_EXECUTION_SESSION_HANDOFF_LINE_PATTERN.test(trimmedOutput);
144
- }
145
15
  function isPlanLikeMode(mode) {
146
16
  return /plan/i.test(mode);
147
17
  }
@@ -280,393 +150,6 @@ function toCodexMcpConfigMap(mcpServers) {
280
150
  }
281
151
  return mcpServersByName;
282
152
  }
283
- function buildToolUserInputPermissionOptions(questions) {
284
- if (questions.length !== 1) {
285
- return [
286
- { optionId: 'allow_once', name: 'Submit', kind: 'allow_once' },
287
- { optionId: 'reject_once', name: 'Cancel', kind: 'reject_once' },
288
- ];
289
- }
290
- const firstQuestionWithOptions = questions.find((question) => Array.isArray(question.options) && question.options.length > 0);
291
- if (!firstQuestionWithOptions?.options) {
292
- return [
293
- { optionId: 'allow_once', name: 'Submit', kind: 'allow_once' },
294
- { optionId: 'reject_once', name: 'Cancel', kind: 'reject_once' },
295
- ];
296
- }
297
- const mappedOptions = firstQuestionWithOptions.options.slice(0, 6).map((option, index) => ({
298
- optionId: `answer_${index}`,
299
- name: option.label,
300
- kind: 'allow_once',
301
- }));
302
- mappedOptions.push({ optionId: 'reject_once', name: 'Cancel', kind: 'reject_once' });
303
- return mappedOptions;
304
- }
305
- function buildToolUserInputAnswers(params) {
306
- if (params.selectedOptionId === null || params.selectedOptionId === 'reject_once') {
307
- return {};
308
- }
309
- const parsedAnswers = parseToolUserInputAnswersFromPermissionMeta({
310
- questions: params.questions,
311
- permission: params.permission,
312
- });
313
- if (parsedAnswers) {
314
- return parsedAnswers;
315
- }
316
- if (params.questions.length !== 1) {
317
- throw new Error('Missing structured answers for multi-question requestUserInput');
318
- }
319
- const selectedIndex = params.selectedOptionId.startsWith('answer_')
320
- ? Number.parseInt(params.selectedOptionId.slice('answer_'.length), 10)
321
- : Number.NaN;
322
- const answers = {};
323
- const [question] = params.questions;
324
- if (!(question && Array.isArray(question.options)) || question.options.length === 0) {
325
- return answers;
326
- }
327
- const selectedOption = Number.isNaN(selectedIndex)
328
- ? question.options[0]
329
- : (question.options[selectedIndex] ?? question.options[0]);
330
- if (!selectedOption) {
331
- return answers;
332
- }
333
- answers[question.id] = { answers: [selectedOption.label] };
334
- return answers;
335
- }
336
- function isRecord(value) {
337
- return typeof value === 'object' && value !== null && !Array.isArray(value);
338
- }
339
- function parseToolUserInputAnswersFromPermissionMeta(params) {
340
- const meta = params.permission._meta;
341
- if (!isRecord(meta)) {
342
- return null;
343
- }
344
- const factoryFactoryMeta = isRecord(meta.factoryFactory) ? meta.factoryFactory : null;
345
- const answersRaw = (factoryFactoryMeta?.toolUserInputAnswers ?? meta.toolUserInputAnswers);
346
- if (!isRecord(answersRaw)) {
347
- return null;
348
- }
349
- const knownQuestionIds = new Set(params.questions.map((question) => question.id));
350
- const answers = {};
351
- for (const [questionId, value] of Object.entries(answersRaw)) {
352
- if (!knownQuestionIds.has(questionId)) {
353
- continue;
354
- }
355
- const values = (Array.isArray(value) ? value : [value])
356
- .filter((entry) => typeof entry === 'string')
357
- .map((entry) => entry.trim())
358
- .filter((entry) => entry.length > 0);
359
- if (values.length === 0) {
360
- continue;
361
- }
362
- answers[questionId] = { answers: values };
363
- }
364
- return answers;
365
- }
366
- function asString(value) {
367
- return typeof value === 'string' ? value : null;
368
- }
369
- function trimOptionalQuotes(token) {
370
- if (token.length >= 2 && token.startsWith('"') && token.endsWith('"')) {
371
- return { text: token.slice(1, -1), quote: '"' };
372
- }
373
- if (token.length >= 2 && token.startsWith("'") && token.endsWith("'")) {
374
- return { text: token.slice(1, -1), quote: "'" };
375
- }
376
- return { text: token, quote: null };
377
- }
378
- function unescapeCommandToken(token, quote) {
379
- if (quote === "'") {
380
- return token.replace(/\\'/g, "'").replace(/\\\\/g, '\\');
381
- }
382
- return token.replace(/\\(["'\\\s|&;])/g, '$1');
383
- }
384
- function sanitizeCommandToken(token) {
385
- const trimmed = token.trim();
386
- const { text, quote } = trimOptionalQuotes(trimmed);
387
- return unescapeCommandToken(text, quote).trim();
388
- }
389
- function tokenizeCommand(command) {
390
- return (command.match(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+/g) ?? [])
391
- .map((token) => sanitizeCommandToken(token))
392
- .filter((token) => token.length > 0);
393
- }
394
- function commandName(token) {
395
- const unix = token.split('/').at(-1) ?? token;
396
- return (unix.split('\\').at(-1) ?? unix).toLowerCase();
397
- }
398
- function isChainSeparatorChar(char) {
399
- return char === ';' || char === '\n' || char === '|' || char === '&';
400
- }
401
- function readChainSeparatorLength(command, index) {
402
- const char = command[index];
403
- if (!(char && isChainSeparatorChar(char))) {
404
- return 0;
405
- }
406
- const next = command[index + 1];
407
- if ((char === '|' || char === '&') && next === char) {
408
- return 2;
409
- }
410
- return 1;
411
- }
412
- function isLikelyPathToken(token) {
413
- if (!token || token.startsWith('-')) {
414
- return false;
415
- }
416
- if (token.startsWith('./') ||
417
- token.startsWith('../') ||
418
- token.startsWith('/') ||
419
- token.startsWith('~')) {
420
- return true;
421
- }
422
- return (token.includes('/') ||
423
- token.includes('\\') ||
424
- token.endsWith('.') ||
425
- /\.[a-z0-9]+$/i.test(token));
426
- }
427
- function normalizeLocationPath(pathToken, cwd) {
428
- if (pathToken.startsWith('/')) {
429
- return pathToken;
430
- }
431
- if (pathToken.startsWith('~')) {
432
- return pathToken;
433
- }
434
- const base = cwd.endsWith('/') ? cwd.slice(0, -1) : cwd;
435
- return `${base}/${pathToken}`;
436
- }
437
- const READ_COMMANDS = new Set(['cat', 'head', 'tail', 'less', 'more']);
438
- const LIST_OR_FIND_COMMANDS = new Set(['ls', 'tree', 'find', 'fd']);
439
- const GREP_LIKE_COMMANDS = new Set(['rg', 'ripgrep', 'grep', 'ag']);
440
- const SHELL_META_COMMANDS = new Set(['cd', 'export', 'set', 'unset', 'alias', 'unalias', 'source']);
441
- function pushCommandChainPart(state) {
442
- const trimmed = state.current.trim();
443
- if (trimmed.length > 0) {
444
- state.parts.push(trimmed);
445
- }
446
- state.current = '';
447
- }
448
- function consumeEscapedCommandChar(state, char) {
449
- if (!state.escaped) {
450
- return false;
451
- }
452
- state.current += char;
453
- state.escaped = false;
454
- return true;
455
- }
456
- function consumeEscapeInitiator(state, char) {
457
- if (!(char === '\\' && state.quote !== "'")) {
458
- return false;
459
- }
460
- state.current += char;
461
- state.escaped = true;
462
- return true;
463
- }
464
- function hasOddTrailingBackslashes(value) {
465
- let count = 0;
466
- for (let index = value.length - 1; index >= 0; index -= 1) {
467
- if (value[index] !== '\\') {
468
- break;
469
- }
470
- count += 1;
471
- }
472
- return count % 2 === 1;
473
- }
474
- function consumeQuotedCommandChar(state, char) {
475
- if (!state.quote) {
476
- return false;
477
- }
478
- const escapedSingleQuote = state.quote === "'" && char === "'" && hasOddTrailingBackslashes(state.current);
479
- state.current += char;
480
- if (char === state.quote && !escapedSingleQuote) {
481
- state.quote = null;
482
- }
483
- return true;
484
- }
485
- function consumeQuoteStart(state, char) {
486
- if (!(char === '"' || char === "'")) {
487
- return false;
488
- }
489
- state.quote = char;
490
- state.current += char;
491
- return true;
492
- }
493
- function consumeCommandChainSeparator(state, command, index) {
494
- const separatorLength = readChainSeparatorLength(command, index);
495
- if (separatorLength <= 0) {
496
- return 0;
497
- }
498
- pushCommandChainPart(state);
499
- return separatorLength;
500
- }
501
- function splitCommandChain(command) {
502
- const state = {
503
- parts: [],
504
- current: '',
505
- quote: null,
506
- escaped: false,
507
- };
508
- for (let index = 0; index < command.length; index += 1) {
509
- const char = command[index];
510
- if (!char) {
511
- continue;
512
- }
513
- if (consumeEscapedCommandChar(state, char)) {
514
- continue;
515
- }
516
- if (consumeEscapeInitiator(state, char)) {
517
- continue;
518
- }
519
- if (consumeQuotedCommandChar(state, char)) {
520
- continue;
521
- }
522
- if (consumeQuoteStart(state, char)) {
523
- continue;
524
- }
525
- const consumedSeparatorLength = consumeCommandChainSeparator(state, command, index);
526
- if (consumedSeparatorLength > 0) {
527
- index += consumedSeparatorLength - 1;
528
- continue;
529
- }
530
- state.current += char;
531
- }
532
- pushCommandChainPart(state);
533
- return state.parts;
534
- }
535
- function buildCommandDisplayContexts(rawCommand, cwd) {
536
- const command = rawCommand?.trim();
537
- if (!command) {
538
- return [];
539
- }
540
- const contexts = [];
541
- const segments = splitCommandChain(command);
542
- for (const segment of segments) {
543
- const tokens = tokenizeCommand(segment);
544
- if (tokens.length === 0) {
545
- continue;
546
- }
547
- const [firstToken] = tokens;
548
- if (!firstToken) {
549
- continue;
550
- }
551
- const firstCommand = commandName(firstToken);
552
- const nonFlagArgs = tokens.slice(1).filter((token) => !token.startsWith('-'));
553
- const pathArg = nonFlagArgs.find(isLikelyPathToken) ?? null;
554
- const commandPath = pathArg ? normalizeLocationPath(pathArg, cwd) : null;
555
- const locations = commandPath ? [{ path: commandPath }] : [];
556
- contexts.push({
557
- command: segment,
558
- firstCommand,
559
- nonFlagArgs,
560
- pathArg,
561
- cwd,
562
- locations,
563
- isShellMeta: SHELL_META_COMMANDS.has(firstCommand),
564
- });
565
- }
566
- return contexts;
567
- }
568
- function chooseActionableCommandContexts(contexts) {
569
- const actionable = contexts.filter((context) => !context.isShellMeta);
570
- return actionable.length > 0 ? actionable : contexts;
571
- }
572
- function selectCombinedCommandKind(displays) {
573
- const firstNonExecute = displays.find((display) => display.kind !== 'execute');
574
- return firstNonExecute?.kind ?? 'execute';
575
- }
576
- function resolveCommandDisplay(params) {
577
- const contexts = chooseActionableCommandContexts(buildCommandDisplayContexts(params.command, params.cwd));
578
- if (contexts.length === 0) {
579
- return { title: 'commandExecution', kind: 'execute', locations: [] };
580
- }
581
- const [singleContext] = contexts;
582
- if (singleContext && contexts.length === 1) {
583
- return resolveCommandDisplayFromContext(singleContext);
584
- }
585
- const displays = contexts.map((context) => resolveCommandDisplayFromContext(context));
586
- const title = dedupeStrings(displays.map((display) => display.title)).join(', ');
587
- const kind = selectCombinedCommandKind(displays);
588
- const locations = dedupeLocations(displays.flatMap((display) => display.locations)).map((location) => ({ path: location.path }));
589
- return { title, kind, locations };
590
- }
591
- function resolveCommandDisplayFromContext(context) {
592
- if (READ_COMMANDS.has(context.firstCommand)) {
593
- const label = context.pathArg ?? context.command;
594
- return { title: `Read ${label}`, kind: 'read', locations: context.locations };
595
- }
596
- if (LIST_OR_FIND_COMMANDS.has(context.firstCommand)) {
597
- const target = context.pathArg
598
- ? normalizeLocationPath(context.pathArg, context.cwd)
599
- : context.cwd;
600
- const title = context.firstCommand === 'find' || context.firstCommand === 'fd'
601
- ? `Search ${target}`
602
- : `List ${target}`;
603
- return { title, kind: 'search', locations: context.locations };
604
- }
605
- if (GREP_LIKE_COMMANDS.has(context.firstCommand)) {
606
- const query = context.nonFlagArgs.find((token) => !isLikelyPathToken(token));
607
- const target = context.pathArg ? ` in ${context.pathArg}` : '';
608
- const title = query ? `Search ${query}${target}` : `Search ${context.command}`;
609
- return { title, kind: 'search', locations: context.locations };
610
- }
611
- return { title: context.command, kind: 'execute', locations: context.locations };
612
- }
613
- function normalizeCwdForScope(cwd) {
614
- if (cwd.length > 1 && cwd.endsWith('/')) {
615
- return cwd.slice(0, -1);
616
- }
617
- return cwd;
618
- }
619
- function normalizeScopeToken(token) {
620
- return token.replace(/\s+/g, ' ').trim();
621
- }
622
- function buildCommandApprovalScopeKey(params) {
623
- const contexts = buildCommandDisplayContexts(params.command, params.cwd);
624
- if (contexts.length === 0) {
625
- return null;
626
- }
627
- let scopeCwd = normalizeCwdForScope(params.cwd);
628
- const segments = [];
629
- for (const context of contexts) {
630
- if (context.firstCommand === 'cd') {
631
- const rawTarget = context.nonFlagArgs[0];
632
- const target = rawTarget ? normalizeScopeToken(rawTarget) : '';
633
- if (target.length > 0) {
634
- scopeCwd = normalizeCwdForScope(normalizeLocationPath(target, scopeCwd));
635
- segments.push(`cd ${target} -> ${scopeCwd}`);
636
- }
637
- else {
638
- segments.push('cd');
639
- }
640
- continue;
641
- }
642
- const args = context.nonFlagArgs.map(normalizeScopeToken).filter((arg) => arg.length > 0);
643
- const normalized = normalizeScopeToken([context.firstCommand, ...args].join(' '));
644
- if (normalized.length === 0) {
645
- continue;
646
- }
647
- segments.push(`[cwd=${scopeCwd}] ${normalized}`);
648
- }
649
- const normalizedSegments = segments
650
- .map(normalizeScopeToken)
651
- .filter((segment) => segment.length > 0);
652
- if (normalizedSegments.length === 0) {
653
- return null;
654
- }
655
- return `cwd=${normalizeCwdForScope(params.cwd)}|${normalizedSegments.join(' && ')}`;
656
- }
657
- function dedupeLocations(locations) {
658
- const seen = new Set();
659
- const result = [];
660
- for (const location of locations) {
661
- const key = `${location.path}:${location.line ?? ''}`;
662
- if (seen.has(key)) {
663
- continue;
664
- }
665
- seen.add(key);
666
- result.push(location);
667
- }
668
- return result;
669
- }
670
153
  function parseTextFromPromptBlock(block) {
671
154
  if (block.type === 'text') {
672
155
  return block.text;
@@ -690,123 +173,34 @@ function parseTextFromPromptBlock(block) {
690
173
  }
691
174
  return JSON.stringify(block);
692
175
  }
693
- function toToolStatus(status) {
694
- if (status === 'inProgress') {
695
- return 'in_progress';
696
- }
697
- if (status === 'completed') {
698
- return 'completed';
699
- }
700
- if (status === 'failed' || status === 'declined') {
701
- return 'failed';
702
- }
703
- return undefined;
704
- }
705
- function createCollaborationModeConfigOption(currentMode, collaborationModes) {
706
- const options = collaborationModes
707
- .filter((entry) => isNonEmptyString(entry.mode))
708
- .map((entry) => ({
709
- value: entry.mode,
710
- name: entry.name,
711
- }));
712
- if (!options.some((option) => option.value === currentMode)) {
713
- options.unshift({ value: currentMode, name: sanitizeModeName(currentMode) });
714
- }
715
- return {
716
- id: 'mode',
717
- category: 'mode',
718
- name: 'Collaboration Mode',
719
- type: 'select',
720
- currentValue: currentMode,
721
- options,
722
- };
723
- }
724
- function createModelConfigOption(currentModel, modelCatalog) {
725
- const options = modelCatalog.map((model) => ({
726
- value: model.id,
727
- name: model.displayName,
728
- description: model.description,
729
- }));
730
- if (!options.some((option) => option.value === currentModel)) {
731
- options.unshift({ value: currentModel, name: currentModel });
732
- }
733
- return {
734
- id: 'model',
735
- category: 'model',
736
- name: 'Model',
737
- type: 'select',
738
- currentValue: currentModel,
739
- options,
740
- };
741
- }
742
- function createReasoningEffortConfigOption(currentReasoningEffort, modelCatalog, currentModel) {
743
- const modelEntry = modelCatalog.find((model) => model.id === currentModel);
744
- if (!modelEntry) {
745
- return null;
746
- }
747
- const supportedEntries = modelEntry.supportedReasoningEfforts.filter((entry) => isNonEmptyString(entry.reasoningEffort));
748
- if (supportedEntries.length === 0) {
749
- return null;
750
- }
751
- const supportedByValue = new Map();
752
- for (const entry of supportedEntries) {
753
- if (!supportedByValue.has(entry.reasoningEffort)) {
754
- supportedByValue.set(entry.reasoningEffort, entry.description);
755
- }
756
- }
757
- const supportedValues = [...supportedByValue.keys()];
758
- const resolvedCurrent = currentReasoningEffort && supportedByValue.has(currentReasoningEffort)
759
- ? currentReasoningEffort
760
- : supportedByValue.has(modelEntry.defaultReasoningEffort)
761
- ? modelEntry.defaultReasoningEffort
762
- : supportedValues[0];
763
- if (!resolvedCurrent) {
764
- return null;
765
- }
766
- return {
767
- id: 'reasoning_effort',
768
- category: 'thought_level',
769
- name: 'Reasoning Effort',
770
- type: 'select',
771
- currentValue: resolvedCurrent,
772
- options: supportedValues.map((value) => ({
773
- value,
774
- name: value,
775
- ...(supportedByValue.get(value) ? { description: supportedByValue.get(value) } : {}),
776
- })),
777
- };
778
- }
779
- function createExecutionModeConfigOption(currentPresetId, presets) {
780
- return {
781
- id: 'execution_mode',
782
- category: 'permission',
783
- name: 'Execution Mode',
784
- type: 'select',
785
- currentValue: currentPresetId,
786
- options: presets.map((preset) => ({
787
- value: preset.id,
788
- name: preset.name,
789
- ...(preset.description ? { description: preset.description } : {}),
790
- })),
791
- };
792
- }
793
- function toExecutionPresetId(approvalPolicy, sandboxMode) {
794
- return JSON.stringify([approvalPolicy, sandboxMode]);
795
- }
796
176
  export class CodexAppServerAcpAdapter {
797
177
  connection;
798
178
  codex;
799
- sessions = new Map();
800
- sessionIdByThreadId = new Map();
179
+ stateContainer = new CodexAdapterSessionStateContainer();
801
180
  modelCatalog = [];
802
181
  allowedApprovalPolicies = [];
803
182
  allowedSandboxModes = [];
804
183
  collaborationModes = [];
805
- mcpServersByThreadId = new Map();
806
- appliedMcpServerConfigJson = '{}';
807
- shapeDriftCounts = new Map();
808
- constructor(connection, codexClient) {
184
+ shapeDriftReporter;
185
+ streamEventHandler;
186
+ get sessions() {
187
+ return this.stateContainer.sessions;
188
+ }
189
+ get sessionIdByThreadId() {
190
+ return this.stateContainer.sessionIdByThreadId;
191
+ }
192
+ get mcpServersByThreadId() {
193
+ return this.stateContainer.mcpServersByThreadId;
194
+ }
195
+ get appliedMcpServerConfigJson() {
196
+ return this.stateContainer.appliedMcpServerConfigJson;
197
+ }
198
+ set appliedMcpServerConfigJson(value) {
199
+ this.stateContainer.appliedMcpServerConfigJson = value;
200
+ }
201
+ constructor(connection, codexClient, options) {
809
202
  this.connection = connection;
203
+ this.shapeDriftReporter = new ShapeDriftReporter(options?.shapeDriftWarn);
810
204
  this.codex =
811
205
  codexClient ??
812
206
  new CodexRpcClient({
@@ -832,31 +226,33 @@ export class CodexAppServerAcpAdapter {
832
226
  process.stderr.write(`[codex-app-server-acp] protocol-error: ${error.reason}\n`);
833
227
  },
834
228
  });
229
+ this.streamEventHandler = new CodexStreamEventHandler({
230
+ codex: this.codex,
231
+ sessionIdByThreadId: this.sessionIdByThreadId,
232
+ sessions: this.sessions,
233
+ requireSession: (sessionId) => this.requireSession(sessionId),
234
+ emitSessionUpdate: (sessionId, update) => this.emitSessionUpdate(sessionId, update),
235
+ reportShapeDrift: (event, details) => this.reportShapeDrift(event, details),
236
+ buildToolCallState: (session, item, turnId) => this.buildToolCallState(session, item, turnId),
237
+ emitReasoningThoughtChunkFromItem: (sessionId, item) => this.emitReasoningThoughtChunkFromItem(sessionId, item),
238
+ shouldHoldTurnForPlanApproval: (session, item, turnId) => this.shouldHoldTurnForPlanApproval(session, item, turnId),
239
+ holdTurnUntilPlanApprovalResolves: (session, turnId) => this.holdTurnUntilPlanApprovalResolves(session, turnId),
240
+ maybeRequestPlanApproval: (session, item, turnId, completedPlanToolCall) => this.maybeRequestPlanApproval(session, item, turnId, completedPlanToolCall),
241
+ hasPendingPlanApprovals: (session, turnId) => this.hasPendingPlanApprovals(session, turnId),
242
+ settleTurn: (session, stopReason) => this.settleTurn(session, stopReason),
243
+ emitTurnFailureMessage: (sessionId, errorMessage) => this.emitTurnFailureMessage(sessionId, errorMessage),
244
+ });
835
245
  this.monitorConnectionClose();
836
246
  }
837
247
  monitorConnectionClose() {
838
- let attachAttempts = 0;
839
- const attachCloseWatcher = () => {
840
- try {
841
- void this.connection.closed
842
- .finally(async () => {
843
- await this.codex.stop();
844
- })
845
- .catch(() => {
846
- });
847
- }
848
- catch {
849
- attachAttempts += 1;
850
- if (attachAttempts >= MAX_CLOSE_WATCHER_ATTACH_RETRIES) {
851
- process.stderr.write(`[codex-app-server-acp] failed to attach close watcher after ${MAX_CLOSE_WATCHER_ATTACH_RETRIES} attempts\n`);
852
- void this.codex.stop();
853
- return;
854
- }
855
- const retryTimer = setTimeout(attachCloseWatcher, 0);
856
- retryTimer.unref?.();
857
- }
858
- };
859
- queueMicrotask(attachCloseWatcher);
248
+ attachCloseWatcherWithRetry({
249
+ getClosed: () => this.connection.closed,
250
+ onClose: async () => this.codex.stop(),
251
+ onAttachRetryLimitReached: (maxAttempts) => {
252
+ process.stderr.write(`[codex-app-server-acp] failed to attach close watcher after ${maxAttempts} attempts\n`);
253
+ void this.codex.stop();
254
+ },
255
+ });
860
256
  }
861
257
  async initialize(_params) {
862
258
  this.codex.start();
@@ -870,11 +266,11 @@ export class CodexAppServerAcpAdapter {
870
266
  },
871
267
  });
872
268
  this.codex.notify('initialized');
873
- const configRequirements = await this.loadConfigRequirements();
269
+ const configRequirements = await loadConfigRequirements({ codex: this.codex });
874
270
  this.allowedApprovalPolicies = configRequirements.allowedApprovalPolicies;
875
271
  this.allowedSandboxModes = configRequirements.allowedSandboxModes;
876
- this.collaborationModes = await this.loadCollaborationModes();
877
- this.modelCatalog = await this.loadModelCatalog();
272
+ this.collaborationModes = await loadCollaborationModes({ codex: this.codex });
273
+ this.modelCatalog = await loadModelCatalog({ codex: this.codex });
878
274
  return {
879
275
  protocolVersion: PROTOCOL_VERSION,
880
276
  agentInfo: {
@@ -892,91 +288,42 @@ export class CodexAppServerAcpAdapter {
892
288
  };
893
289
  }
894
290
  async newSession(params) {
895
- const defaultModel = this.resolveDefaultModel();
896
- const responseRaw = await this.codex.request('thread/start', {
291
+ const negotiatedSession = await negotiateNewSession({
292
+ codex: this.codex,
897
293
  cwd: params.cwd,
898
- model: defaultModel,
294
+ resolveDefaultModel: () => this.resolveDefaultModel(),
295
+ resolveSessionModel: (model, fallbackModel) => this.resolveSessionModel(model, fallbackModel),
296
+ resolveSandboxPolicy: (sandbox, cwd) => this.resolveSandboxPolicy(sandbox, cwd),
297
+ resolveReasoningEffortForModel: (modelId, candidateReasoningEffort) => this.resolveReasoningEffortForModel(modelId, candidateReasoningEffort),
298
+ resolveDefaultCollaborationMode: () => this.resolveDefaultCollaborationMode(),
899
299
  });
900
- const response = threadStartResponseSchema.parse(responseRaw);
901
- const sessionId = toSessionId(response.thread.id);
902
- const approvalPolicy = this.requireApprovalPolicy(response.approvalPolicy, 'thread/start');
903
- const model = this.resolveSessionModel(response.model, defaultModel);
904
- const sandboxPolicy = this.resolveSandboxPolicy(response.sandbox, params.cwd);
905
- const reasoningEffort = this.resolveReasoningEffortForModel(model, response.reasoningEffort);
906
- const collaborationMode = this.resolveDefaultCollaborationMode();
907
- const session = {
908
- sessionId,
909
- threadId: response.thread.id,
910
- cwd: params.cwd,
911
- defaults: {
912
- model,
913
- approvalPolicy,
914
- sandboxPolicy,
915
- reasoningEffort,
916
- collaborationMode,
917
- },
918
- activeTurn: null,
919
- toolCallsByItemId: new Map(),
920
- syntheticallyCompletedToolItemIds: new Set(),
921
- reasoningDeltaItemIds: new Set(),
922
- planTextByItemId: new Map(),
923
- planApprovalRequestedByTurnId: new Set(),
924
- pendingPlanApprovalsByTurnId: new Map(),
925
- pendingTurnCompletionsByTurnId: new Map(),
926
- commandApprovalScopes: new Set(),
927
- replayedTurnItemKeys: new Set(),
928
- };
929
- this.sessions.set(sessionId, session);
930
- this.sessionIdByThreadId.set(session.threadId, sessionId);
300
+ const session = this.stateContainer.createSession(negotiatedSession);
301
+ this.stateContainer.registerSession(session);
931
302
  try {
932
303
  await this.applyMcpServers(session.threadId, params.mcpServers);
933
304
  }
934
305
  catch (error) {
935
- this.sessions.delete(sessionId);
936
- this.sessionIdByThreadId.delete(session.threadId);
306
+ this.stateContainer.deleteSession(negotiatedSession.sessionId);
937
307
  throw error;
938
308
  }
939
309
  return {
940
- sessionId,
310
+ sessionId: negotiatedSession.sessionId,
941
311
  configOptions: this.buildConfigOptions(session),
942
312
  };
943
313
  }
944
314
  async loadSession(params) {
945
- const threadId = toThreadId(params.sessionId);
946
- const responseRaw = await this.codex.request('thread/resume', {
947
- threadId,
948
- cwd: params.cwd,
949
- });
950
- const response = threadResumeResponseSchema.parse(responseRaw);
951
- const approvalPolicy = this.requireApprovalPolicy(response.approvalPolicy, 'thread/resume');
952
- const model = this.resolveSessionModel(response.model, this.resolveDefaultModel());
953
- const sandboxPolicy = this.resolveSandboxPolicy(response.sandbox, params.cwd);
954
- const reasoningEffort = this.resolveReasoningEffortForModel(model, response.reasoningEffort);
955
- const collaborationMode = this.resolveDefaultCollaborationMode();
956
- const session = {
315
+ const negotiatedSession = await negotiateSessionResume({
316
+ codex: this.codex,
957
317
  sessionId: params.sessionId,
958
- threadId: response.thread.id,
959
318
  cwd: params.cwd,
960
- defaults: {
961
- model,
962
- approvalPolicy,
963
- sandboxPolicy,
964
- reasoningEffort,
965
- collaborationMode,
966
- },
967
- activeTurn: null,
968
- toolCallsByItemId: new Map(),
969
- syntheticallyCompletedToolItemIds: new Set(),
970
- reasoningDeltaItemIds: new Set(),
971
- planTextByItemId: new Map(),
972
- planApprovalRequestedByTurnId: new Set(),
973
- pendingPlanApprovalsByTurnId: new Map(),
974
- pendingTurnCompletionsByTurnId: new Map(),
975
- commandApprovalScopes: new Set(),
976
- replayedTurnItemKeys: new Set(),
977
- };
978
- this.sessions.set(session.sessionId, session);
979
- this.sessionIdByThreadId.set(session.threadId, session.sessionId);
319
+ resolveDefaultModel: () => this.resolveDefaultModel(),
320
+ resolveSessionModel: (model, fallbackModel) => this.resolveSessionModel(model, fallbackModel),
321
+ resolveSandboxPolicy: (sandbox, cwd) => this.resolveSandboxPolicy(sandbox, cwd),
322
+ resolveReasoningEffortForModel: (modelId, candidateReasoningEffort) => this.resolveReasoningEffortForModel(modelId, candidateReasoningEffort),
323
+ resolveDefaultCollaborationMode: () => this.resolveDefaultCollaborationMode(),
324
+ });
325
+ const session = this.stateContainer.createSession(negotiatedSession);
326
+ this.stateContainer.registerSession(session);
980
327
  try {
981
328
  await this.applyMcpServers(session.threadId, params.mcpServers);
982
329
  await this.replayThreadHistory(session.sessionId, session.threadId);
@@ -987,8 +334,7 @@ export class CodexAppServerAcpAdapter {
987
334
  }
988
335
  catch {
989
336
  }
990
- this.sessions.delete(session.sessionId);
991
- this.sessionIdByThreadId.delete(session.threadId);
337
+ this.stateContainer.deleteSession(session.sessionId);
992
338
  throw error;
993
339
  }
994
340
  return {
@@ -1040,7 +386,7 @@ export class CodexAppServerAcpAdapter {
1040
386
  break;
1041
387
  }
1042
388
  case 'model': {
1043
- if (!this.modelCatalog.some((model) => model.id === params.value)) {
389
+ if (!isKnownModel(this.modelCatalog, params.value)) {
1044
390
  throw RequestError.invalidParams({
1045
391
  configId: params.configId,
1046
392
  value: params.value,
@@ -1052,12 +398,7 @@ export class CodexAppServerAcpAdapter {
1052
398
  }
1053
399
  case 'reasoning_effort':
1054
400
  case 'thought_level': {
1055
- const modelEntry = this.modelCatalog.find((model) => model.id === session.defaults.model);
1056
- const supportedReasoningEfforts = modelEntry?.supportedReasoningEfforts ?? [];
1057
- const supportedValues = new Set(supportedReasoningEfforts
1058
- .map((entry) => entry.reasoningEffort)
1059
- .filter((effort) => isNonEmptyString(effort)));
1060
- if (!supportedValues.has(params.value)) {
401
+ if (!isReasoningEffortSupportedForModel(this.modelCatalog, session.defaults.model, params.value)) {
1061
402
  throw RequestError.invalidParams({
1062
403
  configId: params.configId,
1063
404
  value: params.value,
@@ -1207,15 +548,7 @@ export class CodexAppServerAcpAdapter {
1207
548
  }
1208
549
  }
1209
550
  resolveDefaultModel() {
1210
- const preferred = this.modelCatalog.find((model) => model.isDefault);
1211
- const fallback = this.modelCatalog[0]?.id;
1212
- if (preferred?.id) {
1213
- return preferred.id;
1214
- }
1215
- if (fallback) {
1216
- return fallback;
1217
- }
1218
- throw new Error('Codex app-server model/list returned no models');
551
+ return resolveDefaultModel(this.modelCatalog);
1219
552
  }
1220
553
  buildMergedMcpServersConfig() {
1221
554
  const merged = {};
@@ -1288,414 +621,41 @@ export class CodexAppServerAcpAdapter {
1288
621
  }
1289
622
  }
1290
623
  buildConfigOptions(session) {
1291
- const executionPresets = this.getExecutionPresets(session);
1292
- const currentExecutionPreset = this.resolveExecutionPresetId(session, executionPresets);
1293
- const configOptions = [
1294
- createModelConfigOption(session.defaults.model, this.modelCatalog),
1295
- createCollaborationModeConfigOption(session.defaults.collaborationMode, this.collaborationModes),
1296
- createExecutionModeConfigOption(currentExecutionPreset, executionPresets),
1297
- ];
1298
- const reasoningOption = createReasoningEffortConfigOption(session.defaults.reasoningEffort, this.modelCatalog, session.defaults.model);
1299
- if (reasoningOption) {
1300
- configOptions.push(reasoningOption);
1301
- }
1302
- return configOptions;
1303
- }
1304
- requireApprovalPolicy(approvalPolicy, source) {
1305
- if (!isNonEmptyString(approvalPolicy)) {
1306
- throw new Error(`Codex ${source} response did not include approvalPolicy`);
1307
- }
1308
- return approvalPolicy;
624
+ return buildConfigOptions(session, this.modelCatalog, this.collaborationModes, this.allowedApprovalPolicies, this.allowedSandboxModes);
1309
625
  }
1310
626
  resolveSessionModel(model, fallbackModel) {
1311
- return isNonEmptyString(model) ? model : fallbackModel;
627
+ return resolveSessionModel(model, fallbackModel);
1312
628
  }
1313
629
  resolveSandboxPolicy(sandbox, cwd) {
1314
- return isRecord(sandbox) ? sandbox : createWorkspaceWriteSandboxPolicy(cwd);
630
+ return resolveSandboxPolicy(sandbox, cwd);
1315
631
  }
1316
632
  resolveDefaultCollaborationMode() {
1317
- if (this.collaborationModes.length === 0) {
1318
- throw new Error('Codex collaborationMode/list returned no modes');
1319
- }
1320
- const preferredDefault = this.collaborationModes.find((entry) => entry.mode === 'default');
1321
- const firstMode = this.collaborationModes[0]?.mode;
1322
- if (!firstMode) {
1323
- throw new Error('Codex collaborationMode/list returned an invalid mode entry');
1324
- }
1325
- return preferredDefault?.mode ?? firstMode;
633
+ return resolveDefaultCollaborationMode(this.collaborationModes);
1326
634
  }
1327
635
  resolveTurnCollaborationMode(session) {
1328
- const modeEntry = this.collaborationModes.find((entry) => entry.mode === session.defaults.collaborationMode);
1329
- return {
1330
- mode: modeEntry?.mode ?? session.defaults.collaborationMode,
1331
- settings: {
1332
- model: modeEntry?.model ?? session.defaults.model,
1333
- reasoning_effort: modeEntry?.reasoningEffort ?? session.defaults.reasoningEffort,
1334
- developer_instructions: modeEntry?.developerInstructions ?? null,
1335
- },
1336
- };
636
+ return resolveTurnCollaborationMode(this.collaborationModes, session);
1337
637
  }
1338
638
  resolveReasoningEffortForModel(modelId, candidateReasoningEffort) {
1339
- const modelEntry = this.modelCatalog.find((entry) => entry.id === modelId);
1340
- if (!modelEntry) {
1341
- return null;
1342
- }
1343
- const supportedEntries = modelEntry.supportedReasoningEfforts.filter((entry) => isNonEmptyString(entry.reasoningEffort));
1344
- if (supportedEntries.length === 0) {
1345
- return null;
1346
- }
1347
- const supportedValues = dedupeStrings(supportedEntries.map((entry) => entry.reasoningEffort));
1348
- if (isNonEmptyString(candidateReasoningEffort) &&
1349
- supportedValues.includes(candidateReasoningEffort)) {
1350
- return candidateReasoningEffort;
1351
- }
1352
- if (supportedValues.includes(modelEntry.defaultReasoningEffort)) {
1353
- return modelEntry.defaultReasoningEffort;
1354
- }
1355
- return supportedValues[0] ?? null;
639
+ return resolveReasoningEffortForModel(this.modelCatalog, modelId, candidateReasoningEffort);
1356
640
  }
1357
641
  getCollaborationModeValues(currentMode) {
1358
- const values = this.collaborationModes
1359
- .map((entry) => entry.mode)
1360
- .filter((mode) => isNonEmptyString(mode));
1361
- if (!values.includes(currentMode)) {
1362
- values.unshift(currentMode);
1363
- }
1364
- return dedupeStrings(values);
1365
- }
1366
- resolveCurrentSandboxMode(session) {
1367
- const currentSandboxMode = parseSandboxModeFromPolicy(session.defaults.sandboxPolicy);
1368
- if (currentSandboxMode) {
1369
- return currentSandboxMode;
1370
- }
1371
- const allowedSandboxMode = this.allowedSandboxModes[0];
1372
- if (allowedSandboxMode) {
1373
- return allowedSandboxMode;
1374
- }
1375
- throw new Error('Unable to resolve current sandbox mode for execution-mode options');
642
+ return getCollaborationModeValues(this.collaborationModes, currentMode);
1376
643
  }
1377
644
  getExecutionPresets(session) {
1378
- const currentSandboxMode = this.resolveCurrentSandboxMode(session);
1379
- const policies = this.allowedApprovalPolicies.length > 0
1380
- ? this.allowedApprovalPolicies
1381
- : [session.defaults.approvalPolicy];
1382
- const sandboxModes = this.allowedSandboxModes.length > 0 ? this.allowedSandboxModes : [currentSandboxMode];
1383
- const presets = [];
1384
- const seen = new Set();
1385
- const addPreset = (approvalPolicy, sandboxMode, description) => {
1386
- const id = toExecutionPresetId(approvalPolicy, sandboxMode);
1387
- if (seen.has(id)) {
1388
- return;
1389
- }
1390
- seen.add(id);
1391
- presets.push({
1392
- id,
1393
- name: formatExecutionPresetName(approvalPolicy, sandboxMode),
1394
- ...(description ? { description } : {}),
1395
- approvalPolicy,
1396
- sandboxMode,
1397
- });
1398
- };
1399
- addPreset(session.defaults.approvalPolicy, currentSandboxMode, `Current session: ${formatExecutionPresetName(session.defaults.approvalPolicy, currentSandboxMode)}`);
1400
- for (const policy of policies) {
1401
- for (const sandboxMode of sandboxModes) {
1402
- addPreset(policy, sandboxMode);
1403
- }
1404
- }
1405
- return presets;
1406
- }
1407
- resolveExecutionPresetId(session, presets) {
1408
- const currentSandboxMode = this.resolveCurrentSandboxMode(session);
1409
- const currentPresetId = toExecutionPresetId(session.defaults.approvalPolicy, currentSandboxMode);
1410
- const fallbackPresetId = presets[0]?.id;
1411
- if (!fallbackPresetId) {
1412
- throw new Error('Execution-mode presets are unavailable for this session');
1413
- }
1414
- return presets.some((preset) => preset.id === currentPresetId)
1415
- ? currentPresetId
1416
- : fallbackPresetId;
645
+ return getExecutionPresets(session, this.allowedApprovalPolicies, this.allowedSandboxModes);
1417
646
  }
1418
647
  requireSession(sessionId) {
1419
- const session = this.sessions.get(sessionId);
648
+ const session = this.stateContainer.getSession(sessionId);
1420
649
  if (!session) {
1421
650
  throw RequestError.invalidParams({ sessionId });
1422
651
  }
1423
652
  return session;
1424
653
  }
1425
- async loadConfigRequirements() {
1426
- const raw = await this.codex.request('configRequirements/read', undefined);
1427
- const parsed = configRequirementsReadResponseSchema.parse(raw);
1428
- const requirements = parsed.requirements;
1429
- const allowedApprovalPolicies = dedupeStrings((requirements?.allowedApprovalPolicies ?? []).filter(isNonEmptyString));
1430
- const allowedSandboxModes = dedupeStrings((requirements?.allowedSandboxModes ?? []).filter((mode) => mode === 'read-only' || mode === 'workspace-write' || mode === 'danger-full-access'));
1431
- const hasExplicitApprovalPolicies = Array.isArray(requirements?.allowedApprovalPolicies);
1432
- const hasExplicitSandboxModes = Array.isArray(requirements?.allowedSandboxModes);
1433
- return {
1434
- allowedApprovalPolicies: allowedApprovalPolicies.length > 0
1435
- ? allowedApprovalPolicies
1436
- : hasExplicitApprovalPolicies
1437
- ? []
1438
- : DEFAULT_APPROVAL_POLICIES,
1439
- allowedSandboxModes: allowedSandboxModes.length > 0
1440
- ? allowedSandboxModes
1441
- : hasExplicitSandboxModes
1442
- ? []
1443
- : DEFAULT_SANDBOX_MODES,
1444
- };
1445
- }
1446
- async loadCollaborationModes() {
1447
- const entries = [];
1448
- let cursor = null;
1449
- for (;;) {
1450
- const response = await this.requestCollaborationModeListWithRetry(cursor);
1451
- entries.push(...response.data.flatMap((entry) => isNonEmptyString(entry.mode)
1452
- ? [
1453
- {
1454
- mode: entry.mode,
1455
- name: entry.name,
1456
- model: entry.model ?? null,
1457
- reasoningEffort: entry.reasoning_effort ?? null,
1458
- developerInstructions: entry.developer_instructions ?? null,
1459
- },
1460
- ]
1461
- : []));
1462
- cursor = response.nextCursor ?? null;
1463
- if (!cursor) {
1464
- break;
1465
- }
1466
- }
1467
- if (entries.length === 0) {
1468
- throw new Error('Codex collaborationMode/list returned no modes');
1469
- }
1470
- return entries;
1471
- }
1472
- async requestCollaborationModeListWithRetry(cursor, maxAttempts = 3) {
1473
- let attempt = 0;
1474
- let lastError;
1475
- while (attempt < maxAttempts) {
1476
- attempt += 1;
1477
- try {
1478
- const raw = await this.codex.request('collaborationMode/list', cursor ? { cursor } : {});
1479
- return collaborationModeListResponseSchema.parse(raw);
1480
- }
1481
- catch (error) {
1482
- lastError = error;
1483
- if (!(error instanceof CodexRequestError) ||
1484
- error.code !== -32_001 ||
1485
- attempt >= maxAttempts) {
1486
- throw error;
1487
- }
1488
- const delayMs = Math.round(2 ** attempt * 100 + Math.random() * 120);
1489
- await new Promise((resolve) => setTimeout(resolve, delayMs));
1490
- }
1491
- }
1492
- throw lastError;
1493
- }
1494
- async loadModelCatalog() {
1495
- const models = [];
1496
- let cursor = null;
1497
- for (;;) {
1498
- const response = await this.requestModelListWithRetry(cursor);
1499
- models.push(...response.data.map((model) => ({
1500
- id: model.id,
1501
- displayName: model.displayName,
1502
- description: model.description,
1503
- defaultReasoningEffort: model.defaultReasoningEffort,
1504
- supportedReasoningEfforts: (model.supportedReasoningEfforts ?? [])
1505
- .filter((entry) => isNonEmptyString(entry.reasoningEffort))
1506
- .map((entry) => ({
1507
- reasoningEffort: entry.reasoningEffort,
1508
- description: entry.description,
1509
- })),
1510
- inputModalities: model.inputModalities ?? [],
1511
- isDefault: model.isDefault ?? false,
1512
- })));
1513
- cursor = response.nextCursor ?? null;
1514
- if (!cursor) {
1515
- return models;
1516
- }
1517
- }
1518
- }
1519
- async requestModelListWithRetry(cursor, maxAttempts = 3) {
1520
- let attempt = 0;
1521
- let lastError;
1522
- while (attempt < maxAttempts) {
1523
- attempt += 1;
1524
- try {
1525
- const raw = await this.codex.request('model/list', cursor ? { cursor } : {});
1526
- return modelListResponseSchema.parse(raw);
1527
- }
1528
- catch (error) {
1529
- lastError = error;
1530
- if (!(error instanceof CodexRequestError) ||
1531
- error.code !== -32_001 ||
1532
- attempt >= maxAttempts) {
1533
- throw error;
1534
- }
1535
- const delayMs = Math.round(2 ** attempt * 100 + Math.random() * 120);
1536
- await new Promise((resolve) => setTimeout(resolve, delayMs));
1537
- }
1538
- }
1539
- throw lastError;
1540
- }
1541
654
  async replayThreadHistory(sessionId, threadId) {
1542
- const session = this.requireSession(sessionId);
1543
- const threadReadRaw = await this.codex.request('thread/read', {
1544
- threadId,
1545
- includeTurns: true,
1546
- });
1547
- const threadRead = threadReadResponseSchema.parse(threadReadRaw);
1548
- for (const turn of threadRead.thread.turns) {
1549
- for (const item of turn.items) {
1550
- await this.replayThreadHistoryItem(session, sessionId, turn.id, item);
1551
- }
1552
- }
1553
- }
1554
- async replayThreadHistoryItem(session, sessionId, turnId, item) {
1555
- if (item.type === 'userMessage') {
1556
- await this.replayUserMessageHistoryItem(sessionId, item);
1557
- return;
1558
- }
1559
- if (item.type === 'agentMessage') {
1560
- await this.replayAgentMessageHistoryItem(sessionId, item);
1561
- return;
1562
- }
1563
- await this.replayToolLikeHistoryItem(session, sessionId, turnId, item);
1564
- }
1565
- async replayUserMessageHistoryItem(sessionId, item) {
1566
- const contentBlocks = Array.isArray(item.content) ? item.content : [];
1567
- for (const content of contentBlocks) {
1568
- if (!isRecord(content) || content.type !== 'text' || typeof content.text !== 'string') {
1569
- continue;
1570
- }
1571
- await this.emitSessionUpdate(sessionId, {
1572
- sessionUpdate: 'user_message_chunk',
1573
- content: { type: 'text', text: content.text },
1574
- });
1575
- }
1576
- }
1577
- async replayAgentMessageHistoryItem(sessionId, item) {
1578
- const text = asString(item.text);
1579
- if (!text) {
1580
- return;
1581
- }
1582
- await this.emitSessionUpdate(sessionId, {
1583
- sessionUpdate: 'agent_message_chunk',
1584
- content: { type: 'text', text },
1585
- });
1586
- }
1587
- async replayToolLikeHistoryItem(session, sessionId, turnId, item) {
1588
- if (item.type === 'reasoning') {
1589
- await this.emitSessionUpdate(sessionId, {
1590
- sessionUpdate: 'tool_call',
1591
- toolCallId: resolveToolCallId({ itemId: item.id, source: item }),
1592
- title: 'reasoning',
1593
- kind: 'think',
1594
- status: 'completed',
1595
- rawInput: item,
1596
- rawOutput: item,
1597
- });
1598
- await this.emitReasoningThoughtChunkFromItem(sessionId, item);
1599
- session.replayedTurnItemKeys.add(toTurnItemKey(turnId, item.id));
1600
- return;
1601
- }
1602
- const toolInfo = this.buildToolCallState(session, item, turnId);
1603
- if (!toolInfo) {
1604
- this.reportShapeDrift('unhandled_replay_item', {
1605
- turnId,
1606
- itemType: item.type,
1607
- itemId: item.id,
1608
- });
1609
- return;
1610
- }
1611
- await this.emitSessionUpdate(sessionId, {
1612
- sessionUpdate: 'tool_call',
1613
- toolCallId: toolInfo.toolCallId,
1614
- title: toolInfo.title,
1615
- kind: toolInfo.kind,
1616
- status: 'completed',
1617
- rawInput: item,
1618
- rawOutput: item,
1619
- });
1620
- session.replayedTurnItemKeys.add(toTurnItemKey(turnId, item.id));
655
+ await this.streamEventHandler.replayThreadHistory(sessionId, threadId);
1621
656
  }
1622
657
  async handleCodexNotification(method, params) {
1623
- const parsed = knownCodexNotificationSchema.safeParse({ method, params });
1624
- if (!parsed.success) {
1625
- this.reportShapeDrift('malformed_notification', {
1626
- method,
1627
- issues: parsed.error.issues.slice(0, 3).map((issue) => issue.message),
1628
- });
1629
- return;
1630
- }
1631
- const notification = parsed.data;
1632
- if (notification.method === 'error' || notification.method === 'turn/started') {
1633
- return;
1634
- }
1635
- const sessionId = this.sessionIdByThreadId.get(notification.params.threadId);
1636
- if (!sessionId) {
1637
- return;
1638
- }
1639
- const session = this.sessions.get(sessionId);
1640
- if (!session) {
1641
- return;
1642
- }
1643
- if (notification.method === 'item/agentMessage/delta') {
1644
- await this.emitSessionUpdate(sessionId, {
1645
- sessionUpdate: 'agent_message_chunk',
1646
- content: {
1647
- type: 'text',
1648
- text: notification.params.delta,
1649
- },
1650
- });
1651
- return;
1652
- }
1653
- if (notification.method === 'item/plan/delta') {
1654
- await this.handlePlanDelta(sessionId, session, notification.params.itemId, notification.params.delta);
1655
- return;
1656
- }
1657
- if (notification.method === 'item/reasoning/summaryTextDelta') {
1658
- await this.emitReasoningThoughtDelta(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.delta);
1659
- return;
1660
- }
1661
- if (notification.method === 'item/commandExecution/outputDelta') {
1662
- await this.emitToolCallProgress(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.delta, 'commandExecution');
1663
- return;
1664
- }
1665
- if (notification.method === 'item/fileChange/outputDelta') {
1666
- await this.emitToolCallProgress(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.delta, 'fileChange');
1667
- return;
1668
- }
1669
- if (notification.method === 'item/mcpToolCall/progress') {
1670
- await this.emitToolCallProgress(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.message, 'mcpToolCall');
1671
- return;
1672
- }
1673
- if (notification.method === 'item/started') {
1674
- await this.handleItemStarted(session, notification.params.item, notification.params.turnId);
1675
- return;
1676
- }
1677
- if (notification.method === 'item/completed') {
1678
- await this.handleItemCompleted(session, notification.params.item, notification.params.turnId);
1679
- return;
1680
- }
1681
- if (notification.method === 'turn/completed') {
1682
- await this.handleTurnCompletedNotification(session, notification.params.turn.id, notification.params.turn.status, notification.params.turn.error?.message);
1683
- }
1684
- }
1685
- async handlePlanDelta(sessionId, session, itemId, delta) {
1686
- const previous = session.planTextByItemId.get(itemId) ?? '';
1687
- const next = `${previous}${delta}`;
1688
- session.planTextByItemId.set(itemId, next);
1689
- await this.emitSessionUpdate(sessionId, {
1690
- sessionUpdate: 'plan',
1691
- entries: [
1692
- {
1693
- content: next,
1694
- priority: 'medium',
1695
- status: 'in_progress',
1696
- },
1697
- ],
1698
- });
658
+ await this.streamEventHandler.handleCodexNotification({ method, params });
1699
659
  }
1700
660
  async emitReasoningThoughtChunkFromItem(sessionId, item) {
1701
661
  const text = extractReasoningTextLocal(item);
@@ -1707,262 +667,11 @@ export class CodexAppServerAcpAdapter {
1707
667
  content: { type: 'text', text },
1708
668
  });
1709
669
  }
1710
- isReplayedTurnItem(session, turnId, itemId) {
1711
- return session.replayedTurnItemKeys.has(toTurnItemKey(turnId, itemId));
1712
- }
1713
- async emitReasoningThoughtDelta(sessionId, session, turnId, itemId, delta) {
1714
- if (this.isReplayedTurnItem(session, turnId, itemId)) {
1715
- return;
1716
- }
1717
- if (delta.length === 0) {
1718
- return;
1719
- }
1720
- const existing = session.toolCallsByItemId.get(itemId);
1721
- if (!existing) {
1722
- const toolCallId = resolveToolCallId({
1723
- itemId,
1724
- });
1725
- session.toolCallsByItemId.set(itemId, {
1726
- toolCallId,
1727
- title: 'reasoning',
1728
- kind: 'think',
1729
- locations: [],
1730
- });
1731
- await this.emitSessionUpdate(sessionId, {
1732
- sessionUpdate: 'tool_call',
1733
- toolCallId,
1734
- title: 'reasoning',
1735
- kind: 'think',
1736
- status: 'pending',
1737
- rawInput: {
1738
- type: 'reasoning',
1739
- id: itemId,
1740
- },
1741
- });
1742
- await this.emitSessionUpdate(sessionId, {
1743
- sessionUpdate: 'tool_call_update',
1744
- toolCallId,
1745
- title: 'reasoning',
1746
- kind: 'think',
1747
- status: 'in_progress',
1748
- });
1749
- }
1750
- session.reasoningDeltaItemIds.add(itemId);
1751
- await this.emitSessionUpdate(sessionId, {
1752
- sessionUpdate: 'agent_thought_chunk',
1753
- content: { type: 'text', text: delta },
1754
- });
1755
- }
1756
- async emitToolCallProgress(sessionId, session, turnId, itemId, output, source) {
1757
- if (this.isReplayedTurnItem(session, turnId, itemId)) {
1758
- return;
1759
- }
1760
- const toolCall = session.toolCallsByItemId.get(itemId);
1761
- if (!toolCall) {
1762
- this.reportShapeDrift('tool_progress_without_tool_call', { turnId, itemId });
1763
- return;
1764
- }
1765
- if (session.syntheticallyCompletedToolItemIds.has(itemId)) {
1766
- return;
1767
- }
1768
- if (source === 'commandExecution' && isCommandExecutionSessionHandoffOutput(output)) {
1769
- session.syntheticallyCompletedToolItemIds.add(itemId);
1770
- await this.emitSessionUpdate(sessionId, {
1771
- sessionUpdate: 'tool_call_update',
1772
- toolCallId: toolCall.toolCallId,
1773
- status: 'completed',
1774
- kind: toolCall.kind,
1775
- title: toolCall.title,
1776
- ...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
1777
- rawOutput: output,
1778
- });
1779
- return;
1780
- }
1781
- await this.emitSessionUpdate(sessionId, {
1782
- sessionUpdate: 'tool_call_update',
1783
- toolCallId: toolCall.toolCallId,
1784
- status: 'in_progress',
1785
- ...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
1786
- rawOutput: output,
1787
- });
1788
- }
1789
- async handleTurnCompletedNotification(session, turnId, status, errorMessage) {
1790
- if (status === 'inProgress') {
1791
- return;
1792
- }
1793
- const completionStatus = status;
1794
- if (this.shouldDeferTurnCompletion(session, turnId, completionStatus)) {
1795
- session.pendingTurnCompletionsByTurnId.set(turnId, this.buildPendingTurnCompletion(completionStatus, errorMessage));
1796
- return;
1797
- }
1798
- await this.finalizeTurnCompletion(session, completionStatus, errorMessage);
1799
- }
1800
- shouldDeferTurnCompletion(session, turnId, status) {
1801
- if (!session.activeTurn || session.activeTurn.turnId !== turnId) {
1802
- return true;
1803
- }
1804
- return status !== 'interrupted' && this.hasPendingPlanApprovals(session, turnId);
1805
- }
1806
- buildPendingTurnCompletion(status, errorMessage) {
1807
- const stopReason = status === 'interrupted' ? 'cancelled' : 'end_turn';
1808
- if (status === 'failed' && errorMessage) {
1809
- return { stopReason, errorMessage };
1810
- }
1811
- return { stopReason };
1812
- }
1813
- async finalizeTurnCompletion(session, status, errorMessage) {
1814
- if (status === 'interrupted') {
1815
- this.settleTurn(session, 'cancelled');
1816
- return;
1817
- }
1818
- if (status === 'failed' && errorMessage) {
1819
- await this.emitTurnFailureMessage(session.sessionId, errorMessage);
1820
- }
1821
- if (status === 'failed') {
1822
- this.settleTurn(session, 'end_turn');
1823
- return;
1824
- }
1825
- this.settleTurn(session, session.activeTurn?.cancelRequested ? 'cancelled' : 'end_turn');
1826
- }
1827
- async handleItemStarted(session, item, turnId) {
1828
- if (this.isReplayedTurnItem(session, turnId, item.id)) {
1829
- return;
1830
- }
1831
- if (item.type === 'reasoning') {
1832
- const existing = session.toolCallsByItemId.get(item.id);
1833
- const toolInfo = existing ??
1834
- {
1835
- toolCallId: resolveToolCallId({
1836
- itemId: item.id,
1837
- source: item,
1838
- }),
1839
- title: 'reasoning',
1840
- kind: 'think',
1841
- locations: [],
1842
- };
1843
- if (!existing) {
1844
- session.syntheticallyCompletedToolItemIds.delete(item.id);
1845
- session.toolCallsByItemId.set(item.id, toolInfo);
1846
- await this.emitSessionUpdate(session.sessionId, {
1847
- sessionUpdate: 'tool_call',
1848
- toolCallId: toolInfo.toolCallId,
1849
- title: toolInfo.title,
1850
- kind: toolInfo.kind,
1851
- status: 'pending',
1852
- rawInput: item,
1853
- });
1854
- }
1855
- await this.emitSessionUpdate(session.sessionId, {
1856
- sessionUpdate: 'tool_call_update',
1857
- toolCallId: toolInfo.toolCallId,
1858
- title: toolInfo.title,
1859
- kind: toolInfo.kind,
1860
- status: 'in_progress',
1861
- });
1862
- return;
1863
- }
1864
- const toolInfo = this.buildToolCallState(session, item, turnId);
1865
- if (!toolInfo) {
1866
- this.reportShapeDrift('unhandled_item_started_type', {
1867
- turnId,
1868
- itemType: item.type,
1869
- itemId: item.id,
1870
- });
1871
- return;
1872
- }
1873
- session.syntheticallyCompletedToolItemIds.delete(item.id);
1874
- session.toolCallsByItemId.set(item.id, toolInfo);
1875
- await this.emitSessionUpdate(session.sessionId, {
1876
- sessionUpdate: 'tool_call',
1877
- toolCallId: toolInfo.toolCallId,
1878
- title: toolInfo.title,
1879
- kind: toolInfo.kind,
1880
- status: 'pending',
1881
- ...(toolInfo.locations.length > 0 ? { locations: toolInfo.locations } : {}),
1882
- rawInput: item,
1883
- });
1884
- const itemStatus = toToolStatus(item.status);
1885
- if (itemStatus === 'in_progress') {
1886
- await this.emitSessionUpdate(session.sessionId, {
1887
- sessionUpdate: 'tool_call_update',
1888
- toolCallId: toolInfo.toolCallId,
1889
- status: 'in_progress',
1890
- });
1891
- }
1892
- }
1893
- async handleItemCompleted(session, item, turnId) {
1894
- if (this.isReplayedTurnItem(session, turnId, item.id)) {
1895
- return;
1896
- }
1897
- if (item.type === 'reasoning') {
1898
- const existing = session.toolCallsByItemId.get(item.id);
1899
- const reasoningToolCallId = existing?.toolCallId ??
1900
- resolveToolCallId({
1901
- itemId: item.id,
1902
- source: item,
1903
- });
1904
- if (existing) {
1905
- await this.emitSessionUpdate(session.sessionId, {
1906
- sessionUpdate: 'tool_call_update',
1907
- toolCallId: reasoningToolCallId,
1908
- title: existing.title,
1909
- kind: existing.kind,
1910
- status: toToolStatus(item.status) ?? 'completed',
1911
- rawOutput: item,
1912
- });
1913
- }
1914
- else {
1915
- await this.emitSessionUpdate(session.sessionId, {
1916
- sessionUpdate: 'tool_call',
1917
- toolCallId: reasoningToolCallId,
1918
- title: 'reasoning',
1919
- kind: 'think',
1920
- status: toToolStatus(item.status) ?? 'completed',
1921
- rawInput: item,
1922
- rawOutput: item,
1923
- });
1924
- }
1925
- session.toolCallsByItemId.delete(item.id);
1926
- session.syntheticallyCompletedToolItemIds.delete(item.id);
1927
- const sawDelta = session.reasoningDeltaItemIds.has(item.id);
1928
- session.reasoningDeltaItemIds.delete(item.id);
1929
- if (!sawDelta) {
1930
- await this.emitReasoningThoughtChunkFromItem(session.sessionId, item);
1931
- }
1932
- return;
1933
- }
1934
- const existing = session.toolCallsByItemId.get(item.id);
1935
- if (!existing) {
1936
- this.reportShapeDrift('item_completed_without_started_state', {
1937
- turnId,
1938
- itemType: item.type,
1939
- itemId: item.id,
1940
- });
1941
- return;
1942
- }
1943
- const shouldHoldTurnForPlanApproval = item.type === 'plan' &&
670
+ shouldHoldTurnForPlanApproval(session, item, turnId) {
671
+ return (item.type === 'plan' &&
1944
672
  isPlanLikeMode(session.defaults.collaborationMode) &&
1945
673
  !session.planApprovalRequestedByTurnId.has(turnId) &&
1946
- this.extractPlanApprovalText(session, item) !== null;
1947
- if (shouldHoldTurnForPlanApproval) {
1948
- this.holdTurnUntilPlanApprovalResolves(session, turnId);
1949
- }
1950
- const statusFromItem = toToolStatus(item.status);
1951
- const status = statusFromItem ?? 'completed';
1952
- const completionLocations = this.extractLocations(item);
1953
- const locations = dedupeLocations([...existing.locations, ...completionLocations]);
1954
- await this.emitSessionUpdate(session.sessionId, {
1955
- sessionUpdate: 'tool_call_update',
1956
- toolCallId: existing.toolCallId,
1957
- status,
1958
- kind: existing.kind,
1959
- title: existing.title,
1960
- ...(locations.length > 0 ? { locations } : {}),
1961
- rawOutput: item,
1962
- });
1963
- session.toolCallsByItemId.delete(item.id);
1964
- session.syntheticallyCompletedToolItemIds.delete(item.id);
1965
- await this.maybeRequestPlanApproval(session, item, turnId, existing);
674
+ this.extractPlanApprovalText(session, item) !== null);
1966
675
  }
1967
676
  buildPlanApprovalInput(planText, sourceItemId) {
1968
677
  return {
@@ -2001,11 +710,7 @@ export class CodexAppServerAcpAdapter {
2001
710
  return left.localeCompare(right);
2002
711
  }
2003
712
  resolveCollaborationModeLabel(modeId) {
2004
- const entry = this.collaborationModes.find((candidate) => candidate.mode === modeId);
2005
- if (entry?.name) {
2006
- return entry.name;
2007
- }
2008
- return sanitizeModeName(modeId);
713
+ return resolveCollaborationModeLabel(this.collaborationModes, modeId);
2009
714
  }
2010
715
  buildPlanApprovalOptions(session) {
2011
716
  const currentMode = session.defaults.collaborationMode;
@@ -2145,27 +850,6 @@ export class CodexAppServerAcpAdapter {
2145
850
  await this.releaseTurnHoldForPlanApproval(session, turnId);
2146
851
  }
2147
852
  }
2148
- extractLocations(item) {
2149
- if (!isRecord(item) || item.type !== 'fileChange') {
2150
- return [];
2151
- }
2152
- const changes = item.changes;
2153
- if (!Array.isArray(changes)) {
2154
- return [];
2155
- }
2156
- const locations = [];
2157
- for (const change of changes) {
2158
- if (!isRecord(change)) {
2159
- continue;
2160
- }
2161
- const path = asString(change.path);
2162
- if (!path) {
2163
- continue;
2164
- }
2165
- locations.push({ path });
2166
- }
2167
- return locations;
2168
- }
2169
853
  buildToolCallState(session, item, _turnId) {
2170
854
  const kindByType = {
2171
855
  commandExecution: 'execute',
@@ -2191,7 +875,7 @@ export class CodexAppServerAcpAdapter {
2191
875
  }
2192
876
  else if (item.type === 'fileChange') {
2193
877
  title = 'fileChange';
2194
- locations = this.extractLocations(item);
878
+ locations = extractLocations(item);
2195
879
  }
2196
880
  else if (item.type === 'mcpToolCall') {
2197
881
  const server = asString(item.server) ?? 'mcp';
@@ -2212,280 +896,15 @@ export class CodexAppServerAcpAdapter {
2212
896
  locations,
2213
897
  };
2214
898
  }
2215
- buildPermissionOptions(params) {
2216
- if (params.method === 'item/tool/requestUserInput') {
2217
- return buildToolUserInputPermissionOptions(params.questions);
2218
- }
2219
- if (params.method === 'item/commandExecution/requestApproval') {
2220
- return [
2221
- {
2222
- optionId: 'allow_always',
2223
- name: 'Allow for session',
2224
- kind: 'allow_always',
2225
- },
2226
- {
2227
- optionId: 'allow_once',
2228
- name: 'Allow once',
2229
- kind: 'allow_once',
2230
- },
2231
- {
2232
- optionId: 'reject_once',
2233
- name: 'Reject',
2234
- kind: 'reject_once',
2235
- },
2236
- ];
2237
- }
2238
- return [
2239
- {
2240
- optionId: 'allow_once',
2241
- name: 'Allow once',
2242
- kind: 'allow_once',
2243
- },
2244
- {
2245
- optionId: 'reject_once',
2246
- name: 'Reject',
2247
- kind: 'reject_once',
2248
- },
2249
- ];
2250
- }
2251
- async maybeAutoApproveCommandRequest(params) {
2252
- if (params.request.method !== 'item/commandExecution/requestApproval') {
2253
- return false;
2254
- }
2255
- const scopeKey = buildCommandApprovalScopeKey({
2256
- command: asString(params.request.params.command),
2257
- cwd: asString(params.request.params.cwd) ?? params.session.cwd,
2258
- });
2259
- if (!(scopeKey && params.session.commandApprovalScopes.has(scopeKey))) {
2260
- return false;
2261
- }
2262
- await this.respondToCodexPermissionRequest({
2263
- request: params.request,
2264
- permission: {
2265
- outcome: { outcome: 'selected', optionId: 'allow_always' },
2266
- },
2267
- session: params.session,
2268
- toolCallId: params.toolCallId,
2269
- questions: [],
2270
- });
2271
- return true;
2272
- }
2273
899
  async handleCodexServerRequest(request) {
2274
- try {
2275
- const parsed = knownCodexServerRequestSchema.safeParse(request);
2276
- if (!parsed.success) {
2277
- this.reportShapeDrift('malformed_server_request', {
2278
- method: request.method,
2279
- issues: parsed.error.issues.slice(0, 3).map((issue) => issue.message),
2280
- });
2281
- this.codex.respondError(request.id, {
2282
- code: -32_602,
2283
- message: 'Unsupported codex server request payload',
2284
- });
2285
- return;
2286
- }
2287
- const typed = parsed.data;
2288
- const sessionId = this.sessionIdByThreadId.get(typed.params.threadId);
2289
- if (!sessionId) {
2290
- this.reportShapeDrift('request_for_unknown_thread', {
2291
- method: typed.method,
2292
- threadId: typed.params.threadId,
2293
- itemId: typed.params.itemId,
2294
- });
2295
- this.codex.respondError(typed.id, {
2296
- code: -32_603,
2297
- message: 'No ACP session mapped for this thread',
2298
- });
2299
- return;
2300
- }
2301
- const session = this.sessions.get(sessionId);
2302
- if (!session) {
2303
- this.reportShapeDrift('request_for_missing_session', {
2304
- method: typed.method,
2305
- sessionId,
2306
- itemId: typed.params.itemId,
2307
- });
2308
- this.codex.respondError(typed.id, {
2309
- code: -32_603,
2310
- message: 'No ACP session mapped for this thread',
2311
- });
2312
- return;
2313
- }
2314
- const existingTool = session.toolCallsByItemId.get(typed.params.itemId);
2315
- const toolCall = existingTool ??
2316
- this.buildApprovalToolCallState(session, typed.method, typed.params.itemId, typed.params.turnId, typed.params);
2317
- session.toolCallsByItemId.set(typed.params.itemId, toolCall);
2318
- if (!existingTool) {
2319
- await this.emitSessionUpdate(sessionId, {
2320
- sessionUpdate: 'tool_call',
2321
- toolCallId: toolCall.toolCallId,
2322
- title: toolCall.title,
2323
- kind: toolCall.kind,
2324
- status: 'pending',
2325
- ...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
2326
- rawInput: typed.params,
2327
- });
2328
- }
2329
- if (await this.maybeAutoApproveCommandRequest({
2330
- request: typed,
2331
- session,
2332
- toolCallId: toolCall.toolCallId,
2333
- })) {
2334
- return;
2335
- }
2336
- const questions = typed.method === 'item/tool/requestUserInput' ? typed.params.questions : [];
2337
- const permissionOptions = this.buildPermissionOptions({
2338
- method: typed.method,
2339
- questions,
2340
- });
2341
- await this.emitSessionUpdate(sessionId, {
2342
- sessionUpdate: 'tool_call_update',
2343
- toolCallId: toolCall.toolCallId,
2344
- title: toolCall.title,
2345
- kind: toolCall.kind,
2346
- status: 'pending',
2347
- ...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
2348
- });
2349
- const permissionResult = await this.connection.requestPermission({
2350
- sessionId,
2351
- toolCall: {
2352
- toolCallId: toolCall.toolCallId,
2353
- title: toolCall.title,
2354
- kind: toolCall.kind,
2355
- status: 'pending',
2356
- rawInput: typed.params,
2357
- },
2358
- options: permissionOptions,
2359
- });
2360
- await this.respondToCodexPermissionRequest({
2361
- request: typed,
2362
- permission: permissionResult,
2363
- session,
2364
- toolCallId: toolCall.toolCallId,
2365
- questions,
2366
- });
2367
- }
2368
- catch (error) {
2369
- const message = error instanceof Error ? error.message : String(error);
2370
- this.codex.respondError(request.id, {
2371
- code: -32_600,
2372
- message: 'Failed to process codex approval request',
2373
- data: { error: message },
2374
- });
2375
- }
2376
- }
2377
- buildApprovalToolCallState(session, method, itemId, _turnId, params) {
2378
- if (method === 'item/commandExecution/requestApproval') {
2379
- const command = asString(params.command);
2380
- const cwd = asString(params.cwd) ?? session.cwd;
2381
- const parsed = resolveCommandDisplay({ command, cwd });
2382
- return {
2383
- toolCallId: resolveToolCallId({
2384
- itemId,
2385
- source: params,
2386
- }),
2387
- title: parsed.title,
2388
- kind: parsed.kind,
2389
- locations: parsed.locations,
2390
- };
2391
- }
2392
- if (method === 'item/fileChange/requestApproval') {
2393
- const grantRoot = asString(params.grantRoot);
2394
- return {
2395
- toolCallId: resolveToolCallId({
2396
- itemId,
2397
- source: params,
2398
- }),
2399
- title: 'fileChange',
2400
- kind: 'edit',
2401
- locations: grantRoot ? [{ path: grantRoot }] : [],
2402
- };
2403
- }
2404
- return {
2405
- toolCallId: resolveToolCallId({
2406
- itemId,
2407
- source: params,
2408
- }),
2409
- title: 'item/tool/requestUserInput',
2410
- kind: 'other',
2411
- locations: [],
2412
- };
2413
- }
2414
- isAllowedPermissionSelection(selectedOptionId) {
2415
- return selectedOptionId === 'allow_once' || selectedOptionId === 'allow_always';
2416
- }
2417
- async handleToolUserInputPermissionResponse(params) {
2418
- if (params.request.method !== 'item/tool/requestUserInput') {
2419
- return false;
2420
- }
2421
- const rejected = params.selectedOptionId === null || params.selectedOptionId === 'reject_once';
2422
- let answers;
2423
- try {
2424
- answers = buildToolUserInputAnswers({
2425
- questions: params.questions,
2426
- permission: params.permission,
2427
- selectedOptionId: params.selectedOptionId,
2428
- });
2429
- }
2430
- catch (error) {
2431
- const message = error instanceof Error ? error.message : String(error);
2432
- this.codex.respondError(params.request.id, {
2433
- code: -32_602,
2434
- message: 'Failed to map requestUserInput answers',
2435
- data: { error: message },
2436
- });
2437
- await this.emitSessionUpdate(params.session.sessionId, {
2438
- sessionUpdate: 'tool_call_update',
2439
- toolCallId: params.toolCallId,
2440
- status: 'failed',
2441
- rawOutput: { error: message },
2442
- });
2443
- return true;
2444
- }
2445
- this.codex.respondSuccess(params.request.id, {
2446
- answers,
2447
- });
2448
- await this.emitSessionUpdate(params.session.sessionId, {
2449
- sessionUpdate: 'tool_call_update',
2450
- toolCallId: params.toolCallId,
2451
- status: rejected ? 'failed' : 'completed',
2452
- rawOutput: rejected ? { outcome: 'rejected' } : { answers },
2453
- });
2454
- return true;
2455
- }
2456
- async respondToCodexPermissionRequest(params) {
2457
- const selected = params.permission.outcome.outcome === 'selected' ? params.permission.outcome.optionId : null;
2458
- if (await this.handleToolUserInputPermissionResponse({
2459
- ...params,
2460
- selectedOptionId: selected,
2461
- })) {
2462
- return;
2463
- }
2464
- if (params.request.method === 'item/commandExecution/requestApproval' &&
2465
- selected === 'allow_always') {
2466
- const scopeKey = buildCommandApprovalScopeKey({
2467
- command: asString(params.request.params.command),
2468
- cwd: asString(params.request.params.cwd) ?? params.session.cwd,
2469
- });
2470
- if (scopeKey) {
2471
- params.session.commandApprovalScopes.add(scopeKey);
2472
- }
2473
- else {
2474
- this.reportShapeDrift('allow_always_without_scope_key', {
2475
- itemId: params.request.params.itemId,
2476
- command: params.request.params.command,
2477
- });
2478
- }
2479
- }
2480
- const allow = this.isAllowedPermissionSelection(selected);
2481
- this.codex.respondSuccess(params.request.id, {
2482
- decision: allow ? 'accept' : 'decline',
2483
- });
2484
- await this.emitSessionUpdate(params.session.sessionId, {
2485
- sessionUpdate: 'tool_call_update',
2486
- toolCallId: params.toolCallId,
2487
- status: allow ? 'in_progress' : 'failed',
2488
- rawOutput: { decision: allow ? 'accept' : 'decline' },
900
+ await handleCodexServerPermissionRequest({
901
+ request,
902
+ sessionIdByThreadId: this.sessionIdByThreadId,
903
+ sessions: this.sessions,
904
+ connection: this.connection,
905
+ codex: this.codex,
906
+ emitSessionUpdate: (sessionId, update) => this.emitSessionUpdate(sessionId, update),
907
+ reportShapeDrift: (event, details) => this.reportShapeDrift(event, details),
2489
908
  });
2490
909
  }
2491
910
  settleTurn(session, stopReason) {
@@ -2504,11 +923,7 @@ export class CodexAppServerAcpAdapter {
2504
923
  session.pendingTurnCompletionsByTurnId.clear();
2505
924
  }
2506
925
  reportShapeDrift(event, details) {
2507
- const count = (this.shapeDriftCounts.get(event) ?? 0) + 1;
2508
- this.shapeDriftCounts.set(event, count);
2509
- const includeDetails = details !== undefined && (count <= 5 || count % 50 === 0);
2510
- const detailsSuffix = includeDetails ? ` details=${toShapeDriftDetails(details)}` : '';
2511
- process.stderr.write(`[codex-app-server-acp] shape-drift event=${event} count=${count}${detailsSuffix}\n`);
926
+ this.shapeDriftReporter.report(event, details);
2512
927
  }
2513
928
  async emitSessionUpdate(sessionId, update) {
2514
929
  try {
@@ -2518,10 +933,10 @@ export class CodexAppServerAcpAdapter {
2518
933
  }
2519
934
  }
2520
935
  }
2521
- export function runCodexAppServerAcpAdapter() {
936
+ export function runCodexAppServerAcpAdapter(options) {
2522
937
  const output = Writable.toWeb(process.stdout);
2523
938
  const input = Readable.toWeb(process.stdin);
2524
939
  const stream = ndJsonStream(output, input);
2525
- new AgentSideConnection((connection) => new CodexAppServerAcpAdapter(connection), stream);
940
+ new AgentSideConnection((connection) => new CodexAppServerAcpAdapter(connection, undefined, options), stream);
2526
941
  }
2527
942
  //# sourceMappingURL=codex-app-server-acp-adapter.js.map