factory-factory 0.3.7 → 0.3.8

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 (323) hide show
  1. package/dist/client/assets/{_basePickBy-BsuMuaCZ.js → _basePickBy-BzH_iru3.js} +1 -1
  2. package/dist/client/assets/{_baseUniq-BDd8f52s.js → _baseUniq-D6ny9r_u.js} +1 -1
  3. package/dist/client/assets/{arc-BWbaJQoA.js → arc-CRVgibiy.js} +1 -1
  4. package/dist/client/assets/{architectureDiagram-VXUJARFQ-C_FQG3JS.js → architectureDiagram-VXUJARFQ-1aDFSaTZ.js} +1 -1
  5. package/dist/client/assets/{blockDiagram-VD42YOAC-CLwvH-wA.js → blockDiagram-VD42YOAC-m3mDHY-k.js} +1 -1
  6. package/dist/client/assets/{c4Diagram-YG6GDRKO-Ba80_haP.js → c4Diagram-YG6GDRKO-B7ZlkfXz.js} +1 -1
  7. package/dist/client/assets/channel-B_f9a3jD.js +1 -0
  8. package/dist/client/assets/{chunk-4BX2VUAB-CSlDSMiy.js → chunk-4BX2VUAB-zLj9eiFf.js} +1 -1
  9. package/dist/client/assets/{chunk-55IACEB6-Dm3keBAf.js → chunk-55IACEB6-D6KQTgyD.js} +1 -1
  10. package/dist/client/assets/{chunk-B4BG7PRW-BSrvNYuP.js → chunk-B4BG7PRW-BQbzvx8l.js} +1 -1
  11. package/dist/client/assets/{chunk-DI55MBZ5-DFQPoLQZ.js → chunk-DI55MBZ5-CPxKCw_e.js} +1 -1
  12. package/dist/client/assets/{chunk-FMBD7UC4-C1KS438H.js → chunk-FMBD7UC4-nFaeGtHP.js} +1 -1
  13. package/dist/client/assets/{chunk-QN33PNHL-4rPPxHo4.js → chunk-QN33PNHL-DhrGqSLY.js} +1 -1
  14. package/dist/client/assets/{chunk-QZHKN3VN-B_sF5IzV.js → chunk-QZHKN3VN-CZWrGmvf.js} +1 -1
  15. package/dist/client/assets/{chunk-TZMSLE5B-L-qbjoBp.js → chunk-TZMSLE5B-xhHdVO37.js} +1 -1
  16. package/dist/client/assets/classDiagram-2ON5EDUG-CgnrkUO8.js +1 -0
  17. package/dist/client/assets/classDiagram-v2-WZHVMYZB-CgnrkUO8.js +1 -0
  18. package/dist/client/assets/clone-BmilxOGI.js +1 -0
  19. package/dist/client/assets/{cose-bilkent-S5V4N54A-DB7lwAnl.js → cose-bilkent-S5V4N54A-Cr0HX6ro.js} +1 -1
  20. package/dist/client/assets/{dagre-6UL2VRFP-z2fl_1iD.js → dagre-6UL2VRFP-s6RRMHqY.js} +1 -1
  21. package/dist/client/assets/{diagram-PSM6KHXK-BL2iv8II.js → diagram-PSM6KHXK-BhdZNVs7.js} +1 -1
  22. package/dist/client/assets/{diagram-QEK2KX5R-DgMZW0D1.js → diagram-QEK2KX5R-Dgwc4sx_.js} +1 -1
  23. package/dist/client/assets/{diagram-S2PKOQOG-Ct2QBl2c.js → diagram-S2PKOQOG-BlcMpYrQ.js} +1 -1
  24. package/dist/client/assets/{erDiagram-Q2GNP2WA-DII-pqkb.js → erDiagram-Q2GNP2WA-BQQjswcC.js} +1 -1
  25. package/dist/client/assets/{flowDiagram-NV44I4VS-BV4CMZAZ.js → flowDiagram-NV44I4VS-_cBTH43Q.js} +1 -1
  26. package/dist/client/assets/{ganttDiagram-JELNMOA3-Dfj064tE.js → ganttDiagram-JELNMOA3-BxuyB7Oz.js} +1 -1
  27. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-Cg2b-j3t.js → gitGraphDiagram-V2S2FVAM-D0GjSYQi.js} +1 -1
  28. package/dist/client/assets/{graph-wzICjOO_.js → graph-DNCXrik3.js} +1 -1
  29. package/dist/client/assets/{index-EVrp_NXm.js → index-CCnMDzRJ.js} +165 -158
  30. package/dist/client/assets/index-DVprBuNv.css +1 -0
  31. package/dist/client/assets/{infoDiagram-HS3SLOUP-D09mbfgG.js → infoDiagram-HS3SLOUP-BsUKtNMj.js} +1 -1
  32. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-BebsQbuf.js → journeyDiagram-XKPGCS4Q-sScoNj-6.js} +1 -1
  33. package/dist/client/assets/{kanban-definition-3W4ZIXB7-DOuawTNU.js → kanban-definition-3W4ZIXB7-CycFvltk.js} +1 -1
  34. package/dist/client/assets/{layout-Bj6cMfF5.js → layout-LTiJ8avf.js} +1 -1
  35. package/dist/client/assets/{linear-B58HS9F4.js → linear-CnQEAniJ.js} +1 -1
  36. package/dist/client/assets/{mindmap-definition-VGOIOE7T-hSFgcTL2.js → mindmap-definition-VGOIOE7T-Du5mb-g5.js} +1 -1
  37. package/dist/client/assets/{mobile-baseline-CmdjqYSm.js → mobile-baseline-necQV4Mu.js} +1 -1
  38. package/dist/client/assets/{pieDiagram-ADFJNKIX-D1vkoKs3.js → pieDiagram-ADFJNKIX-CUAEo70K.js} +1 -1
  39. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-pMQj9xcS.js → quadrantDiagram-AYHSOK5B-1MjtTI_Y.js} +1 -1
  40. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-DvRtxnIi.js → requirementDiagram-UZGBJVZJ-zgmi2Sjr.js} +1 -1
  41. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-BWoDxXkR.js → sankeyDiagram-TZEHDZUN-Datw0Rj8.js} +1 -1
  42. package/dist/client/assets/{sequenceDiagram-WL72ISMW-Dz5i1ly3.js → sequenceDiagram-WL72ISMW-DopxoRon.js} +1 -1
  43. package/dist/client/assets/{stateDiagram-FKZM4ZOC-BFd_gXUo.js → stateDiagram-FKZM4ZOC-ZqoVSvsu.js} +1 -1
  44. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BRKf4wQr.js +1 -0
  45. package/dist/client/assets/{terminal-instance-BTIzq32H.js → terminal-instance-gybkMDHu.js} +1 -1
  46. package/dist/client/assets/{timeline-definition-IT6M3QCI-BFEIWW6m.js → timeline-definition-IT6M3QCI-DQwpSE-n.js} +1 -1
  47. package/dist/client/assets/{treemap-GDKQZRPO-CC2Fh6RQ.js → treemap-GDKQZRPO-DK4UuMc6.js} +1 -1
  48. package/dist/client/assets/{xychartDiagram-PRI3JC2R-DFygXQrm.js → xychartDiagram-PRI3JC2R-CJP1ULwR.js} +1 -1
  49. package/dist/client/index.html +2 -2
  50. package/dist/prisma/generated/internal/class.js +4 -4
  51. package/dist/prisma/generated/internal/class.js.map +1 -1
  52. package/dist/prisma/generated/internal/prismaNamespace.d.ts +1 -0
  53. package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
  54. package/dist/prisma/generated/internal/prismaNamespace.js +1 -0
  55. package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
  56. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +1 -0
  57. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
  58. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +1 -0
  59. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  60. package/dist/prisma/generated/models/Workspace.d.ts +44 -1
  61. package/dist/prisma/generated/models/Workspace.d.ts.map +1 -1
  62. package/dist/src/backend/app-context.d.ts +2 -1
  63. package/dist/src/backend/app-context.d.ts.map +1 -1
  64. package/dist/src/backend/app-context.js +19 -5
  65. package/dist/src/backend/app-context.js.map +1 -1
  66. package/dist/src/backend/domains/run-script/index.d.ts +1 -1
  67. package/dist/src/backend/domains/run-script/index.d.ts.map +1 -1
  68. package/dist/src/backend/domains/run-script/index.js +1 -1
  69. package/dist/src/backend/domains/run-script/index.js.map +1 -1
  70. package/dist/src/backend/domains/run-script/run-script-domain-exports.test.js +5 -4
  71. package/dist/src/backend/domains/run-script/run-script-domain-exports.test.js.map +1 -1
  72. package/dist/src/backend/domains/run-script/run-script.service.d.ts +12 -1
  73. package/dist/src/backend/domains/run-script/run-script.service.d.ts.map +1 -1
  74. package/dist/src/backend/domains/run-script/run-script.service.js +140 -2
  75. package/dist/src/backend/domains/run-script/run-script.service.js.map +1 -1
  76. package/dist/src/backend/domains/run-script/run-script.service.test.js +86 -0
  77. package/dist/src/backend/domains/run-script/run-script.service.test.js.map +1 -1
  78. package/dist/src/backend/domains/session/acp/acp-runtime-manager.d.ts.map +1 -1
  79. package/dist/src/backend/domains/session/acp/acp-runtime-manager.js +4 -1
  80. package/dist/src/backend/domains/session/acp/acp-runtime-manager.js.map +1 -1
  81. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.d.ts +23 -0
  82. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.d.ts.map +1 -0
  83. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.js +76 -0
  84. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.js.map +1 -0
  85. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.d.ts +97 -0
  86. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.d.ts.map +1 -0
  87. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.js +2 -0
  88. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.js.map +1 -0
  89. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts +3 -24
  90. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts.map +1 -1
  91. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js +36 -1127
  92. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js.map +1 -1
  93. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.test.js +0 -191
  94. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.test.js.map +1 -1
  95. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-zod.d.ts +3 -3
  96. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.d.ts +16 -0
  97. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.d.ts.map +1 -0
  98. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.js +292 -0
  99. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.js.map +1 -0
  100. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.d.ts +2 -0
  101. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.d.ts.map +1 -0
  102. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.js +56 -0
  103. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.js.map +1 -0
  104. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.d.ts +19 -0
  105. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.d.ts.map +1 -0
  106. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.js +369 -0
  107. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.js.map +1 -0
  108. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.d.ts +2 -0
  109. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.d.ts.map +1 -0
  110. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.js +91 -0
  111. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.js.map +1 -0
  112. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.d.ts +53 -0
  113. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.d.ts.map +1 -0
  114. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.js +419 -0
  115. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.js.map +1 -0
  116. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.d.ts +2 -0
  117. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.d.ts.map +1 -0
  118. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.js +95 -0
  119. package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.js.map +1 -0
  120. package/dist/src/backend/domains/session/acp/index.d.ts +1 -1
  121. package/dist/src/backend/domains/session/acp/index.d.ts.map +1 -1
  122. package/dist/src/backend/domains/session/acp/index.js +1 -1
  123. package/dist/src/backend/domains/session/acp/index.js.map +1 -1
  124. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.d.ts.map +1 -1
  125. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.js +19 -5
  126. package/dist/src/backend/domains/session/data/claude-session-history-loader.service.js.map +1 -1
  127. package/dist/src/backend/domains/session/data/codex-session-history-loader.service.d.ts.map +1 -1
  128. package/dist/src/backend/domains/session/data/codex-session-history-loader.service.js +77 -24
  129. package/dist/src/backend/domains/session/data/codex-session-history-loader.service.js.map +1 -1
  130. package/dist/src/backend/domains/session/data/session-data.service.d.ts +2 -0
  131. package/dist/src/backend/domains/session/data/session-data.service.d.ts.map +1 -1
  132. package/dist/src/backend/domains/session/index.d.ts +3 -1
  133. package/dist/src/backend/domains/session/index.d.ts.map +1 -1
  134. package/dist/src/backend/domains/session/index.js +2 -1
  135. package/dist/src/backend/domains/session/index.js.map +1 -1
  136. package/dist/src/backend/domains/session/interceptor.bridge.d.ts +8 -0
  137. package/dist/src/backend/domains/session/interceptor.bridge.d.ts.map +1 -0
  138. package/dist/src/backend/domains/session/interceptor.bridge.js +7 -0
  139. package/dist/src/backend/domains/session/interceptor.bridge.js.map +1 -0
  140. package/dist/src/backend/domains/session/lifecycle/session.config.service.d.ts +59 -0
  141. package/dist/src/backend/domains/session/lifecycle/session.config.service.d.ts.map +1 -0
  142. package/dist/src/backend/domains/session/lifecycle/session.config.service.js +635 -0
  143. package/dist/src/backend/domains/session/lifecycle/session.config.service.js.map +1 -0
  144. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.d.ts +2 -0
  145. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.d.ts.map +1 -0
  146. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.js +552 -0
  147. package/dist/src/backend/domains/session/lifecycle/session.config.service.test.js.map +1 -0
  148. package/dist/src/backend/domains/session/lifecycle/session.permission.service.d.ts +17 -0
  149. package/dist/src/backend/domains/session/lifecycle/session.permission.service.d.ts.map +1 -0
  150. package/dist/src/backend/domains/session/lifecycle/session.permission.service.js +86 -0
  151. package/dist/src/backend/domains/session/lifecycle/session.permission.service.js.map +1 -0
  152. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.d.ts +2 -0
  153. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.d.ts.map +1 -0
  154. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.js +137 -0
  155. package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.js.map +1 -0
  156. package/dist/src/backend/domains/session/lifecycle/session.service.d.ts +16 -29
  157. package/dist/src/backend/domains/session/lifecycle/session.service.d.ts.map +1 -1
  158. package/dist/src/backend/domains/session/lifecycle/session.service.js +92 -723
  159. package/dist/src/backend/domains/session/lifecycle/session.service.js.map +1 -1
  160. package/dist/src/backend/domains/session/lifecycle/session.service.test.js +0 -698
  161. package/dist/src/backend/domains/session/lifecycle/session.service.test.js.map +1 -1
  162. package/dist/src/backend/domains/session/session-domain.service.d.ts +1 -2
  163. package/dist/src/backend/domains/session/session-domain.service.d.ts.map +1 -1
  164. package/dist/src/backend/domains/session/session-domain.service.js +5 -2
  165. package/dist/src/backend/domains/session/session-domain.service.js.map +1 -1
  166. package/dist/src/backend/domains/session/store/file-lock.service.d.ts.map +1 -1
  167. package/dist/src/backend/domains/session/store/file-lock.service.js +23 -2
  168. package/dist/src/backend/domains/session/store/file-lock.service.js.map +1 -1
  169. package/dist/src/backend/domains/session/zod-issue-summary.d.ts +3 -0
  170. package/dist/src/backend/domains/session/zod-issue-summary.d.ts.map +1 -0
  171. package/dist/src/backend/domains/session/zod-issue-summary.js +7 -0
  172. package/dist/src/backend/domains/session/zod-issue-summary.js.map +1 -0
  173. package/dist/src/backend/domains/workspace/lifecycle/creation.service.d.ts +7 -0
  174. package/dist/src/backend/domains/workspace/lifecycle/creation.service.d.ts.map +1 -1
  175. package/dist/src/backend/domains/workspace/lifecycle/creation.service.js +98 -85
  176. package/dist/src/backend/domains/workspace/lifecycle/creation.service.js.map +1 -1
  177. package/dist/src/backend/domains/workspace/lifecycle/creation.service.test.js +41 -1
  178. package/dist/src/backend/domains/workspace/lifecycle/creation.service.test.js.map +1 -1
  179. package/dist/src/backend/domains/workspace/lifecycle/data.service.d.ts +9 -1
  180. package/dist/src/backend/domains/workspace/lifecycle/data.service.d.ts.map +1 -1
  181. package/dist/src/backend/domains/workspace/lifecycle/data.service.js +2 -1
  182. package/dist/src/backend/domains/workspace/lifecycle/data.service.js.map +1 -1
  183. package/dist/src/backend/domains/workspace/query/project-management.service.d.ts +2 -0
  184. package/dist/src/backend/domains/workspace/query/project-management.service.d.ts.map +1 -1
  185. package/dist/src/backend/domains/workspace/query/workspace-query.service.d.ts +4 -1
  186. package/dist/src/backend/domains/workspace/query/workspace-query.service.d.ts.map +1 -1
  187. package/dist/src/backend/domains/workspace/query/workspace-query.service.js +18 -7
  188. package/dist/src/backend/domains/workspace/query/workspace-query.service.js.map +1 -1
  189. package/dist/src/backend/domains/workspace/query/workspace-query.service.test.js +57 -0
  190. package/dist/src/backend/domains/workspace/query/workspace-query.service.test.js.map +1 -1
  191. package/dist/src/backend/domains/workspace/state/kanban-state.d.ts +2 -1
  192. package/dist/src/backend/domains/workspace/state/kanban-state.d.ts.map +1 -1
  193. package/dist/src/backend/domains/workspace/state/kanban-state.js +6 -3
  194. package/dist/src/backend/domains/workspace/state/kanban-state.js.map +1 -1
  195. package/dist/src/backend/domains/workspace/state/kanban-state.test.js +23 -0
  196. package/dist/src/backend/domains/workspace/state/kanban-state.test.js.map +1 -1
  197. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.d.ts +3 -6
  198. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.d.ts.map +1 -1
  199. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.js +7 -116
  200. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.js.map +1 -1
  201. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.test.js +38 -65
  202. package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.test.js.map +1 -1
  203. package/dist/src/backend/interceptors/conversation-rename.interceptor.d.ts.map +1 -1
  204. package/dist/src/backend/interceptors/conversation-rename.interceptor.js +6 -4
  205. package/dist/src/backend/interceptors/conversation-rename.interceptor.js.map +1 -1
  206. package/dist/src/backend/interceptors/conversation-rename.interceptor.test.js +10 -10
  207. package/dist/src/backend/interceptors/conversation-rename.interceptor.test.js.map +1 -1
  208. package/dist/src/backend/lib/file-helpers.d.ts +2 -0
  209. package/dist/src/backend/lib/file-helpers.d.ts.map +1 -1
  210. package/dist/src/backend/lib/file-helpers.js +64 -1
  211. package/dist/src/backend/lib/file-helpers.js.map +1 -1
  212. package/dist/src/backend/middleware/cors.middleware.d.ts +1 -2
  213. package/dist/src/backend/middleware/cors.middleware.d.ts.map +1 -1
  214. package/dist/src/backend/middleware/cors.middleware.js +0 -2
  215. package/dist/src/backend/middleware/cors.middleware.js.map +1 -1
  216. package/dist/src/backend/middleware/index.d.ts +1 -1
  217. package/dist/src/backend/middleware/index.d.ts.map +1 -1
  218. package/dist/src/backend/middleware/index.js +1 -1
  219. package/dist/src/backend/middleware/index.js.map +1 -1
  220. package/dist/src/backend/orchestration/data-backup.service.test.js +1 -0
  221. package/dist/src/backend/orchestration/data-backup.service.test.js.map +1 -1
  222. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts +26 -1
  223. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
  224. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +21 -1
  225. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
  226. package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts +8 -1
  227. package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts.map +1 -1
  228. package/dist/src/backend/orchestration/event-collector.orchestrator.js +41 -21
  229. package/dist/src/backend/orchestration/event-collector.orchestrator.js.map +1 -1
  230. package/dist/src/backend/orchestration/event-collector.orchestrator.test.js +19 -4
  231. package/dist/src/backend/orchestration/event-collector.orchestrator.test.js.map +1 -1
  232. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts +6 -2
  233. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts.map +1 -1
  234. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js +8 -3
  235. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js.map +1 -1
  236. package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts +19 -1
  237. package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts.map +1 -1
  238. package/dist/src/backend/orchestration/workspace-archive.orchestrator.js +5 -7
  239. package/dist/src/backend/orchestration/workspace-archive.orchestrator.js.map +1 -1
  240. package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js +40 -47
  241. package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js.map +1 -1
  242. package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts.map +1 -1
  243. package/dist/src/backend/orchestration/workspace-init.orchestrator.js +86 -36
  244. package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
  245. package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js +62 -2
  246. package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js.map +1 -1
  247. package/dist/src/backend/resource_accessors/workspace.accessor.d.ts +1 -0
  248. package/dist/src/backend/resource_accessors/workspace.accessor.d.ts.map +1 -1
  249. package/dist/src/backend/resource_accessors/workspace.accessor.js.map +1 -1
  250. package/dist/src/backend/routers/websocket/index.d.ts +1 -0
  251. package/dist/src/backend/routers/websocket/index.d.ts.map +1 -1
  252. package/dist/src/backend/routers/websocket/index.js +1 -0
  253. package/dist/src/backend/routers/websocket/index.js.map +1 -1
  254. package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts +9 -0
  255. package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts.map +1 -0
  256. package/dist/src/backend/routers/websocket/post-run-logs.handler.js +52 -0
  257. package/dist/src/backend/routers/websocket/post-run-logs.handler.js.map +1 -0
  258. package/dist/src/backend/server.d.ts.map +1 -1
  259. package/dist/src/backend/server.js +10 -4
  260. package/dist/src/backend/server.js.map +1 -1
  261. package/dist/src/backend/server.upgrade.test.js +2 -0
  262. package/dist/src/backend/server.upgrade.test.js.map +1 -1
  263. package/dist/src/backend/services/workspace-snapshot-store.service.d.ts +2 -0
  264. package/dist/src/backend/services/workspace-snapshot-store.service.d.ts.map +1 -1
  265. package/dist/src/backend/services/workspace-snapshot-store.service.js +8 -4
  266. package/dist/src/backend/services/workspace-snapshot-store.service.js.map +1 -1
  267. package/dist/src/backend/trpc/admin.trpc.js +2 -2
  268. package/dist/src/backend/trpc/admin.trpc.js.map +1 -1
  269. package/dist/src/backend/trpc/index.d.ts +41 -1
  270. package/dist/src/backend/trpc/index.d.ts.map +1 -1
  271. package/dist/src/backend/trpc/project.trpc.d.ts +14 -0
  272. package/dist/src/backend/trpc/project.trpc.d.ts.map +1 -1
  273. package/dist/src/backend/trpc/project.trpc.js +22 -0
  274. package/dist/src/backend/trpc/project.trpc.js.map +1 -1
  275. package/dist/src/backend/trpc/session.router.test.js +1 -0
  276. package/dist/src/backend/trpc/session.router.test.js.map +1 -1
  277. package/dist/src/backend/trpc/session.trpc.d.ts +4 -0
  278. package/dist/src/backend/trpc/session.trpc.d.ts.map +1 -1
  279. package/dist/src/backend/trpc/session.trpc.js +2 -2
  280. package/dist/src/backend/trpc/session.trpc.js.map +1 -1
  281. package/dist/src/backend/trpc/workspace/files.trpc.d.ts.map +1 -1
  282. package/dist/src/backend/trpc/workspace/files.trpc.js +1 -64
  283. package/dist/src/backend/trpc/workspace/files.trpc.js.map +1 -1
  284. package/dist/src/backend/trpc/workspace/init.router.test.js +1 -1
  285. package/dist/src/backend/trpc/workspace/init.router.test.js.map +1 -1
  286. package/dist/src/backend/trpc/workspace/init.trpc.d.ts +1 -0
  287. package/dist/src/backend/trpc/workspace/init.trpc.d.ts.map +1 -1
  288. package/dist/src/backend/trpc/workspace/init.trpc.js +2 -3
  289. package/dist/src/backend/trpc/workspace/init.trpc.js.map +1 -1
  290. package/dist/src/backend/trpc/workspace/run-script.router.test.js +1 -1
  291. package/dist/src/backend/trpc/workspace/run-script.router.test.js.map +1 -1
  292. package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts +2 -0
  293. package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts.map +1 -1
  294. package/dist/src/backend/trpc/workspace/run-script.trpc.js +1 -1
  295. package/dist/src/backend/trpc/workspace/run-script.trpc.js.map +1 -1
  296. package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts +2 -0
  297. package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts.map +1 -1
  298. package/dist/src/backend/trpc/workspace.router.test.js +39 -0
  299. package/dist/src/backend/trpc/workspace.router.test.js.map +1 -1
  300. package/dist/src/backend/trpc/workspace.trpc.d.ts +23 -1
  301. package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
  302. package/dist/src/backend/trpc/workspace.trpc.js +6 -3
  303. package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
  304. package/dist/src/cli/index.js +12 -3
  305. package/dist/src/cli/index.js.map +1 -1
  306. package/dist/src/shared/schemas/factory-config.schema.d.ts +1 -0
  307. package/dist/src/shared/schemas/factory-config.schema.d.ts.map +1 -1
  308. package/dist/src/shared/schemas/factory-config.schema.js +1 -0
  309. package/dist/src/shared/schemas/factory-config.schema.js.map +1 -1
  310. package/dist/src/shared/schemas/persisted-stores.schema.d.ts +0 -2
  311. package/dist/src/shared/schemas/persisted-stores.schema.d.ts.map +1 -1
  312. package/dist/src/shared/schemas/persisted-stores.schema.js +0 -1
  313. package/dist/src/shared/schemas/persisted-stores.schema.js.map +1 -1
  314. package/dist/tsconfig.backend.tsbuildinfo +1 -1
  315. package/package.json +1 -1
  316. package/prisma/migrations/20260222120000_add_post_run_command/migration.sql +1 -0
  317. package/prisma/schema.prisma +1 -0
  318. package/dist/client/assets/channel-B2z94T-9.js +0 -1
  319. package/dist/client/assets/classDiagram-2ON5EDUG-B2LoFG_o.js +0 -1
  320. package/dist/client/assets/classDiagram-v2-WZHVMYZB-B2LoFG_o.js +0 -1
  321. package/dist/client/assets/clone-C8LA0zQQ.js +0 -1
  322. package/dist/client/assets/index-DvtmO7DV.css +0 -1
  323. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-CO6XGRkL.js +0 -1
@@ -1,16 +1,16 @@
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 { collaborationModeListResponseSchema, configRequirementsReadResponseSchema, modelListResponseSchema, threadResumeResponseSchema, threadStartResponseSchema, turnStartResponseSchema, } from './codex-zod.js';
6
+ import { resolveCommandDisplay } from './command-metadata.js';
7
+ import { handleCodexServerPermissionRequest } from './protocol-permission-handler.js';
8
+ import { CodexStreamEventHandler } from './stream-event-handler.js';
5
9
  const PENDING_TURN_ID = '__pending_turn__';
6
10
  const MAX_CLOSE_WATCHER_ATTACH_RETRIES = 50;
7
11
  const DEFAULT_APPROVAL_POLICIES = ['on-failure', 'on-request', 'never'];
8
12
  const DEFAULT_SANDBOX_MODES = ['read-only', 'workspace-write', 'danger-full-access'];
9
13
  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
14
  function toShapeDriftDetails(value) {
15
15
  try {
16
16
  const text = JSON.stringify(value);
@@ -28,9 +28,6 @@ function toShapeDriftDetails(value) {
28
28
  function isNonEmptyString(value) {
29
29
  return typeof value === 'string' && value.trim().length > 0;
30
30
  }
31
- function dedupeStrings(values) {
32
- return Array.from(new Set(values));
33
- }
34
31
  function humanizeToken(value) {
35
32
  return value
36
33
  .split(/[-_]/)
@@ -126,22 +123,6 @@ function toSessionId(threadId) {
126
123
  function toThreadId(sessionId) {
127
124
  return sessionId.startsWith('sess_') ? sessionId.slice('sess_'.length) : sessionId;
128
125
  }
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
126
  function isPlanLikeMode(mode) {
146
127
  return /plan/i.test(mode);
147
128
  }
@@ -280,393 +261,6 @@ function toCodexMcpConfigMap(mcpServers) {
280
261
  }
281
262
  return mcpServersByName;
282
263
  }
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
264
  function parseTextFromPromptBlock(block) {
671
265
  if (block.type === 'text') {
672
266
  return block.text;
@@ -690,18 +284,6 @@ function parseTextFromPromptBlock(block) {
690
284
  }
691
285
  return JSON.stringify(block);
692
286
  }
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
287
  function createCollaborationModeConfigOption(currentMode, collaborationModes) {
706
288
  const options = collaborationModes
707
289
  .filter((entry) => isNonEmptyString(entry.mode))
@@ -805,6 +387,7 @@ export class CodexAppServerAcpAdapter {
805
387
  mcpServersByThreadId = new Map();
806
388
  appliedMcpServerConfigJson = '{}';
807
389
  shapeDriftCounts = new Map();
390
+ streamEventHandler;
808
391
  constructor(connection, codexClient) {
809
392
  this.connection = connection;
810
393
  this.codex =
@@ -832,6 +415,22 @@ export class CodexAppServerAcpAdapter {
832
415
  process.stderr.write(`[codex-app-server-acp] protocol-error: ${error.reason}\n`);
833
416
  },
834
417
  });
418
+ this.streamEventHandler = new CodexStreamEventHandler({
419
+ codex: this.codex,
420
+ sessionIdByThreadId: this.sessionIdByThreadId,
421
+ sessions: this.sessions,
422
+ requireSession: (sessionId) => this.requireSession(sessionId),
423
+ emitSessionUpdate: (sessionId, update) => this.emitSessionUpdate(sessionId, update),
424
+ reportShapeDrift: (event, details) => this.reportShapeDrift(event, details),
425
+ buildToolCallState: (session, item, turnId) => this.buildToolCallState(session, item, turnId),
426
+ emitReasoningThoughtChunkFromItem: (sessionId, item) => this.emitReasoningThoughtChunkFromItem(sessionId, item),
427
+ shouldHoldTurnForPlanApproval: (session, item, turnId) => this.shouldHoldTurnForPlanApproval(session, item, turnId),
428
+ holdTurnUntilPlanApprovalResolves: (session, turnId) => this.holdTurnUntilPlanApprovalResolves(session, turnId),
429
+ maybeRequestPlanApproval: (session, item, turnId, completedPlanToolCall) => this.maybeRequestPlanApproval(session, item, turnId, completedPlanToolCall),
430
+ hasPendingPlanApprovals: (session, turnId) => this.hasPendingPlanApprovals(session, turnId),
431
+ settleTurn: (session, stopReason) => this.settleTurn(session, stopReason),
432
+ emitTurnFailureMessage: (sessionId, errorMessage) => this.emitTurnFailureMessage(sessionId, errorMessage),
433
+ });
835
434
  this.monitorConnectionClose();
836
435
  }
837
436
  monitorConnectionClose() {
@@ -1539,163 +1138,10 @@ export class CodexAppServerAcpAdapter {
1539
1138
  throw lastError;
1540
1139
  }
1541
1140
  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));
1141
+ await this.streamEventHandler.replayThreadHistory(sessionId, threadId);
1621
1142
  }
1622
1143
  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
- });
1144
+ await this.streamEventHandler.handleCodexNotification({ method, params });
1699
1145
  }
1700
1146
  async emitReasoningThoughtChunkFromItem(sessionId, item) {
1701
1147
  const text = extractReasoningTextLocal(item);
@@ -1707,262 +1153,11 @@ export class CodexAppServerAcpAdapter {
1707
1153
  content: { type: 'text', text },
1708
1154
  });
1709
1155
  }
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' &&
1156
+ shouldHoldTurnForPlanApproval(session, item, turnId) {
1157
+ return (item.type === 'plan' &&
1944
1158
  isPlanLikeMode(session.defaults.collaborationMode) &&
1945
1159
  !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);
1160
+ this.extractPlanApprovalText(session, item) !== null);
1966
1161
  }
1967
1162
  buildPlanApprovalInput(planText, sourceItemId) {
1968
1163
  return {
@@ -2145,27 +1340,6 @@ export class CodexAppServerAcpAdapter {
2145
1340
  await this.releaseTurnHoldForPlanApproval(session, turnId);
2146
1341
  }
2147
1342
  }
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
1343
  buildToolCallState(session, item, _turnId) {
2170
1344
  const kindByType = {
2171
1345
  commandExecution: 'execute',
@@ -2191,7 +1365,7 @@ export class CodexAppServerAcpAdapter {
2191
1365
  }
2192
1366
  else if (item.type === 'fileChange') {
2193
1367
  title = 'fileChange';
2194
- locations = this.extractLocations(item);
1368
+ locations = extractLocations(item);
2195
1369
  }
2196
1370
  else if (item.type === 'mcpToolCall') {
2197
1371
  const server = asString(item.server) ?? 'mcp';
@@ -2212,280 +1386,15 @@ export class CodexAppServerAcpAdapter {
2212
1386
  locations,
2213
1387
  };
2214
1388
  }
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
1389
  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' },
1390
+ await handleCodexServerPermissionRequest({
1391
+ request,
1392
+ sessionIdByThreadId: this.sessionIdByThreadId,
1393
+ sessions: this.sessions,
1394
+ connection: this.connection,
1395
+ codex: this.codex,
1396
+ emitSessionUpdate: (sessionId, update) => this.emitSessionUpdate(sessionId, update),
1397
+ reportShapeDrift: (event, details) => this.reportShapeDrift(event, details),
2489
1398
  });
2490
1399
  }
2491
1400
  settleTurn(session, stopReason) {