@jingyi0605/codingns 0.7.3 → 0.8.0

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 (419) hide show
  1. package/README.md +6 -0
  2. package/bin/codingns.mjs +747 -28
  3. package/bin/office-mcp-server.mjs +620 -0
  4. package/dist/public/assets/{AdaptiveButlerPage-CgBX49t-.js → AdaptiveButlerPage-BsgVNRAa.js} +1 -1
  5. package/dist/public/assets/{App-tXOqoHNl.js → App-tPcbyRdS.js} +3 -3
  6. package/dist/public/assets/{BootstrapPage-DoRMz87R.js → BootstrapPage--MDOigQi.js} +1 -1
  7. package/dist/public/assets/{ConversationPage-DXR6Hp4O.js → ConversationPage-BBss5ED8.js} +6 -6
  8. package/dist/public/assets/{DesktopDetachPreviewPage-Cyk-ZYCk.js → DesktopDetachPreviewPage-CB8DoqwU.js} +1 -1
  9. package/dist/public/assets/{DesktopWindowPage-DNVNK3hs.js → DesktopWindowPage-GtIx5m8K.js} +1 -1
  10. package/dist/public/assets/FileContextPanel-BcM7AIT4.js +1 -0
  11. package/dist/public/assets/{GitSidebar-Cr3Z9OUI.js → GitSidebar-CMtkaxuI.js} +2 -2
  12. package/dist/public/assets/{MobileCreateSessionSheet-DMW0V6GJ.js → MobileCreateSessionSheet-CrFY41_8.js} +1 -1
  13. package/dist/public/assets/{MobileTopHeaderFrame-CkdnZ_MU.js → MobileTopHeaderFrame-DGVOzXyg.js} +1 -1
  14. package/dist/public/assets/{MobileWorkspaceSwitcherHeader-KIbqBYJN.js → MobileWorkspaceSwitcherHeader-DLkACTnQ.js} +1 -1
  15. package/dist/public/assets/{RelayConnectEntryPage-DIRBH3hw.js → RelayConnectEntryPage-0MPPjxtQ.js} +1 -1
  16. package/dist/public/assets/{ServerSettingsModal-C-9RxdWP.js → ServerSettingsModal-vgOhwus4.js} +1 -1
  17. package/dist/public/assets/{SessionIndexPage-bRlIydRA.js → SessionIndexPage-KK626Ra9.js} +1 -1
  18. package/dist/public/assets/{SettingsPage-CMEt4ua9.js → SettingsPage-B3edBJIo.js} +2 -2
  19. package/dist/public/assets/{TerminalManagerPanel-2bi9wVhT.js → TerminalManagerPanel-BxlhZp8c.js} +1 -1
  20. package/dist/public/assets/{TerminalPage-DayZz2Tf.js → TerminalPage-B6Rdhylx.js} +1 -1
  21. package/dist/public/assets/{TerminalRuntimeFallbackModal-DgwYcp-Y.js → TerminalRuntimeFallbackModal-BVLfrpSa.js} +1 -1
  22. package/dist/public/assets/{ToolFilesPage-YvnP_FXW.js → ToolFilesPage-N_gwwUjD.js} +1 -1
  23. package/dist/public/assets/{ToolGitPage-GMcQKtV9.js → ToolGitPage-DOcuuWM1.js} +1 -1
  24. package/dist/public/assets/{ToolProcessesPage-DFIQ7BCd.js → ToolProcessesPage-D-FfJ7Re.js} +1 -1
  25. package/dist/public/assets/{ToolsHomePage-CSilFzXR.js → ToolsHomePage-CHfPxd20.js} +1 -1
  26. package/dist/public/assets/{WorkbenchLandingPage-1VtToSz9.js → WorkbenchLandingPage-CTTnfovY.js} +1 -1
  27. package/dist/public/assets/WorkbenchLayout-CbpJg0g1.js +244 -0
  28. package/dist/public/assets/{WorkbenchModal-BWXYSXmC.js → WorkbenchModal-Bt_1fYmM.js} +1 -1
  29. package/dist/public/assets/WorkbenchShellRoute-B4XB8SwG.css +1 -0
  30. package/dist/public/assets/WorkbenchShellRoute-DyaMnPfS.js +1 -0
  31. package/dist/public/assets/{WorkspaceDebugDetailPage-Ux8_Q7la.js → WorkspaceDebugDetailPage-s7yuDIxR.js} +1 -1
  32. package/dist/public/assets/{WorkspaceDetailPage-B402p99m.js → WorkspaceDetailPage-Cf-gVpqK.js} +1 -1
  33. package/dist/public/assets/{WorkspaceHomePage-D2pob6HI.js → WorkspaceHomePage-COf6I8sT.js} +1 -1
  34. package/dist/public/assets/{client-runtime-manager-C5D76ewj.js → client-runtime-manager-DGdKvYzx.js} +1 -1
  35. package/dist/public/assets/file-tree-icon-BeHqeru9.js +590 -0
  36. package/dist/public/assets/index-CcaQt50x.css +1 -0
  37. package/dist/public/assets/index-CuzMc7q2.js +42 -0
  38. package/dist/public/assets/{login-direct-candidate-resolver-wXSaB0i7.js → login-direct-candidate-resolver-DEP_xCmR.js} +1 -1
  39. package/dist/public/assets/{model-switch-api-CPtou49j.js → model-switch-api-c6kcbBGm.js} +1 -1
  40. package/dist/public/assets/{preferences-service-CdaK7zA8.js → preferences-service-CV6Ih0BG.js} +1 -1
  41. package/dist/public/assets/{realtime-client-BjQazYsK.js → realtime-client-CRCx5xBt.js} +1 -1
  42. package/dist/public/assets/{relay-entry-BwE5nw0l.js → relay-entry-C751A-Sm.js} +1 -1
  43. package/dist/public/assets/{terminal-runtime-meta-C-Lbyx2i.js → terminal-runtime-meta-CRAVR-8G.js} +1 -1
  44. package/dist/public/assets/{useRegisteredDebugTemplates-BM7-c-gx.js → useRegisteredDebugTemplates-D6YtNS0r.js} +1 -1
  45. package/dist/public/index.html +2 -2
  46. package/dist/server/config/env.d.ts +3 -0
  47. package/dist/server/config/env.js +67 -1
  48. package/dist/server/config/env.js.map +1 -1
  49. package/dist/server/config/opencode-base-url-resolver.d.ts +3 -2
  50. package/dist/server/config/opencode-base-url-resolver.js +64 -24
  51. package/dist/server/config/opencode-base-url-resolver.js.map +1 -1
  52. package/dist/server/middlewares/auth-guard.js +4 -0
  53. package/dist/server/middlewares/auth-guard.js.map +1 -1
  54. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +168 -1
  55. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +205 -4
  56. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  57. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +296 -2
  58. package/dist/server/modules/assistant-capability/assistant-capability-service.js +872 -3
  59. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  60. package/dist/server/modules/auth/auth-service.d.ts +21 -1
  61. package/dist/server/modules/auth/auth-service.js +64 -0
  62. package/dist/server/modules/auth/auth-service.js.map +1 -1
  63. package/dist/server/modules/browser-runtime/browser-profile-service.d.ts +26 -0
  64. package/dist/server/modules/browser-runtime/browser-profile-service.js +85 -0
  65. package/dist/server/modules/browser-runtime/browser-profile-service.js.map +1 -0
  66. package/dist/server/modules/browser-runtime/browser-runtime-controller.d.ts +69 -0
  67. package/dist/server/modules/browser-runtime/browser-runtime-controller.js +83 -0
  68. package/dist/server/modules/browser-runtime/browser-runtime-controller.js.map +1 -0
  69. package/dist/server/modules/browser-runtime/browser-runtime-service.d.ts +56 -0
  70. package/dist/server/modules/browser-runtime/browser-runtime-service.js +215 -0
  71. package/dist/server/modules/browser-runtime/browser-runtime-service.js.map +1 -0
  72. package/dist/server/modules/browser-runtime/browser-task-execution-support.d.ts +65 -0
  73. package/dist/server/modules/browser-runtime/browser-task-execution-support.js +432 -0
  74. package/dist/server/modules/browser-runtime/browser-task-execution-support.js.map +1 -0
  75. package/dist/server/modules/browser-runtime/browser-task-executor-registry.d.ts +7 -0
  76. package/dist/server/modules/browser-runtime/browser-task-executor-registry.js +21 -0
  77. package/dist/server/modules/browser-runtime/browser-task-executor-registry.js.map +1 -0
  78. package/dist/server/modules/browser-runtime/browser-task-executor.d.ts +55 -0
  79. package/dist/server/modules/browser-runtime/browser-task-executor.js +2 -0
  80. package/dist/server/modules/browser-runtime/browser-task-executor.js.map +1 -0
  81. package/dist/server/modules/browser-runtime/browser-task-payload.d.ts +31 -0
  82. package/dist/server/modules/browser-runtime/browser-task-payload.js +55 -0
  83. package/dist/server/modules/browser-runtime/browser-task-payload.js.map +1 -0
  84. package/dist/server/modules/browser-runtime/opencli-bridge-browser-executor.d.ts +19 -0
  85. package/dist/server/modules/browser-runtime/opencli-bridge-browser-executor.js +219 -0
  86. package/dist/server/modules/browser-runtime/opencli-bridge-browser-executor.js.map +1 -0
  87. package/dist/server/modules/browser-runtime/opencli-browser-bridge-service.d.ts +15 -0
  88. package/dist/server/modules/browser-runtime/opencli-browser-bridge-service.js +33 -0
  89. package/dist/server/modules/browser-runtime/opencli-browser-bridge-service.js.map +1 -0
  90. package/dist/server/modules/browser-runtime/playwright-browser-executor.d.ts +16 -0
  91. package/dist/server/modules/browser-runtime/playwright-browser-executor.js +272 -0
  92. package/dist/server/modules/browser-runtime/playwright-browser-executor.js.map +1 -0
  93. package/dist/server/modules/butler/butler-auth-service.js +4 -0
  94. package/dist/server/modules/butler/butler-auth-service.js.map +1 -1
  95. package/dist/server/modules/butler/butler-inbox-instruction-adapter.js +1 -0
  96. package/dist/server/modules/butler/butler-inbox-instruction-adapter.js.map +1 -1
  97. package/dist/server/modules/butler/butler-session-summary-service.d.ts +1 -0
  98. package/dist/server/modules/butler/butler-session-summary-service.js +5 -3
  99. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
  100. package/dist/server/modules/butler/butler-workspace-context.js +23 -0
  101. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  102. package/dist/server/modules/channels/wechat-claw-client.d.ts +51 -0
  103. package/dist/server/modules/channels/wechat-claw-client.js +245 -0
  104. package/dist/server/modules/channels/wechat-claw-client.js.map +1 -0
  105. package/dist/server/modules/debug-target/debug-target-service.d.ts +2 -0
  106. package/dist/server/modules/debug-target/debug-target-service.js +14 -0
  107. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  108. package/dist/server/modules/document-runtime/document-docx-fallback-renderer.py +139 -0
  109. package/dist/server/modules/document-runtime/document-export-executor.d.ts +50 -0
  110. package/dist/server/modules/document-runtime/document-export-executor.js +827 -0
  111. package/dist/server/modules/document-runtime/document-export-executor.js.map +1 -0
  112. package/dist/server/modules/document-runtime/document-runtime-controller.d.ts +127 -0
  113. package/dist/server/modules/document-runtime/document-runtime-controller.js +131 -0
  114. package/dist/server/modules/document-runtime/document-runtime-controller.js.map +1 -0
  115. package/dist/server/modules/document-runtime/document-runtime-service.d.ts +125 -0
  116. package/dist/server/modules/document-runtime/document-runtime-service.js +706 -0
  117. package/dist/server/modules/document-runtime/document-runtime-service.js.map +1 -0
  118. package/dist/server/modules/office/office-controller.d.ts +77 -0
  119. package/dist/server/modules/office/office-controller.js +174 -0
  120. package/dist/server/modules/office/office-controller.js.map +1 -0
  121. package/dist/server/modules/office/office-preview-link-service.d.ts +27 -0
  122. package/dist/server/modules/office/office-preview-link-service.js +121 -0
  123. package/dist/server/modules/office/office-preview-link-service.js.map +1 -0
  124. package/dist/server/modules/office/office-service.d.ts +67 -0
  125. package/dist/server/modules/office/office-service.js +359 -0
  126. package/dist/server/modules/office/office-service.js.map +1 -0
  127. package/dist/server/modules/opencli/opencli-bridge-skill-service.js +38 -14
  128. package/dist/server/modules/opencli/opencli-bridge-skill-service.js.map +1 -1
  129. package/dist/server/modules/opencli/opencli-install-discovery.d.ts +4 -0
  130. package/dist/server/modules/opencli/opencli-install-discovery.js +94 -0
  131. package/dist/server/modules/opencli/opencli-install-discovery.js.map +1 -1
  132. package/dist/server/modules/opencli/opencli-runtime-builder.js +29 -0
  133. package/dist/server/modules/opencli/opencli-runtime-builder.js.map +1 -1
  134. package/dist/server/modules/opencli/opencli-runtime-guard.d.ts +2 -0
  135. package/dist/server/modules/opencli/opencli-runtime-guard.js +5 -0
  136. package/dist/server/modules/opencli/opencli-runtime-guard.js.map +1 -0
  137. package/dist/server/modules/ops-runtime/ops-runtime-controller.d.ts +70 -0
  138. package/dist/server/modules/ops-runtime/ops-runtime-controller.js +83 -0
  139. package/dist/server/modules/ops-runtime/ops-runtime-controller.js.map +1 -0
  140. package/dist/server/modules/ops-runtime/ops-runtime-service.d.ts +80 -0
  141. package/dist/server/modules/ops-runtime/ops-runtime-service.js +327 -0
  142. package/dist/server/modules/ops-runtime/ops-runtime-service.js.map +1 -0
  143. package/dist/server/modules/ops-runtime/ssh-ops-executor.d.ts +41 -0
  144. package/dist/server/modules/ops-runtime/ssh-ops-executor.js +478 -0
  145. package/dist/server/modules/ops-runtime/ssh-ops-executor.js.map +1 -0
  146. package/dist/server/modules/presentation/presentation-controller.d.ts +22 -0
  147. package/dist/server/modules/presentation/presentation-controller.js +59 -0
  148. package/dist/server/modules/presentation/presentation-controller.js.map +1 -0
  149. package/dist/server/modules/presentation/presentation-export-task-service.d.ts +24 -0
  150. package/dist/server/modules/presentation/presentation-export-task-service.js +137 -0
  151. package/dist/server/modules/presentation/presentation-export-task-service.js.map +1 -0
  152. package/dist/server/modules/presentation/presentation-export-types.d.ts +12 -0
  153. package/dist/server/modules/presentation/presentation-export-types.js +2 -0
  154. package/dist/server/modules/presentation/presentation-export-types.js.map +1 -0
  155. package/dist/server/modules/presentation/presentation-pdf-export-service.d.ts +20 -0
  156. package/dist/server/modules/presentation/presentation-pdf-export-service.js +29 -0
  157. package/dist/server/modules/presentation/presentation-pdf-export-service.js.map +1 -0
  158. package/dist/server/modules/presentation/presentation-pptx-export-service.d.ts +20 -0
  159. package/dist/server/modules/presentation/presentation-pptx-export-service.js +64 -0
  160. package/dist/server/modules/presentation/presentation-pptx-export-service.js.map +1 -0
  161. package/dist/server/modules/presentation/presentation-renderer.d.ts +21 -0
  162. package/dist/server/modules/presentation/presentation-renderer.js +208 -0
  163. package/dist/server/modules/presentation/presentation-renderer.js.map +1 -0
  164. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +3 -3
  165. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -1
  166. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +6 -1
  167. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -1
  168. package/dist/server/modules/sessions/codex-app-server-helper-process.js +2 -1
  169. package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
  170. package/dist/server/modules/sessions/session-controller.d.ts +1 -0
  171. package/dist/server/modules/sessions/session-controller.js +59 -4
  172. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  173. package/dist/server/modules/sessions/session-history-service.js +17 -5
  174. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  175. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +5 -1
  176. package/dist/server/modules/sessions/session-live-runtime-service.js +86 -8
  177. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  178. package/dist/server/modules/sessions/session-provider-config-service.d.ts +25 -1
  179. package/dist/server/modules/sessions/session-provider-config-service.js +54 -5
  180. package/dist/server/modules/sessions/session-provider-config-service.js.map +1 -1
  181. package/dist/server/modules/sessions/workspace-office-mcp-config.d.ts +14 -0
  182. package/dist/server/modules/sessions/workspace-office-mcp-config.js +54 -0
  183. package/dist/server/modules/sessions/workspace-office-mcp-config.js.map +1 -0
  184. package/dist/server/modules/sessions/workspace-session-auth-service.d.ts +27 -0
  185. package/dist/server/modules/sessions/workspace-session-auth-service.js +109 -0
  186. package/dist/server/modules/sessions/workspace-session-auth-service.js.map +1 -0
  187. package/dist/server/modules/sessions/workspace-session-runtime-context-service.d.ts +50 -0
  188. package/dist/server/modules/sessions/workspace-session-runtime-context-service.js +332 -0
  189. package/dist/server/modules/sessions/workspace-session-runtime-context-service.js.map +1 -0
  190. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js +5 -0
  191. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js.map +1 -1
  192. package/dist/server/modules/skills/builtin-skills/codingns-workspace-session/SKILL.md +67 -0
  193. package/dist/server/modules/skills/builtin-skills/codingns-workspace-session/agents/openai.yaml +4 -0
  194. package/dist/server/modules/skills/builtin-skills/codingns-workspace-session/references/cli-workflow.md +133 -0
  195. package/dist/server/modules/skills/skill-controller.d.ts +7 -0
  196. package/dist/server/modules/skills/skill-controller.js +7 -0
  197. package/dist/server/modules/skills/skill-controller.js.map +1 -1
  198. package/dist/server/modules/skills/skill-manager-service.d.ts +61 -0
  199. package/dist/server/modules/skills/skill-manager-service.js +218 -0
  200. package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
  201. package/dist/server/modules/skills/skill-name-policy.js +2 -1
  202. package/dist/server/modules/skills/skill-name-policy.js.map +1 -1
  203. package/dist/server/modules/tasks/task-helper-client.d.ts +1 -0
  204. package/dist/server/modules/tasks/task-helper-client.js +45 -9
  205. package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
  206. package/dist/server/modules/tasks/task-types.d.ts +5 -0
  207. package/dist/server/modules/tasks/task-types.js +6 -1
  208. package/dist/server/modules/tasks/task-types.js.map +1 -1
  209. package/dist/server/modules/terminal/runtime/conpty-session-agent-process.js +2 -1
  210. package/dist/server/modules/terminal/runtime/conpty-session-agent-process.js.map +1 -1
  211. package/dist/server/modules/terminal/runtime/node-pty-loader.d.ts +5 -0
  212. package/dist/server/modules/terminal/runtime/node-pty-loader.js +68 -0
  213. package/dist/server/modules/terminal/runtime/node-pty-loader.js.map +1 -0
  214. package/dist/server/modules/terminal/runtime/pty-broker-agent-process.js +2 -1
  215. package/dist/server/modules/terminal/runtime/pty-broker-agent-process.js.map +1 -1
  216. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.js +6 -9
  217. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.js.map +1 -1
  218. package/dist/server/modules/terminal/runtime/pty-runtime-manager.js +6 -9
  219. package/dist/server/modules/terminal/runtime/pty-runtime-manager.js.map +1 -1
  220. package/dist/server/routes/assistant.d.ts +2 -1
  221. package/dist/server/routes/assistant.js +20 -1
  222. package/dist/server/routes/assistant.js.map +1 -1
  223. package/dist/server/routes/browser-runtime.d.ts +3 -0
  224. package/dist/server/routes/browser-runtime.js +14 -0
  225. package/dist/server/routes/browser-runtime.js.map +1 -0
  226. package/dist/server/routes/document-runtime.d.ts +3 -0
  227. package/dist/server/routes/document-runtime.js +18 -0
  228. package/dist/server/routes/document-runtime.js.map +1 -0
  229. package/dist/server/routes/office.d.ts +3 -0
  230. package/dist/server/routes/office.js +16 -0
  231. package/dist/server/routes/office.js.map +1 -0
  232. package/dist/server/routes/ops-runtime.d.ts +3 -0
  233. package/dist/server/routes/ops-runtime.js +13 -0
  234. package/dist/server/routes/ops-runtime.js.map +1 -0
  235. package/dist/server/routes/presentation.d.ts +3 -0
  236. package/dist/server/routes/presentation.js +5 -0
  237. package/dist/server/routes/presentation.js.map +1 -0
  238. package/dist/server/routes/skills.js +1 -0
  239. package/dist/server/routes/skills.js.map +1 -1
  240. package/dist/server/server/create-server.d.ts +36 -0
  241. package/dist/server/server/create-server.js +215 -4
  242. package/dist/server/server/create-server.js.map +1 -1
  243. package/dist/server/server/release-manifest-sync.d.ts +1 -0
  244. package/dist/server/server/release-manifest-sync.js +2 -2
  245. package/dist/server/server/release-manifest-sync.js.map +1 -1
  246. package/dist/server/server/start-host.js +1 -1
  247. package/dist/server/server/start-host.js.map +1 -1
  248. package/dist/server/storage/repositories/auth-token-repository.js +22 -6
  249. package/dist/server/storage/repositories/auth-token-repository.js.map +1 -1
  250. package/dist/server/storage/repositories/browser-profile-repository.d.ts +18 -0
  251. package/dist/server/storage/repositories/browser-profile-repository.js +134 -0
  252. package/dist/server/storage/repositories/browser-profile-repository.js.map +1 -0
  253. package/dist/server/storage/repositories/document-comment-repository.d.ts +10 -0
  254. package/dist/server/storage/repositories/document-comment-repository.js +118 -0
  255. package/dist/server/storage/repositories/document-comment-repository.js.map +1 -0
  256. package/dist/server/storage/repositories/document-repository.d.ts +16 -0
  257. package/dist/server/storage/repositories/document-repository.js +109 -0
  258. package/dist/server/storage/repositories/document-repository.js.map +1 -0
  259. package/dist/server/storage/repositories/document-revision-repository.d.ts +10 -0
  260. package/dist/server/storage/repositories/document-revision-repository.js +79 -0
  261. package/dist/server/storage/repositories/document-revision-repository.js.map +1 -0
  262. package/dist/server/storage/repositories/document-template-repository.d.ts +13 -0
  263. package/dist/server/storage/repositories/document-template-repository.js +244 -0
  264. package/dist/server/storage/repositories/document-template-repository.js.map +1 -0
  265. package/dist/server/storage/repositories/office-approval-repository.d.ts +11 -0
  266. package/dist/server/storage/repositories/office-approval-repository.js +109 -0
  267. package/dist/server/storage/repositories/office-approval-repository.js.map +1 -0
  268. package/dist/server/storage/repositories/office-artifact-repository.d.ts +10 -0
  269. package/dist/server/storage/repositories/office-artifact-repository.js +89 -0
  270. package/dist/server/storage/repositories/office-artifact-repository.js.map +1 -0
  271. package/dist/server/storage/repositories/office-audit-event-repository.d.ts +8 -0
  272. package/dist/server/storage/repositories/office-audit-event-repository.js +54 -0
  273. package/dist/server/storage/repositories/office-audit-event-repository.js.map +1 -0
  274. package/dist/server/storage/repositories/office-connector-repository.d.ts +10 -0
  275. package/dist/server/storage/repositories/office-connector-repository.js +97 -0
  276. package/dist/server/storage/repositories/office-connector-repository.js.map +1 -0
  277. package/dist/server/storage/repositories/office-receipt-repository.d.ts +8 -0
  278. package/dist/server/storage/repositories/office-receipt-repository.js +48 -0
  279. package/dist/server/storage/repositories/office-receipt-repository.js.map +1 -0
  280. package/dist/server/storage/repositories/office-rollback-record-repository.d.ts +8 -0
  281. package/dist/server/storage/repositories/office-rollback-record-repository.js +60 -0
  282. package/dist/server/storage/repositories/office-rollback-record-repository.js.map +1 -0
  283. package/dist/server/storage/repositories/office-task-repository.d.ts +19 -0
  284. package/dist/server/storage/repositories/office-task-repository.js +199 -0
  285. package/dist/server/storage/repositories/office-task-repository.js.map +1 -0
  286. package/dist/server/storage/repositories/office-task-step-repository.d.ts +10 -0
  287. package/dist/server/storage/repositories/office-task-step-repository.js +110 -0
  288. package/dist/server/storage/repositories/office-task-step-repository.js.map +1 -0
  289. package/dist/server/storage/repositories/ops-target-repository.d.ts +16 -0
  290. package/dist/server/storage/repositories/ops-target-repository.js +119 -0
  291. package/dist/server/storage/repositories/ops-target-repository.js.map +1 -0
  292. package/dist/server/storage/repositories/session-binding-repository.d.ts +4 -0
  293. package/dist/server/storage/repositories/session-binding-repository.js +70 -69
  294. package/dist/server/storage/repositories/session-binding-repository.js.map +1 -1
  295. package/dist/server/storage/repositories/session-changed-file-repository.d.ts +6 -0
  296. package/dist/server/storage/repositories/session-changed-file-repository.js +44 -43
  297. package/dist/server/storage/repositories/session-changed-file-repository.js.map +1 -1
  298. package/dist/server/storage/repositories/session-fork-repository.d.ts +2 -0
  299. package/dist/server/storage/repositories/session-fork-repository.js +42 -41
  300. package/dist/server/storage/repositories/session-fork-repository.js.map +1 -1
  301. package/dist/server/storage/repositories/session-index-repository.d.ts +5 -0
  302. package/dist/server/storage/repositories/session-index-repository.js +153 -152
  303. package/dist/server/storage/repositories/session-index-repository.js.map +1 -1
  304. package/dist/server/storage/repositories/session-message-attachment-repository.d.ts +7 -0
  305. package/dist/server/storage/repositories/session-message-attachment-repository.js +91 -90
  306. package/dist/server/storage/repositories/session-message-attachment-repository.js.map +1 -1
  307. package/dist/server/storage/repositories/session-message-origin-repository.d.ts +2 -0
  308. package/dist/server/storage/repositories/session-message-origin-repository.js +25 -24
  309. package/dist/server/storage/repositories/session-message-origin-repository.js.map +1 -1
  310. package/dist/server/storage/repositories/session-state-repository.d.ts +2 -0
  311. package/dist/server/storage/repositories/session-state-repository.js +35 -34
  312. package/dist/server/storage/repositories/session-state-repository.js.map +1 -1
  313. package/dist/server/storage/repositories/session-status-snapshot-repository.d.ts +2 -0
  314. package/dist/server/storage/repositories/session-status-snapshot-repository.js +25 -24
  315. package/dist/server/storage/repositories/session-status-snapshot-repository.js.map +1 -1
  316. package/dist/server/storage/sqlite/client.js +123 -1
  317. package/dist/server/storage/sqlite/client.js.map +1 -1
  318. package/dist/server/storage/sqlite/schema.sql +300 -1
  319. package/dist/server/types/domain.d.ts +205 -1
  320. package/package.json +14 -7
  321. package/scripts/postinstall.mjs +170 -36
  322. package/dist/public/assets/FileContextPanel-xGTYDclT.js +0 -1
  323. package/dist/public/assets/WorkbenchLayout-DScHaza9.js +0 -244
  324. package/dist/public/assets/WorkbenchShellRoute-DN6LdrqC.js +0 -1
  325. package/dist/public/assets/WorkbenchShellRoute-DhQo_0vu.css +0 -1
  326. package/dist/public/assets/file-tree-icon-lfU9Ag77.js +0 -3
  327. package/dist/public/assets/index-CFYXCsyx.css +0 -1
  328. package/dist/public/assets/index-NGxWr8Ix.js +0 -42
  329. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.d.ts +0 -42
  330. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js +0 -346
  331. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js.map +0 -1
  332. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.d.ts +0 -1
  333. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js +0 -80
  334. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js.map +0 -1
  335. package/node_modules/@codingns/session-sync-core/dist/index.d.ts +0 -18
  336. package/node_modules/@codingns/session-sync-core/dist/index.js +0 -19
  337. package/node_modules/@codingns/session-sync-core/dist/index.js.map +0 -1
  338. package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.d.ts +0 -18
  339. package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js +0 -659
  340. package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js.map +0 -1
  341. package/node_modules/@codingns/session-sync-core/dist/kimi-shared.d.ts +0 -11
  342. package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js +0 -72
  343. package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js.map +0 -1
  344. package/node_modules/@codingns/session-sync-core/dist/patch-builder.d.ts +0 -67
  345. package/node_modules/@codingns/session-sync-core/dist/patch-builder.js +0 -752
  346. package/node_modules/@codingns/session-sync-core/dist/patch-builder.js.map +0 -1
  347. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +0 -48
  348. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +0 -1184
  349. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +0 -1
  350. package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.d.ts +0 -11
  351. package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.js +0 -105
  352. package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.js.map +0 -1
  353. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +0 -84
  354. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +0 -2436
  355. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +0 -1
  356. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +0 -47
  357. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +0 -1480
  358. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +0 -1
  359. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +0 -33
  360. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +0 -684
  361. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +0 -1
  362. package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.d.ts +0 -9
  363. package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.js +0 -17
  364. package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.js.map +0 -1
  365. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.d.ts +0 -1
  366. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.js +0 -8
  367. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.js.map +0 -1
  368. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.d.ts +0 -48
  369. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js +0 -373
  370. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js.map +0 -1
  371. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +0 -61
  372. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +0 -1191
  373. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +0 -1
  374. package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +0 -27
  375. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +0 -415
  376. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +0 -1
  377. package/node_modules/@codingns/session-sync-core/dist/registry.d.ts +0 -7
  378. package/node_modules/@codingns/session-sync-core/dist/registry.js +0 -22
  379. package/node_modules/@codingns/session-sync-core/dist/registry.js.map +0 -1
  380. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +0 -24
  381. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +0 -329
  382. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +0 -1
  383. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.d.ts +0 -30
  384. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +0 -939
  385. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +0 -1
  386. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.d.ts +0 -1
  387. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js +0 -16
  388. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js.map +0 -1
  389. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +0 -70
  390. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +0 -2571
  391. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +0 -1
  392. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.d.ts +0 -21
  393. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js +0 -561
  394. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js.map +0 -1
  395. package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.d.ts +0 -38
  396. package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js +0 -911
  397. package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js.map +0 -1
  398. package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.d.ts +0 -15
  399. package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.js +0 -16
  400. package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.js.map +0 -1
  401. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.d.ts +0 -37
  402. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js +0 -963
  403. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js.map +0 -1
  404. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.d.ts +0 -21
  405. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js +0 -168
  406. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js.map +0 -1
  407. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +0 -152
  408. package/node_modules/@codingns/session-sync-core/dist/runtime/types.js +0 -2
  409. package/node_modules/@codingns/session-sync-core/dist/runtime/types.js.map +0 -1
  410. package/node_modules/@codingns/session-sync-core/dist/services.d.ts +0 -28
  411. package/node_modules/@codingns/session-sync-core/dist/services.js +0 -148
  412. package/node_modules/@codingns/session-sync-core/dist/services.js.map +0 -1
  413. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.d.ts +0 -6
  414. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js +0 -9
  415. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js.map +0 -1
  416. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +0 -198
  417. package/node_modules/@codingns/session-sync-core/dist/types.js +0 -2
  418. package/node_modules/@codingns/session-sync-core/dist/types.js.map +0 -1
  419. package/node_modules/@codingns/session-sync-core/package.json +0 -33
@@ -1,2571 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { spawn } from "node:child_process";
3
- import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
4
- import { homedir } from "node:os";
5
- import { performance } from "node:perf_hooks";
6
- import { basename, dirname, join, resolve } from "node:path";
7
- import { createInterface } from "node:readline";
8
- import { fileURLToPath, pathToFileURL } from "node:url";
9
- import { appendJsonLine, createRawRef, ensureDirectory, extractTextBlocks, messageIdFromStableKey, messageIdFromRawRef, nextTimestamp, normalizeWorkspacePath } from "../providers/utils.js";
10
- import { buildCodexResumeHistoryFromRawStore } from "../codex-resume-history.js";
11
- import { buildApplyPatchFromCodexCommandLikeValue, buildApplyPatchFromFileChangeList, extractApplyPatchTargetPathsFromToolOutput, normalizeApplyPatchText } from "../patch-builder.js";
12
- import { loadDatabaseSync } from "../sqlite/node-sqlite.js";
13
- import { createCodexThreadPermissionOptions } from "./codex-permissions.js";
14
- const CODEX_RUNTIME_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_PERF_DEBUG?.trim() ?? "");
15
- const CODEX_APP_SERVER_REQUEST_TIMEOUT_MS = 20_000;
16
- function logCodexRuntimeStep(scope, startedAtMs, detail = {}) {
17
- if (!CODEX_RUNTIME_DEBUG_ENABLED) {
18
- return;
19
- }
20
- const durationMs = Math.round(performance.now() - startedAtMs);
21
- const suffix = formatCodexRuntimeDebugDetail(detail);
22
- console.info(`[perf][codex-runtime] ${scope} ${durationMs}ms${suffix ? ` ${suffix}` : ""}`);
23
- }
24
- function formatCodexRuntimeDebugDetail(detail) {
25
- const entries = Object.entries(detail).filter(([, value]) => value !== undefined);
26
- if (entries.length === 0) {
27
- return "";
28
- }
29
- return entries
30
- .map(([key, value]) => `${key}=${formatCodexRuntimeDebugValue(value)}`)
31
- .join(" ");
32
- }
33
- function formatCodexRuntimeDebugValue(value) {
34
- if (value === null) {
35
- return "null";
36
- }
37
- if (typeof value === "string") {
38
- return JSON.stringify(value);
39
- }
40
- if (typeof value === "number") {
41
- return Number.isFinite(value) ? String(Math.round(value)) : String(value);
42
- }
43
- if (typeof value === "boolean") {
44
- return value ? "true" : "false";
45
- }
46
- try {
47
- return JSON.stringify(value);
48
- }
49
- catch {
50
- return String(value);
51
- }
52
- }
53
- export class CodexRuntimeAdapter {
54
- options;
55
- providerId = "codex";
56
- constructor(options = {}) {
57
- this.options = options;
58
- }
59
- async startSession(request, sink) {
60
- const launchedAtMs = Date.now();
61
- const launchPerfStartedAtMs = performance.now();
62
- const transport = this.options.transportFactory
63
- ? this.options.transportFactory(request)
64
- : createCodexAppServerTransport({
65
- ...this.options,
66
- homeDir: request.runtimeHomeDir?.trim() || this.options.homeDir,
67
- runtimeEnv: request.runtimeEnv ?? this.options.runtimeEnv ?? null
68
- });
69
- try {
70
- const initializeStartedAtMs = performance.now();
71
- await transport.initialize();
72
- logCodexRuntimeStep("start_session.initialize", initializeStartedAtMs, {
73
- sessionId: request.sessionId,
74
- workspacePath: request.workspacePath
75
- });
76
- const abortController = new AbortController();
77
- const eventQueue = createAsyncEventQueue();
78
- const translateNotification = createCodexAppServerNotificationTranslator();
79
- const forwardTranslatedNotification = createCodexTranslatedNotificationForwarder(eventQueue);
80
- const resumedSyntheticSession = await this.resumeSyntheticThreadFromHistory(transport, request);
81
- const startedSession = resumedSyntheticSession ??
82
- await (async () => {
83
- const startThreadStartedAtMs = performance.now();
84
- const started = await transport.startThread(request);
85
- logCodexRuntimeStep("start_session.thread_start", startThreadStartedAtMs, {
86
- sessionId: request.sessionId,
87
- providerSessionId: started.providerSessionId
88
- });
89
- return started;
90
- })();
91
- const providerSessionId = startedSession.providerSessionId;
92
- const syntheticRawStoreRef = buildRuntimeRawStoreRef(resolveRuntimeStoreKey(providerSessionId, request.sessionId));
93
- const rawStoreRef = pickAvailableCodexRawStoreRef(providerSessionId, resumedSyntheticSession
94
- ? [resumedSyntheticSession.rawStoreRef]
95
- : [startedSession.rawStoreRef, request.rawStoreRef], syntheticRawStoreRef);
96
- logCodexRuntimeStep("start_session.raw_store_ref_ready", launchPerfStartedAtMs, {
97
- sessionId: request.sessionId,
98
- providerSessionId,
99
- synthetic: isSyntheticRawStoreRef(rawStoreRef),
100
- hasProviderRawStoreRef: Boolean(startedSession.rawStoreRef),
101
- providerRawStoreRefExists: Boolean(startedSession.rawStoreRef && existsSync(startedSession.rawStoreRef))
102
- });
103
- sink.updateSessionBinding({
104
- providerSessionId,
105
- rawStoreRef
106
- });
107
- let firstNotificationLogged = false;
108
- transport.setNotificationHandler(async (notification) => {
109
- if (!firstNotificationLogged) {
110
- firstNotificationLogged = true;
111
- logCodexRuntimeStep("start_session.first_notification", launchPerfStartedAtMs, {
112
- sessionId: request.sessionId,
113
- providerSessionId,
114
- method: ensureText(notification.method).trim() || null
115
- });
116
- }
117
- const translated = translateNotification(notification);
118
- forwardTranslatedNotification(translated);
119
- });
120
- transport.setServerRequestHandler(async (serverRequest) => {
121
- if (!this.options.handleServerRequest) {
122
- throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
123
- }
124
- return this.options.handleServerRequest({
125
- sessionId: request.sessionId,
126
- providerSessionId,
127
- request: serverRequest
128
- });
129
- });
130
- transport.setOnClose((error) => {
131
- if (error) {
132
- eventQueue.push({
133
- type: "turn.failed",
134
- timestamp: nextTimestamp(),
135
- error: error.message
136
- });
137
- }
138
- eventQueue.close();
139
- });
140
- const startTurnStartedAtMs = performance.now();
141
- const startTurnResult = await transport.startTurn(request, providerSessionId);
142
- const startTurnNotification = startTurnResult?.notification ?? null;
143
- if (startTurnNotification) {
144
- const translated = translateNotification(startTurnNotification);
145
- forwardTranslatedNotification(translated);
146
- }
147
- logCodexRuntimeStep("start_session.turn_start", startTurnStartedAtMs, {
148
- sessionId: request.sessionId,
149
- providerSessionId
150
- });
151
- logCodexRuntimeStep("start_session.ready", launchPerfStartedAtMs, {
152
- sessionId: request.sessionId,
153
- providerSessionId
154
- });
155
- return {
156
- providerSessionId,
157
- rawStoreRef,
158
- submitDuringRun: async (options) => {
159
- await transport.steerTurn(options);
160
- },
161
- interrupt: async () => {
162
- abortController.abort();
163
- await transport.interruptTurn().catch(() => {
164
- return;
165
- });
166
- transport.close();
167
- },
168
- isAlive: () => transport.isClosed() === false,
169
- completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs).finally(() => {
170
- transport.close();
171
- })
172
- };
173
- }
174
- catch (error) {
175
- transport.close();
176
- throw error;
177
- }
178
- }
179
- async resumeSyntheticThreadFromHistory(transport, request) {
180
- const history = buildSyntheticResumeHistory(request.rawStoreRef);
181
- if (history.length === 0) {
182
- return null;
183
- }
184
- const resumeStartedAtMs = performance.now();
185
- const resumed = await transport.resumeThreadFromHistory({
186
- providerSessionId: null,
187
- workspacePath: request.workspacePath,
188
- history,
189
- model: request.options.model
190
- });
191
- logCodexRuntimeStep("start_session.thread_resume_from_history", resumeStartedAtMs, {
192
- sessionId: request.sessionId,
193
- providerSessionId: resumed.providerSessionId,
194
- messageCount: history.length
195
- });
196
- return resumed;
197
- }
198
- async continueSession(request, sink) {
199
- const providerSessionId = resolveResumeThreadId(request.providerSessionId, request.rawStoreRef);
200
- if (!providerSessionId) {
201
- throw new Error("PROVIDER_SESSION_ID_REQUIRED");
202
- }
203
- const transport = this.options.transportFactory
204
- ? this.options.transportFactory(request)
205
- : createCodexAppServerTransport({
206
- ...this.options,
207
- homeDir: request.runtimeHomeDir?.trim() || this.options.homeDir,
208
- runtimeEnv: request.runtimeEnv ?? this.options.runtimeEnv ?? null
209
- });
210
- try {
211
- const runtimeStartedAtMs = performance.now();
212
- const initializeStartedAtMs = performance.now();
213
- await transport.initialize();
214
- logCodexRuntimeStep("continue_session.initialize", initializeStartedAtMs, {
215
- sessionId: request.sessionId,
216
- providerSessionId
217
- });
218
- const syntheticRawStoreRef = buildRuntimeRawStoreRef(providerSessionId);
219
- let resolvedSessionId = providerSessionId;
220
- let resolvedFallbackHistoryRawStoreRef = null;
221
- const resumeThreadStartedAtMs = performance.now();
222
- let resumed;
223
- try {
224
- resumed = await transport.resumeThread(request, resolvedSessionId);
225
- logCodexRuntimeStep("continue_session.thread_resume", resumeThreadStartedAtMs, {
226
- sessionId: request.sessionId,
227
- providerSessionId: resolvedSessionId,
228
- fallback: false
229
- });
230
- }
231
- catch (error) {
232
- const fallbackHistorySource = await this.resolveContinueFallbackHistorySource({
233
- providerSessionId,
234
- rawStoreRef: request.rawStoreRef,
235
- workspacePath: request.workspacePath,
236
- homeDir: request.runtimeHomeDir?.trim() || this.options.homeDir?.trim() || null
237
- });
238
- const resumeHistory = fallbackHistorySource?.history ?? [];
239
- if (!shouldFallbackCodexContinueFromHistory(error, resumeHistory)) {
240
- throw error;
241
- }
242
- resolvedFallbackHistoryRawStoreRef = fallbackHistorySource?.rawStoreRef ?? null;
243
- const resumeFallbackStartedAtMs = performance.now();
244
- resumed = await transport.resumeThreadFromHistory({
245
- providerSessionId: null,
246
- workspacePath: request.workspacePath,
247
- history: resumeHistory,
248
- model: request.options.model
249
- });
250
- resolvedSessionId = resumed.providerSessionId;
251
- logCodexRuntimeStep("continue_session.thread_resume_from_history_fallback", resumeFallbackStartedAtMs, {
252
- sessionId: request.sessionId,
253
- requestedProviderSessionId: providerSessionId,
254
- providerSessionId: resolvedSessionId,
255
- historyLength: resumeHistory.length
256
- });
257
- }
258
- const pickedRawStoreRef = pickAvailableCodexRawStoreRef(resolvedSessionId, [resolvedFallbackHistoryRawStoreRef, request.rawStoreRef, resumed.rawStoreRef], syntheticRawStoreRef);
259
- const rawStoreRef = !resumed.rawStoreRef?.trim() && resolvedFallbackHistoryRawStoreRef
260
- ? resolvedFallbackHistoryRawStoreRef
261
- : pickedRawStoreRef;
262
- const abortController = new AbortController();
263
- const eventQueue = createAsyncEventQueue();
264
- const translateNotification = createCodexAppServerNotificationTranslator();
265
- const forwardTranslatedNotification = createCodexTranslatedNotificationForwarder(eventQueue);
266
- logCodexRuntimeStep("continue_session.raw_store_ref_ready", runtimeStartedAtMs, {
267
- sessionId: request.sessionId,
268
- providerSessionId: resolvedSessionId,
269
- synthetic: isSyntheticRawStoreRef(rawStoreRef),
270
- hasResumedRawStoreRef: Boolean(resumed.rawStoreRef),
271
- hasRequestRawStoreRef: Boolean(request.rawStoreRef),
272
- resumedRawStoreRefExists: Boolean(resumed.rawStoreRef && existsSync(resumed.rawStoreRef))
273
- });
274
- sink.updateSessionBinding({
275
- providerSessionId: resolvedSessionId,
276
- rawStoreRef
277
- });
278
- let firstNotificationLogged = false;
279
- transport.setNotificationHandler(async (notification) => {
280
- if (!firstNotificationLogged) {
281
- firstNotificationLogged = true;
282
- logCodexRuntimeStep("continue_session.first_notification", runtimeStartedAtMs, {
283
- sessionId: request.sessionId,
284
- providerSessionId: resolvedSessionId,
285
- method: ensureText(notification.method).trim() || null
286
- });
287
- }
288
- const translated = translateNotification(notification);
289
- forwardTranslatedNotification(translated);
290
- });
291
- transport.setServerRequestHandler(async (serverRequest) => {
292
- if (!this.options.handleServerRequest) {
293
- throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
294
- }
295
- return this.options.handleServerRequest({
296
- sessionId: request.sessionId,
297
- providerSessionId: resolvedSessionId,
298
- request: serverRequest
299
- });
300
- });
301
- transport.setOnClose((error) => {
302
- if (error) {
303
- eventQueue.push({
304
- type: "turn.failed",
305
- timestamp: nextTimestamp(),
306
- error: error.message
307
- });
308
- }
309
- eventQueue.close();
310
- });
311
- const startTurnStartedAtMs = performance.now();
312
- const startTurnResult = await transport.startTurn(request, resolvedSessionId);
313
- const startTurnNotification = startTurnResult?.notification ?? null;
314
- if (startTurnNotification) {
315
- const translated = translateNotification(startTurnNotification);
316
- forwardTranslatedNotification(translated);
317
- }
318
- logCodexRuntimeStep("continue_session.turn_start", startTurnStartedAtMs, {
319
- sessionId: request.sessionId,
320
- providerSessionId: resolvedSessionId
321
- });
322
- logCodexRuntimeStep("continue_session.ready", runtimeStartedAtMs, {
323
- sessionId: request.sessionId,
324
- providerSessionId: resolvedSessionId
325
- });
326
- return {
327
- providerSessionId: resolvedSessionId,
328
- rawStoreRef,
329
- submitDuringRun: async (options) => {
330
- await transport.steerTurn(options);
331
- },
332
- interrupt: async () => {
333
- abortController.abort();
334
- await transport.interruptTurn().catch(() => {
335
- return;
336
- });
337
- transport.close();
338
- },
339
- isAlive: () => transport.isClosed() === false,
340
- completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now()).finally(() => {
341
- transport.close();
342
- })
343
- };
344
- }
345
- catch (error) {
346
- transport.close();
347
- throw error;
348
- }
349
- }
350
- async resolveContinueFallbackHistorySource(input) {
351
- const candidates = [];
352
- const seen = new Set();
353
- const pushCandidate = (candidate) => {
354
- const normalized = candidate?.trim();
355
- if (!normalized || seen.has(normalized) || !existsSync(normalized)) {
356
- return;
357
- }
358
- seen.add(normalized);
359
- candidates.push(normalized);
360
- };
361
- pushCandidate(input.rawStoreRef);
362
- // 旧会话的 binding 可能只剩 synthetic stream,或者已经指到了父线程 transcript。
363
- // 继续会话失败时,额外按真实 thread id 扫一次本地 transcript,尽量把历史恢复链路救回来。
364
- pushCandidate(await this.resolveRealRawStoreRef(input.providerSessionId.trim(), input.workspacePath, input.homeDir));
365
- let fallbackMatch = null;
366
- for (const candidate of candidates) {
367
- const history = buildCodexResumeHistoryFromRawStore(candidate);
368
- if (history.length === 0) {
369
- continue;
370
- }
371
- const meta = readSessionMeta(candidate);
372
- if (meta?.threadId === input.providerSessionId.trim()) {
373
- return {
374
- rawStoreRef: candidate,
375
- history
376
- };
377
- }
378
- fallbackMatch ??= {
379
- rawStoreRef: candidate,
380
- history
381
- };
382
- }
383
- return fallbackMatch;
384
- }
385
- async runTurn(thread, request, sink, providerSessionId, rawStoreRef, abortController, preparedEvents, bufferedEvents = [], launchedAtMs = Date.now(), launchPerfStartedAtMs = performance.now()) {
386
- const context = {
387
- providerSessionId,
388
- rawStoreRef,
389
- // 运行时消息必须接在历史消息后面,不能每轮都从 1 重新编号,
390
- // 否则前端会把新 assistant/tool 消息排到旧消息前面,表现成用户消息一直挂在底部。
391
- sequence: Math.max(0, request.sequenceBase ?? 0),
392
- toolNameByCallId: new Map(),
393
- stableMessageRefByIdentity: new Map(),
394
- lastSignatureByIdentity: new Map(),
395
- sink,
396
- workspacePath: request.workspacePath,
397
- firstUserMessage: request.options.content,
398
- homeDir: request.runtimeHomeDir?.trim() || this.options.homeDir?.trim() || null,
399
- launchedAtMs,
400
- launchPerfStartedAtMs
401
- };
402
- try {
403
- await this.refreshSessionBindingIfNeeded(context);
404
- persistSyntheticUserMessageIfNeeded(context.rawStoreRef, context.providerSessionId, {
405
- workspacePath: request.workspacePath,
406
- content: request.options.content,
407
- timestamp: nextTimestamp()
408
- });
409
- for (const event of bufferedEvents) {
410
- await this.refreshSessionBindingIfNeeded(context);
411
- persistSyntheticEventIfNeeded(context.rawStoreRef, context.providerSessionId, event);
412
- await this.handleEvent(event, request, context, abortController.signal.aborted);
413
- }
414
- const events = preparedEvents ??
415
- (await thread.runStreamed(createCodexInput(request), {
416
- signal: abortController.signal
417
- })).events[Symbol.asyncIterator]();
418
- while (true) {
419
- const next = await events.next();
420
- if (next.done) {
421
- return;
422
- }
423
- await this.refreshSessionBindingIfNeeded(context);
424
- persistSyntheticEventIfNeeded(context.rawStoreRef, context.providerSessionId, next.value);
425
- await this.handleEvent(next.value, request, context, abortController.signal.aborted);
426
- }
427
- }
428
- catch (error) {
429
- if (abortController.signal.aborted) {
430
- await sink.emit({
431
- type: "interrupted",
432
- status: "interrupted",
433
- interruptSource: "user",
434
- providerSessionId: context.providerSessionId,
435
- rawStoreRef: context.rawStoreRef,
436
- detail: "codex turn interrupted",
437
- timestamp: nextTimestamp()
438
- });
439
- return;
440
- }
441
- const failure = classifyCodexRuntimeFailure(error);
442
- await sink.emit({
443
- type: "error",
444
- status: "failed",
445
- providerSessionId: context.providerSessionId,
446
- rawStoreRef: context.rawStoreRef,
447
- errorCode: failure.errorCode,
448
- detail: failure.detail,
449
- timestamp: nextTimestamp()
450
- });
451
- }
452
- }
453
- async handleEvent(event, request, context, interrupted) {
454
- const eventType = ensureText(readProp(event, "type")).trim();
455
- if (eventType.length === 0) {
456
- return;
457
- }
458
- if (context.lastSignatureByIdentity.size === 0 && eventType.startsWith("item.")) {
459
- logCodexRuntimeStep("turn.first_item_event", context.launchPerfStartedAtMs, {
460
- sessionId: request.sessionId,
461
- providerSessionId: context.providerSessionId,
462
- eventType
463
- });
464
- }
465
- if (eventType === "turn.completed") {
466
- await context.sink.emit({
467
- type: "complete",
468
- status: "completed",
469
- providerSessionId: context.providerSessionId,
470
- rawStoreRef: context.rawStoreRef,
471
- detail: "codex turn completed",
472
- timestamp: pickTimestamp(event)
473
- });
474
- return;
475
- }
476
- if (eventType === "turn.failed") {
477
- const detail = extractTextBlocks(readProp(event, "error")).trim() || "codex turn failed";
478
- await context.sink.emit({
479
- type: "error",
480
- status: "failed",
481
- providerSessionId: context.providerSessionId,
482
- rawStoreRef: context.rawStoreRef,
483
- errorCode: classifyCodexDetailErrorCode(detail, "CODEX_CLI_TURN_FAILED"),
484
- detail,
485
- timestamp: pickTimestamp(event)
486
- });
487
- return;
488
- }
489
- if (eventType === "turn.interrupted") {
490
- await context.sink.emit({
491
- type: "interrupted",
492
- status: "interrupted",
493
- interruptSource: interrupted ? "user" : "runtime",
494
- providerSessionId: context.providerSessionId,
495
- rawStoreRef: context.rawStoreRef,
496
- detail: "codex turn interrupted",
497
- timestamp: pickTimestamp(event)
498
- });
499
- return;
500
- }
501
- if (interrupted) {
502
- return;
503
- }
504
- if (!eventType.startsWith("item.")) {
505
- return;
506
- }
507
- const item = readProp(event, "item");
508
- const itemType = ensureText(readProp(item, "type")).trim();
509
- if (itemType.length === 0) {
510
- return;
511
- }
512
- if (itemType === "agent_message" &&
513
- (eventType === "item.updated" || eventType === "item.completed")) {
514
- const content = pickFirstNonEmpty(ensureText(readProp(item, "text")).trim(), extractTextBlocks(readProp(item, "content")).trim());
515
- if (content.length > 0) {
516
- await this.emitStableMessage(context, {
517
- identity: `assistant:text:${ensureText(readProp(item, "id")).trim() || "default"}`,
518
- timestamp: pickTimestamp(item, event),
519
- role: "assistant",
520
- kind: "text",
521
- content
522
- });
523
- }
524
- return;
525
- }
526
- if (itemType === "reasoning" &&
527
- (eventType === "item.updated" || eventType === "item.completed")) {
528
- const content = pickFirstNonEmpty(ensureText(readProp(item, "text")).trim(), extractTextBlocks(readProp(item, "summary")).trim(), extractTextBlocks(readProp(item, "content")).trim());
529
- if (content.length > 0) {
530
- await this.emitStableMessage(context, {
531
- identity: `assistant:thinking:${ensureText(readProp(item, "id")).trim() || "default"}`,
532
- timestamp: pickTimestamp(item, event),
533
- role: "assistant",
534
- kind: "thinking",
535
- content
536
- });
537
- }
538
- return;
539
- }
540
- if (!isToolItem(itemType)) {
541
- return;
542
- }
543
- const callId = pickFirstNonEmpty(ensureText(readProp(item, "id")).trim(), ensureText(readProp(item, "call_id")).trim(), `${itemType}-${randomUUID()}`);
544
- const name = pickFirstNonEmpty(ensureText(readProp(item, "name")).trim(), ensureText(readProp(item, "tool")).trim(), itemType);
545
- if (eventType === "item.started") {
546
- const input = resolveCodexToolInput(name, item);
547
- const toolCall = {
548
- callId,
549
- name,
550
- input,
551
- output: null,
552
- error: null,
553
- status: "running"
554
- };
555
- context.toolNameByCallId.set(callId, name);
556
- await this.emitStableMessage(context, {
557
- identity: `tool:call:${callId}`,
558
- timestamp: pickTimestamp(item, event),
559
- role: "tool",
560
- kind: "tool_call",
561
- content: input,
562
- toolCall
563
- });
564
- return;
565
- }
566
- if (eventType === "item.updated") {
567
- const knownName = context.toolNameByCallId.get(callId) ?? name;
568
- const input = resolveCodexToolInput(knownName, item);
569
- const output = pickFirstNonEmpty(extractTextBlocks(readProp(item, "result")).trim(), extractTextBlocks(readProp(item, "output")).trim(), extractTextBlocks(readProp(item, "aggregated_output")).trim(), extractTextBlocks(readProp(item, "error")).trim());
570
- if (output.length === 0) {
571
- return;
572
- }
573
- context.toolNameByCallId.set(callId, knownName);
574
- await this.emitStableMessage(context, {
575
- identity: `tool:result:${callId}`,
576
- timestamp: pickTimestamp(item, event),
577
- role: "tool",
578
- kind: "tool_result",
579
- content: output,
580
- toolCall: {
581
- callId,
582
- name: knownName,
583
- input,
584
- output,
585
- error: null,
586
- status: "running"
587
- }
588
- });
589
- return;
590
- }
591
- if (eventType === "item.completed") {
592
- const knownName = context.toolNameByCallId.get(callId) ?? name;
593
- const input = resolveCodexToolInput(knownName, item);
594
- const output = pickFirstNonEmpty(extractTextBlocks(readProp(item, "result")).trim(), extractTextBlocks(readProp(item, "output")).trim(), extractTextBlocks(readProp(item, "aggregated_output")).trim(), extractTextBlocks(readProp(item, "error")).trim());
595
- const success = inferToolSuccess(item, output);
596
- const toolCall = {
597
- callId,
598
- name: knownName,
599
- input,
600
- output: success ? output : null,
601
- error: success ? null : output,
602
- status: success ? "completed" : "failed"
603
- };
604
- await this.emitStableMessage(context, {
605
- identity: `tool:result:${callId}`,
606
- timestamp: pickTimestamp(item, event),
607
- role: "tool",
608
- kind: "tool_result",
609
- content: output,
610
- toolCall
611
- });
612
- }
613
- }
614
- async emitStableMessage(context, input) {
615
- const message = this.buildMessage(context, {
616
- timestamp: input.timestamp,
617
- role: input.role,
618
- kind: input.kind,
619
- content: input.content,
620
- toolCall: input.toolCall ?? null,
621
- stableIdentity: input.identity
622
- });
623
- const signature = buildCodexMessageSignature(message);
624
- if (context.lastSignatureByIdentity.get(input.identity) === signature) {
625
- return;
626
- }
627
- context.lastSignatureByIdentity.set(input.identity, signature);
628
- await context.sink.emit({
629
- type: "message",
630
- message,
631
- providerSessionId: context.providerSessionId,
632
- rawStoreRef: context.rawStoreRef,
633
- timestamp: input.timestamp,
634
- rawEventRef: message.rawRef
635
- });
636
- }
637
- async refreshSessionBindingIfNeeded(context) {
638
- if (!isSyntheticRawStoreRef(context.rawStoreRef)) {
639
- return;
640
- }
641
- const resolved = await this.resolveLaunchedSessionBinding(context.workspacePath, context.firstUserMessage, context.launchedAtMs, context.homeDir) ??
642
- await this.resolveExistingSessionBinding(context.providerSessionId, context.rawStoreRef, context.workspacePath, context.homeDir);
643
- if (!resolved ||
644
- (resolved.providerSessionId === context.providerSessionId &&
645
- resolved.rawStoreRef === context.rawStoreRef)) {
646
- return;
647
- }
648
- context.providerSessionId = resolved.providerSessionId;
649
- context.rawStoreRef = resolved.rawStoreRef;
650
- context.sink.updateSessionBinding({
651
- providerSessionId: resolved.providerSessionId,
652
- rawStoreRef: resolved.rawStoreRef
653
- });
654
- }
655
- async resolveExistingSessionBinding(providerSessionId, rawStoreRef, workspacePath, homeDirOverride = null) {
656
- const normalizedProviderSessionId = providerSessionId.trim();
657
- const meta = readSessionMeta(rawStoreRef);
658
- if (meta && meta.threadId === normalizedProviderSessionId && existsSync(rawStoreRef)) {
659
- return {
660
- providerSessionId: meta.threadId,
661
- rawStoreRef
662
- };
663
- }
664
- if (!normalizedProviderSessionId) {
665
- return null;
666
- }
667
- const resolvedRawStoreRef = await this.resolveRealRawStoreRef(normalizedProviderSessionId, workspacePath, homeDirOverride);
668
- if (!resolvedRawStoreRef) {
669
- return null;
670
- }
671
- return {
672
- providerSessionId: normalizedProviderSessionId,
673
- rawStoreRef: resolvedRawStoreRef
674
- };
675
- }
676
- async resolveLaunchedSessionBinding(workspacePath, firstUserMessage, launchedAtMs, homeDirOverride = null) {
677
- for (let attempt = 0; attempt < 20; attempt += 1) {
678
- const matched = this.findLaunchedSessionBindingOnce(workspacePath, firstUserMessage, launchedAtMs, homeDirOverride);
679
- if (matched) {
680
- return matched;
681
- }
682
- if (attempt < 19) {
683
- await sleep(100);
684
- }
685
- }
686
- return null;
687
- }
688
- async resolveRealRawStoreRef(providerSessionId, workspacePath, homeDirOverride = null) {
689
- for (let attempt = 0; attempt < 10; attempt += 1) {
690
- const matched = this.findRawStoreRefOnce(providerSessionId, workspacePath, homeDirOverride);
691
- if (matched) {
692
- return matched;
693
- }
694
- if (attempt < 9) {
695
- await sleep(150);
696
- }
697
- }
698
- return null;
699
- }
700
- findRawStoreRefOnce(providerSessionId, workspacePath, homeDirOverride = null) {
701
- const homeDir = homeDirOverride?.trim()
702
- || this.options.homeDir?.trim()
703
- || process.env.CODINGNS_CODEX_HOME
704
- || join(homedir(), ".codex");
705
- const candidates = this.listSessionFiles(homeDir);
706
- const normalizedWorkspace = normalizeWorkspacePath(workspacePath);
707
- for (const filePath of candidates) {
708
- const meta = readSessionMeta(filePath);
709
- if (!meta) {
710
- continue;
711
- }
712
- if (meta.threadId !== providerSessionId) {
713
- continue;
714
- }
715
- if (meta.cwd && normalizeWorkspacePath(meta.cwd) !== normalizedWorkspace) {
716
- continue;
717
- }
718
- return filePath;
719
- }
720
- return null;
721
- }
722
- listSessionFiles(homeDir) {
723
- const now = new Date();
724
- const currentYear = String(now.getUTCFullYear());
725
- const currentMonth = String(now.getUTCMonth() + 1).padStart(2, "0");
726
- const currentDay = String(now.getUTCDate()).padStart(2, "0");
727
- const preferredRoots = [
728
- join(homeDir, "sessions", currentYear, currentMonth, currentDay),
729
- join(homeDir, "sessions"),
730
- join(homeDir, "archived_sessions")
731
- ];
732
- const seen = new Set();
733
- const files = [];
734
- for (const root of preferredRoots) {
735
- for (const file of walkJsonlFiles(root)) {
736
- if (seen.has(file)) {
737
- continue;
738
- }
739
- seen.add(file);
740
- files.push(file);
741
- }
742
- }
743
- return files;
744
- }
745
- findLaunchedSessionBindingOnce(workspacePath, firstUserMessage, launchedAtMs, homeDirOverride = null) {
746
- const dbPath = findLatestCodexStateDatabase(this.getCodexHomeDir(homeDirOverride));
747
- if (!dbPath) {
748
- return null;
749
- }
750
- const DatabaseSync = loadDatabaseSync();
751
- let db = null;
752
- try {
753
- db = new DatabaseSync(dbPath, { open: true, readOnly: true });
754
- const rows = db.prepare(`SELECT id, rollout_path, cwd, first_user_message, created_at
755
- FROM threads
756
- WHERE source = 'exec'
757
- AND created_at >= ?
758
- ORDER BY created_at DESC
759
- LIMIT 30`).all(Math.max(0, Math.floor((launchedAtMs - 30_000) / 1000)));
760
- const normalizedWorkspace = normalizeWorkspacePath(workspacePath);
761
- const normalizedMessage = firstUserMessage.trim();
762
- for (const row of rows) {
763
- if (normalizeWorkspacePath(row.cwd) !== normalizedWorkspace ||
764
- row.first_user_message.trim() !== normalizedMessage ||
765
- !existsSync(row.rollout_path)) {
766
- continue;
767
- }
768
- return {
769
- providerSessionId: row.id,
770
- rawStoreRef: row.rollout_path
771
- };
772
- }
773
- }
774
- catch {
775
- return null;
776
- }
777
- finally {
778
- db?.close();
779
- }
780
- return null;
781
- }
782
- getCodexHomeDir(homeDirOverride = null) {
783
- return (homeDirOverride?.trim()
784
- || this.options.homeDir?.trim()
785
- || process.env.CODINGNS_CODEX_HOME
786
- || join(homedir(), ".codex"));
787
- }
788
- buildMessage(context, input) {
789
- const stableRef = this.resolveStableMessageRef(context, input.stableIdentity ?? null);
790
- const rawRef = stableRef?.rawRef ??
791
- createRawRef(this.providerId, context.rawStoreRef, ++context.sequence);
792
- const sequence = stableRef?.sequence ?? context.sequence;
793
- const messageId = stableRef?.messageId ?? messageIdFromRawRef(rawRef);
794
- return {
795
- messageId,
796
- provider: this.providerId,
797
- providerSessionId: context.providerSessionId,
798
- role: input.role,
799
- kind: input.kind,
800
- content: input.content,
801
- toolCall: input.toolCall ?? null,
802
- timestamp: input.timestamp,
803
- sequence,
804
- rawRef
805
- };
806
- }
807
- resolveStableMessageRef(context, stableIdentity) {
808
- if (!stableIdentity) {
809
- return null;
810
- }
811
- const existing = context.stableMessageRefByIdentity.get(stableIdentity);
812
- if (existing) {
813
- return existing;
814
- }
815
- context.sequence += 1;
816
- const rawRef = createRawRef(this.providerId, context.rawStoreRef, context.sequence);
817
- const created = {
818
- sequence: context.sequence,
819
- rawRef,
820
- messageId: messageIdFromStableKey(buildCodexStableMessageKey(context.providerSessionId, stableIdentity))
821
- };
822
- context.stableMessageRefByIdentity.set(stableIdentity, created);
823
- return created;
824
- }
825
- async awaitThreadStarted(thread, events, workspacePath, firstUserMessage, launchedAtMs) {
826
- const bufferedEvents = [];
827
- while (true) {
828
- const next = await events.next();
829
- if (next.done) {
830
- const resolved = await this.resolveLaunchedSessionBinding(workspacePath, firstUserMessage, launchedAtMs);
831
- if (resolved) {
832
- return {
833
- providerSessionId: resolved.providerSessionId,
834
- bufferedEvents
835
- };
836
- }
837
- throw new Error("CODEX_THREAD_START_MISSING");
838
- }
839
- const eventType = ensureText(readProp(next.value, "type")).trim();
840
- if (eventType === "thread.started") {
841
- const providerSessionId = pickFirstNonEmpty(ensureText(readProp(next.value, "thread_id")).trim(), ensureText(thread.id).trim());
842
- if (providerSessionId.length === 0) {
843
- throw new Error("CODEX_THREAD_ID_MISSING");
844
- }
845
- return {
846
- providerSessionId,
847
- bufferedEvents
848
- };
849
- }
850
- bufferedEvents.push(next.value);
851
- const resolved = await this.resolveLaunchedSessionBinding(workspacePath, firstUserMessage, launchedAtMs);
852
- if (resolved) {
853
- return {
854
- providerSessionId: resolved.providerSessionId,
855
- bufferedEvents
856
- };
857
- }
858
- }
859
- }
860
- }
861
- function createCodexAppServerTransport(options) {
862
- const commandPath = resolveCodexCommand(options.commandPath);
863
- const launch = resolveCodexCommandLaunch(commandPath, ["app-server"]);
864
- const runtimeEnv = options.runtimeEnv ?? null;
865
- const child = spawn(launch.command, launch.args, {
866
- env: {
867
- ...process.env,
868
- ...(runtimeEnv ?? {})
869
- },
870
- stdio: ["pipe", "pipe", "pipe"],
871
- shell: launch.shell,
872
- windowsHide: true
873
- });
874
- const stdout = createInterface({ input: child.stdout });
875
- let notificationHandler = () => undefined;
876
- let serverRequestHandler = async () => {
877
- throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
878
- };
879
- let requestSequence = 0;
880
- let closed = false;
881
- let activeTurnId = null;
882
- let activeThreadId = null;
883
- let closeHandler = null;
884
- const pendingResponses = new Map();
885
- const finalize = (error) => {
886
- if (closed) {
887
- return;
888
- }
889
- closed = true;
890
- stdout.close();
891
- for (const pending of pendingResponses.values()) {
892
- pending.reject(error ?? new Error("CODEX_APP_SERVER_CLOSED"));
893
- }
894
- pendingResponses.clear();
895
- closeHandler?.(error);
896
- };
897
- child.on("error", (error) => {
898
- finalize(error);
899
- });
900
- child.on("exit", (code, signal) => {
901
- if (closed) {
902
- return;
903
- }
904
- const detail = signal
905
- ? `codex app-server exited with signal ${signal}`
906
- : `codex app-server exited with code ${String(code ?? "unknown")}`;
907
- finalize(new Error(detail));
908
- });
909
- stdout.on("line", (line) => {
910
- const trimmed = line.trim();
911
- if (!trimmed) {
912
- return;
913
- }
914
- let parsed;
915
- try {
916
- parsed = JSON.parse(trimmed);
917
- }
918
- catch {
919
- return;
920
- }
921
- if (typeof parsed.method === "string" && parsed.id !== undefined) {
922
- void Promise.resolve(serverRequestHandler(parsed))
923
- .then((result) => {
924
- writeJsonRpcMessage(child, {
925
- jsonrpc: "2.0",
926
- id: parsed.id,
927
- result
928
- });
929
- })
930
- .catch((error) => {
931
- writeJsonRpcMessage(child, {
932
- jsonrpc: "2.0",
933
- id: parsed.id,
934
- error: {
935
- code: -32000,
936
- message: error instanceof Error ? error.message : "CODEX_APP_SERVER_REQUEST_FAILED"
937
- }
938
- });
939
- });
940
- return;
941
- }
942
- if (typeof parsed.method === "string") {
943
- const method = parsed.method.trim();
944
- const params = readJsonRpcParams(parsed);
945
- if (method === "turn/started") {
946
- activeTurnId = ensureText(readProp(readProp(params, "turn"), "id")).trim() || activeTurnId;
947
- }
948
- if (method === "thread/started") {
949
- activeThreadId = ensureText(readProp(readProp(params, "thread"), "id")).trim() || activeThreadId;
950
- }
951
- void notificationHandler({
952
- method,
953
- params
954
- });
955
- return;
956
- }
957
- const responseId = String(parsed.id ?? "");
958
- const pending = pendingResponses.get(responseId);
959
- if (!pending) {
960
- return;
961
- }
962
- pendingResponses.delete(responseId);
963
- if (parsed.error && typeof parsed.error === "object") {
964
- const message = ensureText(readProp(parsed.error, "message")).trim() || "CODEX_APP_SERVER_ERROR";
965
- pending.reject(new Error(message));
966
- return;
967
- }
968
- pending.resolve(readJsonRpcResult(parsed));
969
- });
970
- return {
971
- async initialize() {
972
- const startedAtMs = performance.now();
973
- await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("initialize", () => ++requestSequence), {
974
- method: "initialize",
975
- params: {
976
- clientInfo: {
977
- name: "codingns-runtime",
978
- version: "0.0.0"
979
- },
980
- capabilities: null
981
- }
982
- });
983
- writeJsonRpcMessage(child, {
984
- jsonrpc: "2.0",
985
- method: "initialized",
986
- params: {}
987
- });
988
- logCodexRuntimeStep("transport.initialize", startedAtMs);
989
- },
990
- async startThread(request) {
991
- const startedAtMs = performance.now();
992
- const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-start", () => ++requestSequence), {
993
- method: "thread/start",
994
- params: createThreadStartParams(request)
995
- });
996
- const thread = toRecord(result.thread);
997
- const providerSessionId = ensureText(thread?.id).trim();
998
- if (!providerSessionId) {
999
- throw new Error("CODEX_APP_SERVER_THREAD_ID_MISSING");
1000
- }
1001
- activeThreadId = providerSessionId;
1002
- logCodexRuntimeStep("transport.thread_start", startedAtMs, {
1003
- sessionId: request.sessionId,
1004
- providerSessionId
1005
- });
1006
- return {
1007
- providerSessionId,
1008
- rawStoreRef: normalizeText(thread?.path) || null
1009
- };
1010
- },
1011
- async resumeThread(request, providerSessionId) {
1012
- const startedAtMs = performance.now();
1013
- const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-resume", () => ++requestSequence), {
1014
- method: "thread/resume",
1015
- params: createThreadResumeParams(request, providerSessionId)
1016
- });
1017
- const thread = toRecord(result.thread);
1018
- activeThreadId = ensureText(thread?.id).trim() || providerSessionId;
1019
- logCodexRuntimeStep("transport.thread_resume", startedAtMs, {
1020
- sessionId: request.sessionId,
1021
- providerSessionId: activeThreadId
1022
- });
1023
- return {
1024
- providerSessionId: activeThreadId,
1025
- rawStoreRef: normalizeText(thread?.path) || null
1026
- };
1027
- },
1028
- async resumeThreadFromHistory(input) {
1029
- const startedAtMs = performance.now();
1030
- const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-resume-history", () => ++requestSequence), {
1031
- method: "thread/resume",
1032
- params: createThreadResumeWithHistoryParams(input)
1033
- });
1034
- const thread = toRecord(result.thread);
1035
- const providerSessionId = ensureText(thread?.id).trim();
1036
- if (!providerSessionId) {
1037
- throw new Error("CODEX_APP_SERVER_THREAD_ID_MISSING");
1038
- }
1039
- activeThreadId = providerSessionId;
1040
- logCodexRuntimeStep("transport.thread_resume_from_history", startedAtMs, {
1041
- providerSessionId
1042
- });
1043
- return {
1044
- providerSessionId,
1045
- rawStoreRef: normalizeText(thread?.path) || null
1046
- };
1047
- },
1048
- async startTurn(request, providerSessionId) {
1049
- const startedAtMs = performance.now();
1050
- const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("turn-start", () => ++requestSequence), {
1051
- method: "turn/start",
1052
- params: createTurnStartParams(request, providerSessionId)
1053
- });
1054
- const turn = toRecord(result.turn);
1055
- activeTurnId = ensureText(readProp(turn, "id")).trim() || activeTurnId;
1056
- logCodexRuntimeStep("transport.turn_start", startedAtMs, {
1057
- sessionId: request.sessionId,
1058
- providerSessionId,
1059
- turnId: activeTurnId
1060
- });
1061
- return {
1062
- notification: buildCodexTurnCompletionNotification(turn, providerSessionId)
1063
- };
1064
- },
1065
- async steerTurn(options) {
1066
- if (!activeThreadId || !activeTurnId) {
1067
- throw new Error("SESSION_NOT_RUNNING");
1068
- }
1069
- try {
1070
- const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("turn-steer", () => ++requestSequence), {
1071
- method: "turn/steer",
1072
- params: createTurnSteerParams(activeThreadId, activeTurnId, options)
1073
- });
1074
- const turnId = ensureText(readProp(result, "turnId")).trim();
1075
- if (turnId) {
1076
- activeTurnId = turnId;
1077
- }
1078
- return {
1079
- turnId: turnId || activeTurnId
1080
- };
1081
- }
1082
- catch (error) {
1083
- throw normalizeCodexTurnSteerError(error);
1084
- }
1085
- },
1086
- async interruptTurn() {
1087
- if (!activeThreadId || !activeTurnId) {
1088
- return;
1089
- }
1090
- await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("turn-interrupt", () => ++requestSequence), {
1091
- method: "turn/interrupt",
1092
- params: {
1093
- threadId: activeThreadId,
1094
- turnId: activeTurnId
1095
- }
1096
- });
1097
- },
1098
- setNotificationHandler(handler) {
1099
- notificationHandler = handler;
1100
- },
1101
- setServerRequestHandler(handler) {
1102
- serverRequestHandler = handler;
1103
- },
1104
- setOnClose(handler) {
1105
- closeHandler = handler;
1106
- },
1107
- isClosed() {
1108
- return closed;
1109
- },
1110
- close() {
1111
- if (closed) {
1112
- return;
1113
- }
1114
- finalize(null);
1115
- if (!child.stdin.destroyed) {
1116
- child.stdin.end();
1117
- }
1118
- if (!child.killed) {
1119
- child.kill("SIGTERM");
1120
- }
1121
- }
1122
- };
1123
- }
1124
- function buildCodexTurnCompletionNotification(turn, threadId) {
1125
- const status = ensureText(readProp(turn, "status")).trim();
1126
- if (status !== "completed" && status !== "failed" && status !== "interrupted") {
1127
- return null;
1128
- }
1129
- return {
1130
- method: "turn/completed",
1131
- params: {
1132
- threadId,
1133
- turn
1134
- }
1135
- };
1136
- }
1137
- function createAsyncEventQueue() {
1138
- const values = [];
1139
- const waiters = [];
1140
- let closed = false;
1141
- let turnId = null;
1142
- return {
1143
- iterator: {
1144
- next() {
1145
- if (values.length > 0) {
1146
- return Promise.resolve({
1147
- done: false,
1148
- value: values.shift()
1149
- });
1150
- }
1151
- if (closed) {
1152
- return Promise.resolve({
1153
- done: true,
1154
- value: undefined
1155
- });
1156
- }
1157
- return new Promise((resolve) => {
1158
- waiters.push(resolve);
1159
- });
1160
- }
1161
- },
1162
- push(value) {
1163
- if (closed) {
1164
- return;
1165
- }
1166
- const waiter = waiters.shift();
1167
- if (waiter) {
1168
- waiter({
1169
- done: false,
1170
- value
1171
- });
1172
- return;
1173
- }
1174
- values.push(value);
1175
- },
1176
- close() {
1177
- if (closed) {
1178
- return;
1179
- }
1180
- closed = true;
1181
- while (waiters.length > 0) {
1182
- waiters.shift()?.({
1183
- done: true,
1184
- value: undefined
1185
- });
1186
- }
1187
- },
1188
- setTurnId(nextTurnId) {
1189
- turnId = nextTurnId;
1190
- },
1191
- getTurnId() {
1192
- return turnId;
1193
- }
1194
- };
1195
- }
1196
- function createCodexTranslatedNotificationForwarder(eventQueue) {
1197
- const seenReplayKeys = new Set();
1198
- return (translated) => {
1199
- if (translated.turnId) {
1200
- eventQueue.setTurnId(translated.turnId);
1201
- }
1202
- for (const event of translated.events) {
1203
- const replayKey = buildCodexTranslatedReplayKey(event);
1204
- if (replayKey) {
1205
- if (seenReplayKeys.has(replayKey)) {
1206
- continue;
1207
- }
1208
- seenReplayKeys.add(replayKey);
1209
- while (seenReplayKeys.size > 1024) {
1210
- const oldest = seenReplayKeys.keys().next().value;
1211
- if (typeof oldest !== "string") {
1212
- break;
1213
- }
1214
- seenReplayKeys.delete(oldest);
1215
- }
1216
- }
1217
- eventQueue.push(event);
1218
- }
1219
- if (translated.terminal) {
1220
- eventQueue.close();
1221
- }
1222
- };
1223
- }
1224
- function buildCodexTranslatedReplayKey(event) {
1225
- const eventType = ensureText(event.type).trim();
1226
- if (!eventType) {
1227
- return null;
1228
- }
1229
- if (eventType === "turn.completed" || eventType === "turn.failed" || eventType === "turn.interrupted") {
1230
- return `${eventType}:${ensureText(readProp(event, "turnId")).trim() || ""}`;
1231
- }
1232
- if (!eventType.startsWith("item.")) {
1233
- return null;
1234
- }
1235
- const item = toRecord(readProp(event, "item"));
1236
- if (!item) {
1237
- return null;
1238
- }
1239
- return JSON.stringify({
1240
- eventType,
1241
- itemType: ensureText(item.type).trim(),
1242
- id: ensureText(item.id).trim(),
1243
- status: ensureText(item.status).trim(),
1244
- text: ensureText(item.text).trim(),
1245
- summary: normalizeReplayKeyText(readProp(item, "summary")),
1246
- content: normalizeReplayKeyText(readProp(item, "content")),
1247
- command: normalizeReplayKeyText(readProp(item, "command")),
1248
- result: normalizeReplayKeyText(readProp(item, "result")),
1249
- output: normalizeReplayKeyText(readProp(item, "output")),
1250
- aggregatedOutput: normalizeReplayKeyText(readProp(item, "aggregated_output")),
1251
- error: normalizeReplayKeyText(readProp(item, "error"))
1252
- });
1253
- }
1254
- function normalizeReplayKeyText(value) {
1255
- if (Array.isArray(value)) {
1256
- return value.map((entry) => normalizeReplayKeyText(entry)).join("\n");
1257
- }
1258
- if (value && typeof value === "object") {
1259
- try {
1260
- return JSON.stringify(value);
1261
- }
1262
- catch {
1263
- return String(value);
1264
- }
1265
- }
1266
- return ensureText(value).trim();
1267
- }
1268
- function createCodexAppServerNotificationTranslator() {
1269
- const agentMessageTextById = new Map();
1270
- const reasoningSummaryPartsById = new Map();
1271
- const reasoningContentPartsById = new Map();
1272
- const resetStreamState = () => {
1273
- agentMessageTextById.clear();
1274
- reasoningSummaryPartsById.clear();
1275
- reasoningContentPartsById.clear();
1276
- };
1277
- const ensureIndexedTextPart = (store, itemId, index) => {
1278
- if (!itemId || !Number.isInteger(index) || index < 0) {
1279
- return null;
1280
- }
1281
- const existing = store.get(itemId) ?? [];
1282
- while (existing.length <= index) {
1283
- existing.push("");
1284
- }
1285
- store.set(itemId, existing);
1286
- return existing;
1287
- };
1288
- const buildReasoningSyntheticItem = (itemId) => {
1289
- // 这里必须复制一份快照,不能把可变数组引用直接塞进事件队列。
1290
- // 否则后续 delta 继续追加时,前一帧事件里的 summary/content 也会被同步改掉,
1291
- // 最终所有帧都会看起来像“最后一帧”,下游稳定消息去重就会把中间增量吃掉。
1292
- const summary = [...(reasoningSummaryPartsById.get(itemId) ?? [])];
1293
- const content = [...(reasoningContentPartsById.get(itemId) ?? [])];
1294
- return {
1295
- type: "reasoning",
1296
- id: itemId,
1297
- summary,
1298
- content
1299
- };
1300
- };
1301
- const translateAgentMessageDelta = (params) => {
1302
- const itemId = ensureText(params.itemId).trim();
1303
- const delta = ensureText(params.delta);
1304
- if (!itemId || delta.length === 0) {
1305
- return {
1306
- events: [],
1307
- terminal: false,
1308
- turnId: ensureText(params.turnId).trim() || null
1309
- };
1310
- }
1311
- const nextText = `${agentMessageTextById.get(itemId) ?? ""}${delta}`;
1312
- agentMessageTextById.set(itemId, nextText);
1313
- return {
1314
- events: [
1315
- {
1316
- type: "item.updated",
1317
- item: {
1318
- type: "agent_message",
1319
- id: itemId,
1320
- text: nextText
1321
- },
1322
- timestamp: nextTimestamp()
1323
- }
1324
- ],
1325
- terminal: false,
1326
- turnId: ensureText(params.turnId).trim() || null
1327
- };
1328
- };
1329
- const translateReasoningSummaryPartAdded = (params) => {
1330
- const itemId = ensureText(params.itemId).trim();
1331
- const summaryIndex = Math.trunc(Number(params.summaryIndex));
1332
- ensureIndexedTextPart(reasoningSummaryPartsById, itemId, summaryIndex);
1333
- return {
1334
- events: [],
1335
- terminal: false,
1336
- turnId: ensureText(params.turnId).trim() || null
1337
- };
1338
- };
1339
- const translateReasoningSummaryTextDelta = (params) => {
1340
- const itemId = ensureText(params.itemId).trim();
1341
- const summaryIndex = Math.trunc(Number(params.summaryIndex));
1342
- const delta = ensureText(params.delta);
1343
- const parts = ensureIndexedTextPart(reasoningSummaryPartsById, itemId, summaryIndex);
1344
- if (!parts || delta.length === 0) {
1345
- return {
1346
- events: [],
1347
- terminal: false,
1348
- turnId: ensureText(params.turnId).trim() || null
1349
- };
1350
- }
1351
- parts[summaryIndex] = `${parts[summaryIndex] ?? ""}${delta}`;
1352
- return {
1353
- events: [
1354
- {
1355
- type: "item.updated",
1356
- item: buildReasoningSyntheticItem(itemId),
1357
- timestamp: nextTimestamp()
1358
- }
1359
- ],
1360
- terminal: false,
1361
- turnId: ensureText(params.turnId).trim() || null
1362
- };
1363
- };
1364
- const translateReasoningTextDelta = (params) => {
1365
- const itemId = ensureText(params.itemId).trim();
1366
- const contentIndex = Math.trunc(Number(params.contentIndex));
1367
- const delta = ensureText(params.delta);
1368
- const parts = ensureIndexedTextPart(reasoningContentPartsById, itemId, contentIndex);
1369
- if (!parts || delta.length === 0) {
1370
- return {
1371
- events: [],
1372
- terminal: false,
1373
- turnId: ensureText(params.turnId).trim() || null
1374
- };
1375
- }
1376
- parts[contentIndex] = `${parts[contentIndex] ?? ""}${delta}`;
1377
- return {
1378
- events: [
1379
- {
1380
- type: "item.updated",
1381
- item: buildReasoningSyntheticItem(itemId),
1382
- timestamp: nextTimestamp()
1383
- }
1384
- ],
1385
- terminal: false,
1386
- turnId: ensureText(params.turnId).trim() || null
1387
- };
1388
- };
1389
- return (notification) => {
1390
- const method = ensureText(notification.method).trim();
1391
- const params = toRecord(notification.params) ?? {};
1392
- if (method === "turn/started") {
1393
- return {
1394
- events: [],
1395
- terminal: false,
1396
- turnId: ensureText(readProp(readProp(params, "turn"), "id")).trim() || null
1397
- };
1398
- }
1399
- if (method === "turn/completed") {
1400
- const turn = toRecord(params.turn);
1401
- const status = ensureText(turn?.status).trim();
1402
- const itemEvents = translateCodexAppServerTurnItems(turn, "item.completed");
1403
- resetStreamState();
1404
- if (status === "failed") {
1405
- return {
1406
- events: [
1407
- ...itemEvents,
1408
- {
1409
- type: "turn.failed",
1410
- timestamp: nextTimestamp(),
1411
- error: ensureText(readProp(turn?.error, "message")).trim() || "codex turn failed"
1412
- }
1413
- ],
1414
- terminal: true,
1415
- turnId: ensureText(turn?.id).trim() || null
1416
- };
1417
- }
1418
- if (status === "interrupted") {
1419
- return {
1420
- events: [
1421
- ...itemEvents,
1422
- {
1423
- type: "turn.interrupted",
1424
- timestamp: nextTimestamp()
1425
- }
1426
- ],
1427
- terminal: true,
1428
- turnId: ensureText(turn?.id).trim() || null
1429
- };
1430
- }
1431
- return {
1432
- events: [
1433
- ...itemEvents,
1434
- {
1435
- type: "turn.completed",
1436
- timestamp: nextTimestamp()
1437
- }
1438
- ],
1439
- terminal: true,
1440
- turnId: ensureText(turn?.id).trim() || null
1441
- };
1442
- }
1443
- if (method === "error") {
1444
- const error = toRecord(params.error);
1445
- const detail = buildCodexAppServerErrorDetail(error);
1446
- if (params.willRetry === true) {
1447
- return {
1448
- events: [],
1449
- terminal: false,
1450
- turnId: ensureText(params.turnId).trim() || null
1451
- };
1452
- }
1453
- resetStreamState();
1454
- return {
1455
- events: [
1456
- {
1457
- type: "turn.failed",
1458
- timestamp: nextTimestamp(),
1459
- error: detail
1460
- }
1461
- ],
1462
- terminal: true,
1463
- turnId: ensureText(params.turnId).trim() || null
1464
- };
1465
- }
1466
- if (method === "item/agentMessage/delta") {
1467
- return translateAgentMessageDelta(params);
1468
- }
1469
- if (method === "item/reasoning/summaryPartAdded") {
1470
- return translateReasoningSummaryPartAdded(params);
1471
- }
1472
- if (method === "item/reasoning/summaryTextDelta") {
1473
- return translateReasoningSummaryTextDelta(params);
1474
- }
1475
- if (method === "item/reasoning/textDelta") {
1476
- return translateReasoningTextDelta(params);
1477
- }
1478
- if (method === "item/started" || method === "item/updated" || method === "item/completed") {
1479
- const item = translateCodexAppServerItem(toRecord(params.item));
1480
- if (!item) {
1481
- return {
1482
- events: [],
1483
- terminal: false,
1484
- turnId: null
1485
- };
1486
- }
1487
- if (ensureText(item.type).trim() === "agent_message") {
1488
- const itemId = ensureText(item.id).trim();
1489
- const itemText = ensureText(item.text);
1490
- if (itemId) {
1491
- if (itemText.length > 0) {
1492
- agentMessageTextById.set(itemId, itemText);
1493
- }
1494
- else if (method === "item/completed") {
1495
- agentMessageTextById.delete(itemId);
1496
- }
1497
- }
1498
- }
1499
- if (ensureText(item.type).trim() === "reasoning") {
1500
- const itemId = ensureText(item.id).trim();
1501
- if (itemId) {
1502
- const summary = Array.isArray(item.summary)
1503
- ? item.summary.map((entry) => ensureText(entry))
1504
- : ensureText(item.summary).trim()
1505
- ? [ensureText(item.summary)]
1506
- : [];
1507
- const content = Array.isArray(item.content)
1508
- ? item.content.map((entry) => ensureText(entry))
1509
- : ensureText(item.text).trim()
1510
- ? [ensureText(item.text)]
1511
- : [];
1512
- if (summary.length > 0) {
1513
- reasoningSummaryPartsById.set(itemId, summary);
1514
- }
1515
- else if (method === "item/completed") {
1516
- reasoningSummaryPartsById.delete(itemId);
1517
- }
1518
- if (content.length > 0) {
1519
- reasoningContentPartsById.set(itemId, content);
1520
- }
1521
- else if (method === "item/completed") {
1522
- reasoningContentPartsById.delete(itemId);
1523
- }
1524
- }
1525
- }
1526
- return {
1527
- events: [
1528
- {
1529
- type: method === "item/started"
1530
- ? "item.started"
1531
- : method === "item/updated"
1532
- ? "item.updated"
1533
- : "item.completed",
1534
- item,
1535
- timestamp: nextTimestamp()
1536
- }
1537
- ],
1538
- terminal: false,
1539
- turnId: null
1540
- };
1541
- }
1542
- return {
1543
- events: [],
1544
- terminal: false,
1545
- turnId: null
1546
- };
1547
- };
1548
- }
1549
- function translateCodexAppServerTurnItems(turn, eventType) {
1550
- const rawItems = Array.isArray(turn?.items) ? turn.items : [];
1551
- const translatedItems = rawItems
1552
- .map((item) => translateCodexAppServerItem(toRecord(item)))
1553
- .filter((item) => item !== null)
1554
- .map((item) => ({
1555
- type: eventType,
1556
- item,
1557
- timestamp: nextTimestamp()
1558
- }));
1559
- if (translatedItems.length > 0) {
1560
- return translatedItems;
1561
- }
1562
- const lastAgentMessage = normalizeCodexTurnLastAgentMessage(turn);
1563
- if (!lastAgentMessage) {
1564
- return [];
1565
- }
1566
- return [
1567
- {
1568
- type: eventType,
1569
- item: {
1570
- type: "agent_message",
1571
- id: ensureText(turn?.id).trim() || "turn-final-message",
1572
- text: lastAgentMessage
1573
- },
1574
- timestamp: nextTimestamp()
1575
- }
1576
- ];
1577
- }
1578
- function normalizeCodexTurnLastAgentMessage(turn) {
1579
- const candidate = readProp(turn, "lastAgentMessage")
1580
- ?? readProp(turn, "last_agent_message")
1581
- ?? readProp(turn, "lastMessage")
1582
- ?? readProp(turn, "last_message");
1583
- if (typeof candidate === "string") {
1584
- const normalized = candidate.trim();
1585
- return normalized.length > 0 ? normalized : null;
1586
- }
1587
- const record = toRecord(candidate);
1588
- if (!record) {
1589
- return null;
1590
- }
1591
- const content = pickFirstNonEmpty(ensureText(record.text).trim(), extractTextBlocks(readProp(record, "content")).trim(), ensureText(readProp(record, "message")).trim());
1592
- return content.length > 0 ? content : null;
1593
- }
1594
- function buildCodexAppServerErrorDetail(error) {
1595
- const message = ensureText(error?.message).trim();
1596
- const additionalDetails = ensureText(error?.additionalDetails).trim();
1597
- if (message && additionalDetails && !message.includes(additionalDetails)) {
1598
- return `${message}\n${additionalDetails}`;
1599
- }
1600
- return message || additionalDetails || "codex app-server error";
1601
- }
1602
- function buildCodexMessageSignature(message) {
1603
- return JSON.stringify({
1604
- role: message.role,
1605
- kind: message.kind,
1606
- content: message.content,
1607
- toolCall: message.toolCall
1608
- ? {
1609
- callId: message.toolCall.callId,
1610
- name: message.toolCall.name,
1611
- input: message.toolCall.input,
1612
- output: message.toolCall.output,
1613
- error: message.toolCall.error,
1614
- status: message.toolCall.status
1615
- }
1616
- : null
1617
- });
1618
- }
1619
- function translateCodexAppServerItem(item) {
1620
- if (!item) {
1621
- return null;
1622
- }
1623
- const itemType = ensureText(item.type).trim();
1624
- if (!itemType) {
1625
- return null;
1626
- }
1627
- if (itemType === "agentMessage") {
1628
- return {
1629
- type: "agent_message",
1630
- id: item.id,
1631
- text: ensureText(item.text).trim()
1632
- };
1633
- }
1634
- if (itemType === "reasoning") {
1635
- return {
1636
- type: "reasoning",
1637
- id: item.id,
1638
- text: Array.isArray(item.content) ? item.content.join("\n") : ensureText(item.text).trim(),
1639
- summary: Array.isArray(item.summary) ? item.summary.join("\n") : ensureText(item.summary).trim()
1640
- };
1641
- }
1642
- if (itemType === "commandExecution") {
1643
- const patchText = extractApplyPatchTextFromCommandLikeValues(item.command);
1644
- if (patchText) {
1645
- return {
1646
- type: "custom_tool_call",
1647
- id: item.id,
1648
- tool: "apply_patch",
1649
- input: patchText,
1650
- output: item.aggregatedOutput,
1651
- error: item.error,
1652
- status: normalizeCodexItemStatus(item.status)
1653
- };
1654
- }
1655
- return {
1656
- type: "command_execution",
1657
- id: item.id,
1658
- command: item.command,
1659
- cwd: item.cwd,
1660
- status: normalizeCodexItemStatus(item.status),
1661
- commandActions: item.commandActions,
1662
- aggregated_output: item.aggregatedOutput,
1663
- exit_code: item.exitCode
1664
- };
1665
- }
1666
- if (itemType === "fileChange") {
1667
- const diffText = buildCodexFileChangeOutput(item.changes);
1668
- return {
1669
- type: "custom_tool_call",
1670
- id: item.id,
1671
- tool: "apply_patch",
1672
- input: diffText,
1673
- output: diffText,
1674
- status: normalizeCodexItemStatus(item.status)
1675
- };
1676
- }
1677
- if (itemType === "mcpToolCall") {
1678
- return {
1679
- type: "mcp_tool_call",
1680
- id: item.id,
1681
- tool: item.tool,
1682
- server: item.server,
1683
- arguments: item.arguments,
1684
- result: item.result,
1685
- error: item.error,
1686
- status: normalizeCodexItemStatus(item.status)
1687
- };
1688
- }
1689
- if (itemType === "dynamicToolCall") {
1690
- const toolName = ensureText(item.tool).trim();
1691
- const patchText = isCodexExecCommandToolName(toolName)
1692
- ? extractApplyPatchTextFromCommandLikeValues(item.arguments)
1693
- : null;
1694
- return {
1695
- type: "custom_tool_call",
1696
- id: item.id,
1697
- tool: patchText ? "apply_patch" : item.tool,
1698
- input: patchText ?? item.arguments,
1699
- output: item.contentItems,
1700
- success: item.success,
1701
- status: normalizeCodexItemStatus(item.status)
1702
- };
1703
- }
1704
- return null;
1705
- }
1706
- export function createThreadOptions(request) {
1707
- const options = {
1708
- workingDirectory: request.workspacePath,
1709
- skipGitRepoCheck: true,
1710
- ...createCodexThreadPermissionOptions(request.options.permissionMode ?? "default")
1711
- };
1712
- if (request.options.model) {
1713
- options.model = request.options.model;
1714
- }
1715
- const reasoningEffort = normalizeCodexReasoningEffort(request.options.reasoningLevel);
1716
- if (reasoningEffort) {
1717
- options.modelReasoningEffort = reasoningEffort;
1718
- }
1719
- const additionalDirectories = Array.from(new Set(request.options.attachments.map((attachment) => dirname(attachment.filePath))));
1720
- if (additionalDirectories.length > 0) {
1721
- options.additionalDirectories = additionalDirectories;
1722
- }
1723
- return options;
1724
- }
1725
- function createThreadStartParams(request) {
1726
- const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
1727
- const params = {
1728
- cwd: request.workspacePath,
1729
- approvalsReviewer: "user"
1730
- };
1731
- if (permissionOptions.approvalPolicy) {
1732
- params.approvalPolicy = permissionOptions.approvalPolicy;
1733
- }
1734
- if (permissionOptions.sandboxMode) {
1735
- params.sandbox = permissionOptions.sandboxMode;
1736
- }
1737
- if (request.options.model) {
1738
- params.model = request.options.model;
1739
- }
1740
- return params;
1741
- }
1742
- function createThreadResumeParams(request, providerSessionId) {
1743
- const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
1744
- const params = {
1745
- threadId: providerSessionId,
1746
- cwd: request.workspacePath,
1747
- approvalsReviewer: "user"
1748
- };
1749
- if (permissionOptions.approvalPolicy) {
1750
- params.approvalPolicy = permissionOptions.approvalPolicy;
1751
- }
1752
- if (permissionOptions.sandboxMode) {
1753
- params.sandbox = permissionOptions.sandboxMode;
1754
- }
1755
- if (request.options.model) {
1756
- params.model = request.options.model;
1757
- }
1758
- return params;
1759
- }
1760
- function createThreadResumeWithHistoryParams(input) {
1761
- const params = {
1762
- threadId: input.providerSessionId && input.providerSessionId.trim().length > 0
1763
- ? input.providerSessionId.trim()
1764
- : "__history_resume__",
1765
- cwd: input.workspacePath,
1766
- history: input.history,
1767
- approvalsReviewer: "user"
1768
- };
1769
- if (input.model) {
1770
- params.model = input.model;
1771
- }
1772
- return params;
1773
- }
1774
- function createTurnStartParams(request, providerSessionId) {
1775
- const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
1776
- const params = {
1777
- threadId: providerSessionId,
1778
- input: createCodexAppServerInput(request),
1779
- cwd: request.workspacePath,
1780
- approvalsReviewer: "user"
1781
- };
1782
- if (permissionOptions.approvalPolicy) {
1783
- params.approvalPolicy = permissionOptions.approvalPolicy;
1784
- }
1785
- if (request.options.model) {
1786
- params.model = request.options.model;
1787
- }
1788
- const reasoningEffort = normalizeCodexReasoningEffort(request.options.reasoningLevel);
1789
- if (reasoningEffort) {
1790
- params.effort = reasoningEffort;
1791
- }
1792
- return params;
1793
- }
1794
- function createTurnSteerParams(providerSessionId, activeTurnId, options) {
1795
- return {
1796
- threadId: providerSessionId,
1797
- expectedTurnId: activeTurnId,
1798
- input: createCodexAppServerInputFromOptions(options)
1799
- };
1800
- }
1801
- function normalizeCodexReasoningEffort(value) {
1802
- const normalized = value?.trim().toLowerCase() ?? null;
1803
- if (!normalized) {
1804
- return null;
1805
- }
1806
- if (normalized === "maximum") {
1807
- return "xhigh";
1808
- }
1809
- if (normalized === "minimal" ||
1810
- normalized === "low" ||
1811
- normalized === "medium" ||
1812
- normalized === "high" ||
1813
- normalized === "xhigh") {
1814
- return normalized;
1815
- }
1816
- return null;
1817
- }
1818
- function createCodexInput(request) {
1819
- if (request.options.attachments.length === 0) {
1820
- return request.options.content;
1821
- }
1822
- const input = [];
1823
- const promptText = request.options.content.trim();
1824
- if (promptText.length > 0) {
1825
- input.push({
1826
- type: "text",
1827
- text: promptText
1828
- });
1829
- }
1830
- request.options.attachments.forEach((attachment) => {
1831
- if (attachment.kind !== "image") {
1832
- return;
1833
- }
1834
- input.push({
1835
- type: "local_image",
1836
- path: attachment.filePath
1837
- });
1838
- });
1839
- return input;
1840
- }
1841
- function createCodexAppServerInput(request) {
1842
- return createCodexAppServerInputFromOptions(request.options);
1843
- }
1844
- function createCodexAppServerInputFromOptions(options) {
1845
- const input = [];
1846
- const promptText = (options.providerPrompt ?? options.content).trim();
1847
- if (promptText.length > 0) {
1848
- input.push({
1849
- type: "text",
1850
- text: promptText
1851
- });
1852
- }
1853
- for (const attachment of options.attachments) {
1854
- if (attachment.kind !== "image") {
1855
- continue;
1856
- }
1857
- input.push({
1858
- type: "localImage",
1859
- path: attachment.filePath
1860
- });
1861
- }
1862
- return input;
1863
- }
1864
- function normalizeCodexTurnSteerError(error) {
1865
- const detail = error instanceof Error ? error.message.trim() : String(error).trim();
1866
- const normalized = detail.toLowerCase();
1867
- if (normalized.includes("method not found")
1868
- || (normalized.includes("turn/steer") && normalized.includes("not found"))
1869
- || normalized.includes("unknown method")) {
1870
- return new Error("IN_RUN_INPUT_NOT_SUPPORTED");
1871
- }
1872
- if (normalized.includes("expectedturnid")
1873
- || normalized.includes("active turn")
1874
- || normalized.includes("turn mismatch")
1875
- || normalized.includes("no active turn")
1876
- || normalized.includes("not running")) {
1877
- return new Error("SESSION_NOT_RUNNING");
1878
- }
1879
- return error instanceof Error ? error : new Error(detail || "CODEX_TURN_STEER_FAILED");
1880
- }
1881
- async function loadCodexClient() {
1882
- const moduleName = "@openai/codex-sdk";
1883
- const runtimeImport = new Function("name", "return import(name);");
1884
- const resolvedModuleName = resolveCodexSdkModuleSpecifier(moduleName);
1885
- const module = (await runtimeImport(resolvedModuleName));
1886
- if (!module.Codex) {
1887
- throw new Error("CODEX_SDK_UNAVAILABLE");
1888
- }
1889
- return new module.Codex();
1890
- }
1891
- function resolveCodexSdkModuleSpecifier(moduleName) {
1892
- const localSdkEntry = findNodeModulesFile(dirname(fileURLToPath(import.meta.url)), ["@openai", "codex-sdk", "dist", "index.js"]);
1893
- if (localSdkEntry) {
1894
- return pathToFileURL(localSdkEntry).href;
1895
- }
1896
- if (typeof import.meta.resolve === "function") {
1897
- return import.meta.resolve(moduleName);
1898
- }
1899
- return moduleName;
1900
- }
1901
- function findNodeModulesFile(startDirectory, relativeSegments) {
1902
- let currentDirectory = startDirectory;
1903
- while (true) {
1904
- const candidate = resolveNodeModulesCandidate(currentDirectory, relativeSegments);
1905
- if (existsSync(candidate)) {
1906
- return candidate;
1907
- }
1908
- const parentDirectory = dirname(currentDirectory);
1909
- if (parentDirectory === currentDirectory) {
1910
- return null;
1911
- }
1912
- currentDirectory = parentDirectory;
1913
- }
1914
- }
1915
- function resolveNodeModulesCandidate(currentDirectory, relativeSegments) {
1916
- if (basename(currentDirectory) === "node_modules") {
1917
- return resolve(currentDirectory, ...relativeSegments);
1918
- }
1919
- return resolve(currentDirectory, "node_modules", ...relativeSegments);
1920
- }
1921
- function buildRuntimeRawStoreRef(providerSessionId) {
1922
- return resolve(process.cwd(), "runtime", "codex", `${providerSessionId}.stream`);
1923
- }
1924
- function pickAvailableCodexRawStoreRef(providerSessionId, candidates, fallbackRawStoreRef) {
1925
- const normalizedProviderSessionId = providerSessionId.trim();
1926
- const normalizedCandidates = [];
1927
- const seen = new Set();
1928
- for (const candidate of candidates) {
1929
- const normalized = candidate?.trim();
1930
- if (!normalized || seen.has(normalized) || !existsSync(normalized)) {
1931
- continue;
1932
- }
1933
- seen.add(normalized);
1934
- normalizedCandidates.push(normalized);
1935
- }
1936
- if (!normalizedProviderSessionId) {
1937
- return normalizedCandidates[0] ?? fallbackRawStoreRef;
1938
- }
1939
- for (const candidate of normalizedCandidates) {
1940
- if (readSessionMeta(candidate)?.threadId === normalizedProviderSessionId) {
1941
- return candidate;
1942
- }
1943
- }
1944
- for (const candidate of normalizedCandidates) {
1945
- if (doesRawStorePathLookLikeThread(candidate, normalizedProviderSessionId)) {
1946
- return candidate;
1947
- }
1948
- }
1949
- for (const candidate of normalizedCandidates) {
1950
- if (isSyntheticRawStoreRef(candidate)) {
1951
- return candidate;
1952
- }
1953
- }
1954
- for (const candidate of normalizedCandidates) {
1955
- if (!readSessionMeta(candidate)) {
1956
- return candidate;
1957
- }
1958
- }
1959
- return fallbackRawStoreRef;
1960
- }
1961
- function doesRawStorePathLookLikeThread(rawStoreRef, providerSessionId) {
1962
- const fileName = basename(rawStoreRef, ".jsonl").trim().toLowerCase();
1963
- const normalizedProviderSessionId = providerSessionId.trim().toLowerCase();
1964
- if (!fileName || !normalizedProviderSessionId) {
1965
- return false;
1966
- }
1967
- return fileName === normalizedProviderSessionId || fileName.includes(normalizedProviderSessionId);
1968
- }
1969
- function resolveRuntimeStoreKey(providerSessionId, sessionId) {
1970
- return providerSessionId.trim() || sessionId;
1971
- }
1972
- function resolveCodexCommand(explicitPath) {
1973
- const explicitCandidate = explicitPath?.trim() ||
1974
- process.env.CODINGNS_CODEX_COMMAND?.trim() ||
1975
- "codex";
1976
- return explicitCandidate;
1977
- }
1978
- function resolveCodexCommandLaunch(commandPath, args) {
1979
- const normalizedCommandPath = commandPath.trim();
1980
- if (isNodeScriptPath(normalizedCommandPath)) {
1981
- return {
1982
- command: process.execPath,
1983
- args: [normalizedCommandPath, ...args],
1984
- shell: false
1985
- };
1986
- }
1987
- return {
1988
- command: normalizedCommandPath,
1989
- args: [...args],
1990
- shell: shouldSpawnViaShellOnWindows(normalizedCommandPath)
1991
- };
1992
- }
1993
- function isNodeScriptPath(commandPath) {
1994
- return /\.(?:c|m)?js$/i.test(commandPath);
1995
- }
1996
- function shouldSpawnViaShellOnWindows(commandPath) {
1997
- if (process.platform !== "win32") {
1998
- return false;
1999
- }
2000
- if (/\.(cmd|bat)$/i.test(commandPath)) {
2001
- return true;
2002
- }
2003
- // Windows 上裸名命令(无扩展名、无路径分隔符)需要 shell 才能从 PATH 解析 .cmd 文件
2004
- const extension = commandPath.split(".").pop()?.toLowerCase();
2005
- const hasPathSep = commandPath.includes("\\") || commandPath.includes("/");
2006
- if (!extension || extension === commandPath.toLowerCase()) {
2007
- if (!hasPathSep) {
2008
- return true;
2009
- }
2010
- }
2011
- return false;
2012
- }
2013
- function nextJsonRpcId(prefix, allocate) {
2014
- return `${prefix}:${allocate()}`;
2015
- }
2016
- function writeJsonRpcMessage(child, payload) {
2017
- if (!child.stdin || child.stdin.destroyed || !child.stdin.writable) {
2018
- throw new Error("CODEX_APP_SERVER_STDIN_UNAVAILABLE");
2019
- }
2020
- child.stdin.write(`${JSON.stringify(payload)}\n`, "utf8");
2021
- }
2022
- function sendJsonRpcRequest(child, pendingResponses, createRequestId, input) {
2023
- const id = createRequestId();
2024
- return new Promise((resolve, reject) => {
2025
- const timeout = setTimeout(() => {
2026
- pendingResponses.delete(id);
2027
- reject(new Error("SERVER_TIMEOUT"));
2028
- }, CODEX_APP_SERVER_REQUEST_TIMEOUT_MS);
2029
- pendingResponses.set(id, {
2030
- resolve: (value) => {
2031
- clearTimeout(timeout);
2032
- resolve(value);
2033
- },
2034
- reject: (error) => {
2035
- clearTimeout(timeout);
2036
- reject(error);
2037
- }
2038
- });
2039
- try {
2040
- writeJsonRpcMessage(child, {
2041
- jsonrpc: "2.0",
2042
- id,
2043
- method: input.method,
2044
- params: input.params
2045
- });
2046
- }
2047
- catch (error) {
2048
- clearTimeout(timeout);
2049
- pendingResponses.delete(id);
2050
- reject(error instanceof Error ? error : new Error("CODEX_APP_SERVER_REQUEST_WRITE_FAILED"));
2051
- }
2052
- });
2053
- }
2054
- function readJsonRpcParams(parsed) {
2055
- return toRecord(parsed.params) ?? {};
2056
- }
2057
- function readJsonRpcResult(parsed) {
2058
- return toRecord(parsed.result) ?? {};
2059
- }
2060
- function resolveResumeThreadId(providerSessionId, rawStoreRef) {
2061
- const normalizedProviderSessionId = ensureText(providerSessionId).trim();
2062
- if (normalizedProviderSessionId.length > 0) {
2063
- return normalizedProviderSessionId;
2064
- }
2065
- const fromRawStore = readThreadIdFromRawStore(rawStoreRef);
2066
- if (fromRawStore) {
2067
- return fromRawStore;
2068
- }
2069
- return null;
2070
- }
2071
- function buildSyntheticResumeHistory(rawStoreRef) {
2072
- const filePath = ensureText(rawStoreRef).trim();
2073
- if (!filePath || !existsSync(filePath)) {
2074
- return [];
2075
- }
2076
- const threadId = readThreadIdFromRawStore(filePath);
2077
- if (!threadId || looksLikeCodexThreadId(threadId)) {
2078
- return [];
2079
- }
2080
- return buildCodexResumeHistoryFromRawStore(filePath);
2081
- }
2082
- function shouldFallbackCodexContinueFromHistory(error, history) {
2083
- if (history.length === 0) {
2084
- return false;
2085
- }
2086
- return isCodexThreadLoadError(error) || isCodexRequestTimeoutError(error);
2087
- }
2088
- function isCodexThreadLoadError(error) {
2089
- const message = error instanceof Error ? error.message : String(error);
2090
- const normalized = message.trim().toLowerCase();
2091
- return (normalized.includes("thread not loaded") ||
2092
- normalized.includes("no rollout found for thread id"));
2093
- }
2094
- function isCodexRequestTimeoutError(error) {
2095
- return error instanceof Error && error.message === "SERVER_TIMEOUT";
2096
- }
2097
- function readProp(value, key) {
2098
- if (!value || typeof value !== "object") {
2099
- return null;
2100
- }
2101
- return value[key];
2102
- }
2103
- function toRecord(value) {
2104
- if (!value || typeof value !== "object" || Array.isArray(value)) {
2105
- return null;
2106
- }
2107
- return value;
2108
- }
2109
- function ensureText(value) {
2110
- if (typeof value === "string") {
2111
- return value;
2112
- }
2113
- if (value === undefined || value === null) {
2114
- return "";
2115
- }
2116
- try {
2117
- return JSON.stringify(value);
2118
- }
2119
- catch {
2120
- return String(value);
2121
- }
2122
- }
2123
- function normalizeText(value) {
2124
- const normalized = ensureText(value).trim();
2125
- return normalized.length > 0 ? normalized : null;
2126
- }
2127
- function readThreadIdFromRawStore(rawStoreRef) {
2128
- const filePath = ensureText(rawStoreRef).trim();
2129
- if (!filePath || !existsSync(filePath)) {
2130
- return null;
2131
- }
2132
- const firstLine = readFileSync(filePath, "utf8")
2133
- .split(/\r?\n/, 1)
2134
- .at(0)
2135
- ?.trim();
2136
- if (!firstLine) {
2137
- return null;
2138
- }
2139
- try {
2140
- const record = JSON.parse(firstLine);
2141
- if (ensureText(record.type).trim() !== "session_meta") {
2142
- return null;
2143
- }
2144
- const threadId = ensureText(record.payload?.id).trim();
2145
- return threadId.length > 0 ? threadId : null;
2146
- }
2147
- catch {
2148
- return null;
2149
- }
2150
- }
2151
- function looksLikeCodexThreadId(value) {
2152
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
2153
- }
2154
- function readSessionMeta(filePath) {
2155
- if (!existsSync(filePath)) {
2156
- return null;
2157
- }
2158
- const firstLine = readFileSync(filePath, "utf8")
2159
- .split(/\r?\n/, 1)
2160
- .at(0)
2161
- ?.trim();
2162
- if (!firstLine) {
2163
- return null;
2164
- }
2165
- try {
2166
- const record = JSON.parse(firstLine);
2167
- if (ensureText(record.type).trim() !== "session_meta") {
2168
- return null;
2169
- }
2170
- const metaThreadId = ensureText(record.payload?.id).trim();
2171
- const fileThreadId = basename(filePath, ".jsonl").trim();
2172
- const threadId = looksLikeCodexThreadId(metaThreadId)
2173
- ? metaThreadId
2174
- : looksLikeCodexThreadId(fileThreadId)
2175
- ? fileThreadId
2176
- : metaThreadId;
2177
- if (!threadId) {
2178
- return null;
2179
- }
2180
- const cwdText = ensureText(record.payload?.cwd).trim();
2181
- return {
2182
- threadId,
2183
- cwd: cwdText.length > 0 ? cwdText : null
2184
- };
2185
- }
2186
- catch {
2187
- return null;
2188
- }
2189
- }
2190
- function isSyntheticRawStoreRef(rawStoreRef) {
2191
- const normalized = rawStoreRef.replaceAll("\\", "/").toLowerCase();
2192
- return normalized.includes("/runtime/codex/") || normalized.startsWith("runtime/codex/");
2193
- }
2194
- function walkJsonlFiles(rootDir) {
2195
- if (!existsSync(rootDir)) {
2196
- return [];
2197
- }
2198
- const queue = [rootDir];
2199
- const files = [];
2200
- while (queue.length > 0) {
2201
- const current = queue.shift();
2202
- if (!current) {
2203
- continue;
2204
- }
2205
- for (const entry of readdirSync(current, { withFileTypes: true })) {
2206
- const fullPath = join(current, entry.name);
2207
- if (entry.isDirectory()) {
2208
- queue.push(fullPath);
2209
- continue;
2210
- }
2211
- if (entry.isFile() && basename(fullPath).endsWith(".jsonl")) {
2212
- files.push(fullPath);
2213
- }
2214
- }
2215
- }
2216
- return files;
2217
- }
2218
- function sleep(ms) {
2219
- return new Promise((resolve) => {
2220
- setTimeout(resolve, ms);
2221
- });
2222
- }
2223
- function findLatestCodexStateDatabase(homeDir) {
2224
- if (!existsSync(homeDir)) {
2225
- return null;
2226
- }
2227
- const candidates = readdirSync(homeDir, { withFileTypes: true })
2228
- .filter((entry) => entry.isFile() && /^state_\d+\.sqlite$/i.test(entry.name))
2229
- .map((entry) => {
2230
- const filePath = join(homeDir, entry.name);
2231
- return {
2232
- filePath,
2233
- mtimeMs: statSync(filePath).mtimeMs
2234
- };
2235
- })
2236
- .sort((left, right) => right.mtimeMs - left.mtimeMs);
2237
- return candidates[0]?.filePath ?? null;
2238
- }
2239
- function pickTimestamp(...candidates) {
2240
- for (const candidate of candidates) {
2241
- const raw = ensureText(readProp(candidate, "timestamp")).trim();
2242
- if (raw.length > 0) {
2243
- return raw;
2244
- }
2245
- }
2246
- return nextTimestamp();
2247
- }
2248
- function pickFirstNonEmpty(...values) {
2249
- for (const value of values) {
2250
- if (value.trim().length > 0) {
2251
- return value.trim();
2252
- }
2253
- }
2254
- return "";
2255
- }
2256
- function isToolItem(itemType) {
2257
- return (itemType === "command_execution" ||
2258
- itemType === "file_change" ||
2259
- itemType === "mcp_tool_call" ||
2260
- itemType === "function_call" ||
2261
- itemType === "custom_tool_call" ||
2262
- itemType === "commandExecution" ||
2263
- itemType === "fileChange" ||
2264
- itemType === "mcpToolCall" ||
2265
- itemType === "dynamicToolCall");
2266
- }
2267
- function inferToolSuccess(item, output) {
2268
- const status = ensureText(readProp(item, "status")).trim().toLowerCase();
2269
- if (status === "failed" || status === "error") {
2270
- return false;
2271
- }
2272
- const lowered = output.toLowerCase();
2273
- if (lowered.includes("apply_patch was requested via exec_command")) {
2274
- return false;
2275
- }
2276
- if (status === "completed" || status === "success" || status === "succeeded") {
2277
- return true;
2278
- }
2279
- const exitCode = readProp(item, "exit_code");
2280
- if (typeof exitCode === "number") {
2281
- return exitCode === 0;
2282
- }
2283
- if (lowered.includes("error")) {
2284
- return false;
2285
- }
2286
- return true;
2287
- }
2288
- function classifyCodexRuntimeFailure(error) {
2289
- const detail = error instanceof Error ? error.message : "codex runtime error";
2290
- if (detail.includes("PROVIDER_SESSION_ID_REQUIRED")) {
2291
- return {
2292
- errorCode: "CODEX_PROVIDER_SESSION_ID_REQUIRED",
2293
- detail
2294
- };
2295
- }
2296
- if (detail.includes("Cannot find package") || detail.includes("ERR_MODULE_NOT_FOUND")) {
2297
- return {
2298
- errorCode: "CODEX_RUNTIME_SDK_MISSING",
2299
- detail
2300
- };
2301
- }
2302
- if (detail.includes("ENOENT") || detail.includes("spawn")) {
2303
- return {
2304
- errorCode: "CODEX_CLI_LAUNCH_FAILED",
2305
- detail
2306
- };
2307
- }
2308
- return {
2309
- errorCode: classifyCodexDetailErrorCode(detail, "CODEX_RUNTIME_ERROR"),
2310
- detail
2311
- };
2312
- }
2313
- function classifyCodexDetailErrorCode(detail, fallback) {
2314
- const normalized = detail.trim();
2315
- if (!normalized) {
2316
- return fallback;
2317
- }
2318
- const statusMatch = normalized.match(/\bstatus\s+(\d{3})\b/i)
2319
- ?? normalized.match(/\bHTTP\s+(\d{3})\b/i)
2320
- ?? normalized.match(/\b(\d{3})\s+(?:Bad Gateway|Too Many Requests|Gateway Timeout|Service Unavailable)\b/i);
2321
- if (!statusMatch) {
2322
- return fallback;
2323
- }
2324
- return `CODEX_HTTP_${statusMatch[1]}`;
2325
- }
2326
- function persistSyntheticUserMessageIfNeeded(rawStoreRef, providerSessionId, input) {
2327
- if (!isSyntheticRawStoreRef(rawStoreRef) || input.content.trim().length === 0) {
2328
- return;
2329
- }
2330
- ensureSyntheticRuntimeFile(rawStoreRef, providerSessionId, input.workspacePath, input.timestamp);
2331
- appendJsonLine(rawStoreRef, {
2332
- timestamp: input.timestamp,
2333
- type: "event_msg",
2334
- payload: {
2335
- type: "user_message",
2336
- message: input.content
2337
- }
2338
- });
2339
- }
2340
- function persistSyntheticEventIfNeeded(rawStoreRef, providerSessionId, event) {
2341
- if (!isSyntheticRawStoreRef(rawStoreRef)) {
2342
- return;
2343
- }
2344
- const serialized = toSyntheticRuntimeRecord(event, providerSessionId);
2345
- if (!serialized) {
2346
- return;
2347
- }
2348
- ensureSyntheticRuntimeFile(rawStoreRef, providerSessionId, null, serialized.timestamp);
2349
- appendJsonLine(rawStoreRef, serialized.record);
2350
- }
2351
- function ensureSyntheticRuntimeFile(rawStoreRef, providerSessionId, workspacePath, timestamp) {
2352
- if (existsSync(rawStoreRef)) {
2353
- return;
2354
- }
2355
- ensureDirectory(dirname(rawStoreRef));
2356
- appendJsonLine(rawStoreRef, {
2357
- timestamp,
2358
- type: "session_meta",
2359
- payload: {
2360
- id: providerSessionId,
2361
- timestamp,
2362
- cwd: workspacePath ?? "",
2363
- originator: "CodingNS Runtime",
2364
- source: "codingns-runtime"
2365
- }
2366
- });
2367
- }
2368
- function toSyntheticRuntimeRecord(event, providerSessionId) {
2369
- const eventType = ensureText(readProp(event, "type")).trim();
2370
- const timestamp = pickTimestamp(event);
2371
- if (eventType === "turn.completed") {
2372
- return {
2373
- timestamp,
2374
- record: {
2375
- timestamp,
2376
- type: "event_msg",
2377
- payload: {
2378
- type: "task_complete"
2379
- }
2380
- }
2381
- };
2382
- }
2383
- if (eventType === "turn.failed") {
2384
- return {
2385
- timestamp,
2386
- record: {
2387
- timestamp,
2388
- type: "event_msg",
2389
- payload: {
2390
- type: "task_failed",
2391
- error: extractTextBlocks(readProp(event, "error")).trim()
2392
- }
2393
- }
2394
- };
2395
- }
2396
- if (!eventType.startsWith("item.")) {
2397
- return null;
2398
- }
2399
- const item = readProp(event, "item");
2400
- const itemType = ensureText(readProp(item, "type")).trim();
2401
- if (itemType.length === 0) {
2402
- return null;
2403
- }
2404
- if (itemType === "agent_message" && eventType === "item.completed") {
2405
- const content = pickFirstNonEmpty(ensureText(readProp(item, "text")).trim(), extractTextBlocks(readProp(item, "content")).trim());
2406
- if (content.length === 0) {
2407
- return null;
2408
- }
2409
- return {
2410
- timestamp,
2411
- record: {
2412
- timestamp,
2413
- type: "event_msg",
2414
- payload: {
2415
- type: "agent_message",
2416
- id: ensureText(readProp(item, "id")).trim() || undefined,
2417
- message: content
2418
- }
2419
- }
2420
- };
2421
- }
2422
- if (itemType === "reasoning" && eventType === "item.completed") {
2423
- const content = pickFirstNonEmpty(ensureText(readProp(item, "text")).trim(), extractTextBlocks(readProp(item, "summary")).trim(), extractTextBlocks(readProp(item, "content")).trim());
2424
- if (content.length === 0) {
2425
- return null;
2426
- }
2427
- return {
2428
- timestamp,
2429
- record: {
2430
- timestamp,
2431
- type: "event_msg",
2432
- payload: {
2433
- type: "agent_reasoning",
2434
- id: ensureText(readProp(item, "id")).trim() || undefined,
2435
- text: content
2436
- }
2437
- }
2438
- };
2439
- }
2440
- if (!isToolItem(itemType)) {
2441
- return null;
2442
- }
2443
- const callId = pickFirstNonEmpty(ensureText(readProp(item, "id")).trim(), ensureText(readProp(item, "call_id")).trim(), `${itemType}-${providerSessionId}`);
2444
- const name = pickFirstNonEmpty(ensureText(readProp(item, "name")).trim(), ensureText(readProp(item, "tool")).trim(), itemType);
2445
- if (eventType === "item.started") {
2446
- const input = resolveCodexToolInput(name, item);
2447
- return {
2448
- timestamp,
2449
- record: {
2450
- timestamp,
2451
- type: "response_item",
2452
- payload: {
2453
- type: mapToolStartItemType(itemType),
2454
- call_id: callId,
2455
- name,
2456
- arguments: input,
2457
- input
2458
- }
2459
- }
2460
- };
2461
- }
2462
- if (eventType !== "item.completed") {
2463
- return null;
2464
- }
2465
- const output = pickFirstNonEmpty(extractTextBlocks(readProp(item, "result")).trim(), extractTextBlocks(readProp(item, "output")).trim(), extractTextBlocks(readProp(item, "aggregated_output")).trim(), extractTextBlocks(readProp(item, "error")).trim());
2466
- return {
2467
- timestamp,
2468
- record: {
2469
- timestamp,
2470
- type: "response_item",
2471
- payload: {
2472
- type: mapToolResultItemType(itemType),
2473
- call_id: callId,
2474
- name,
2475
- output,
2476
- status: inferToolSuccess(item, output) ? "completed" : "failed"
2477
- }
2478
- }
2479
- };
2480
- }
2481
- function mapToolStartItemType(itemType) {
2482
- return itemType === "custom_tool_call" ? "custom_tool_call" : "function_call";
2483
- }
2484
- function mapToolResultItemType(itemType) {
2485
- return itemType === "custom_tool_call" ? "custom_tool_call_output" : "function_call_output";
2486
- }
2487
- function buildCodexStableMessageKey(providerSessionId, stableIdentity) {
2488
- return `codex:${providerSessionId}:${stableIdentity}`;
2489
- }
2490
- function normalizeCodexItemStatus(value) {
2491
- const normalized = ensureText(value).trim();
2492
- if (!normalized) {
2493
- return "in_progress";
2494
- }
2495
- if (normalized === "inProgress") {
2496
- return "running";
2497
- }
2498
- if (normalized === "declined") {
2499
- return "failed";
2500
- }
2501
- return normalized;
2502
- }
2503
- function buildCodexFileChangeOutput(value) {
2504
- if (!Array.isArray(value)) {
2505
- return "";
2506
- }
2507
- const structuredPatch = buildApplyPatchFromFileChangeList(value.map((change) => {
2508
- const record = toRecord(change);
2509
- return {
2510
- path: ensureText(record?.path).trim() || null,
2511
- kind: ensureText(record?.kind).trim() || null
2512
- };
2513
- }));
2514
- if (structuredPatch) {
2515
- return structuredPatch;
2516
- }
2517
- return value
2518
- .map((change) => {
2519
- const record = toRecord(change);
2520
- if (!record) {
2521
- return "";
2522
- }
2523
- const diff = ensureText(record.diff).trim();
2524
- if (diff.length > 0) {
2525
- return diff;
2526
- }
2527
- const path = ensureText(record.path).trim();
2528
- return path.length > 0 ? `Updated ${path}` : "";
2529
- })
2530
- .filter((entry) => entry.length > 0)
2531
- .join("\n\n");
2532
- }
2533
- function isCodexExecCommandToolName(value) {
2534
- const normalized = value.trim().toLowerCase();
2535
- return (normalized === "exec_command" ||
2536
- normalized === "shell_command" ||
2537
- normalized === "command_execution");
2538
- }
2539
- function extractApplyPatchTextFromCommandLikeValues(value) {
2540
- return buildApplyPatchFromCodexCommandLikeValue(value);
2541
- }
2542
- function resolveCodexToolInput(name, item) {
2543
- const rawInput = pickFirstNonEmpty(extractTextBlocks(readProp(item, "arguments")).trim(), extractTextBlocks(readProp(item, "input")).trim(), extractTextBlocks(readProp(item, "command")).trim());
2544
- if (name.trim().toLowerCase() !== "apply_patch") {
2545
- return rawInput;
2546
- }
2547
- return (normalizeApplyPatchText(rawInput, {
2548
- fallbackPaths: collectCodexApplyPatchFallbackPaths(item)
2549
- }) ?? rawInput);
2550
- }
2551
- function collectCodexApplyPatchFallbackPaths(item) {
2552
- const directPaths = [
2553
- ensureText(readProp(item, "path")).trim(),
2554
- ensureText(readProp(item, "filePath")).trim(),
2555
- ensureText(readProp(item, "file_path")).trim()
2556
- ].filter((value) => value.length > 0);
2557
- const rawChanges = readProp(item, "changes");
2558
- const changes = Array.isArray(rawChanges) ? rawChanges : [];
2559
- const changePaths = changes
2560
- .map((change) => ensureText(readProp(change, "path")).trim())
2561
- .filter((value) => value.length > 0);
2562
- const outputText = pickFirstNonEmpty(extractTextBlocks(readProp(item, "result")).trim(), extractTextBlocks(readProp(item, "output")).trim(), extractTextBlocks(readProp(item, "aggregated_output")).trim(), extractTextBlocks(readProp(item, "error")).trim());
2563
- return [
2564
- ...new Set([
2565
- ...directPaths,
2566
- ...changePaths,
2567
- ...extractApplyPatchTargetPathsFromToolOutput(outputText)
2568
- ])
2569
- ];
2570
- }
2571
- //# sourceMappingURL=codex-runtime.js.map