@jingyi0605/codingns 0.1.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 (405) hide show
  1. package/README.md +24 -0
  2. package/bin/codingns.mjs +173 -0
  3. package/dist/public/assets/TerminalPage-6GBZ9nXN.css +32 -0
  4. package/dist/public/assets/TerminalPage-Dj_VDew3.js +54 -0
  5. package/dist/public/assets/index-C1GZV2wq.js +106 -0
  6. package/dist/public/assets/index-DU7f8NaZ.css +1 -0
  7. package/dist/public/index.html +13 -0
  8. package/dist/public/logo.png +0 -0
  9. package/dist/public/logo.svg +162 -0
  10. package/dist/server/config/env.d.ts +24 -0
  11. package/dist/server/config/env.js +152 -0
  12. package/dist/server/config/env.js.map +1 -0
  13. package/dist/server/config/opencode-base-url-resolver.d.ts +37 -0
  14. package/dist/server/config/opencode-base-url-resolver.js +422 -0
  15. package/dist/server/config/opencode-base-url-resolver.js.map +1 -0
  16. package/dist/server/main.d.ts +1 -0
  17. package/dist/server/main.js +3 -0
  18. package/dist/server/main.js.map +1 -0
  19. package/dist/server/middlewares/auth-guard.d.ts +4 -0
  20. package/dist/server/middlewares/auth-guard.js +35 -0
  21. package/dist/server/middlewares/auth-guard.js.map +1 -0
  22. package/dist/server/modules/auth/auth-controller.d.ts +15 -0
  23. package/dist/server/modules/auth/auth-controller.js +20 -0
  24. package/dist/server/modules/auth/auth-controller.js.map +1 -0
  25. package/dist/server/modules/auth/auth-service.d.ts +44 -0
  26. package/dist/server/modules/auth/auth-service.js +151 -0
  27. package/dist/server/modules/auth/auth-service.js.map +1 -0
  28. package/dist/server/modules/bootstrap/bootstrap-controller.d.ts +10 -0
  29. package/dist/server/modules/bootstrap/bootstrap-controller.js +13 -0
  30. package/dist/server/modules/bootstrap/bootstrap-controller.js.map +1 -0
  31. package/dist/server/modules/bootstrap/bootstrap-service.d.ts +20 -0
  32. package/dist/server/modules/bootstrap/bootstrap-service.js +71 -0
  33. package/dist/server/modules/bootstrap/bootstrap-service.js.map +1 -0
  34. package/dist/server/modules/client/client-controller.d.ts +9 -0
  35. package/dist/server/modules/client/client-controller.js +65 -0
  36. package/dist/server/modules/client/client-controller.js.map +1 -0
  37. package/dist/server/modules/client/client-service.d.ts +37 -0
  38. package/dist/server/modules/client/client-service.js +186 -0
  39. package/dist/server/modules/client/client-service.js.map +1 -0
  40. package/dist/server/modules/file/file-access-guard.d.ts +27 -0
  41. package/dist/server/modules/file/file-access-guard.js +99 -0
  42. package/dist/server/modules/file/file-access-guard.js.map +1 -0
  43. package/dist/server/modules/file/file-constants.d.ts +6 -0
  44. package/dist/server/modules/file/file-constants.js +7 -0
  45. package/dist/server/modules/file/file-constants.js.map +1 -0
  46. package/dist/server/modules/file/file-content-service.d.ts +65 -0
  47. package/dist/server/modules/file/file-content-service.js +239 -0
  48. package/dist/server/modules/file/file-content-service.js.map +1 -0
  49. package/dist/server/modules/file/file-context-controller.d.ts +29 -0
  50. package/dist/server/modules/file/file-context-controller.js +52 -0
  51. package/dist/server/modules/file/file-context-controller.js.map +1 -0
  52. package/dist/server/modules/file/file-context-service.d.ts +22 -0
  53. package/dist/server/modules/file/file-context-service.js +90 -0
  54. package/dist/server/modules/file/file-context-service.js.map +1 -0
  55. package/dist/server/modules/file/file-controller.d.ts +68 -0
  56. package/dist/server/modules/file/file-controller.js +111 -0
  57. package/dist/server/modules/file/file-controller.js.map +1 -0
  58. package/dist/server/modules/file/file-preview-service.d.ts +19 -0
  59. package/dist/server/modules/file/file-preview-service.js +60 -0
  60. package/dist/server/modules/file/file-preview-service.js.map +1 -0
  61. package/dist/server/modules/file/file-search-service.d.ts +13 -0
  62. package/dist/server/modules/file/file-search-service.js +62 -0
  63. package/dist/server/modules/file/file-search-service.js.map +1 -0
  64. package/dist/server/modules/file/file-tree-service.d.ts +7 -0
  65. package/dist/server/modules/file/file-tree-service.js +43 -0
  66. package/dist/server/modules/file/file-tree-service.js.map +1 -0
  67. package/dist/server/modules/file/file-version-checker.d.ts +10 -0
  68. package/dist/server/modules/file/file-version-checker.js +30 -0
  69. package/dist/server/modules/file/file-version-checker.js.map +1 -0
  70. package/dist/server/modules/file/path-normalizer.d.ts +2 -0
  71. package/dist/server/modules/file/path-normalizer.js +80 -0
  72. package/dist/server/modules/file/path-normalizer.js.map +1 -0
  73. package/dist/server/modules/file/recent-file-service.d.ts +10 -0
  74. package/dist/server/modules/file/recent-file-service.js +28 -0
  75. package/dist/server/modules/file/recent-file-service.js.map +1 -0
  76. package/dist/server/modules/git/commit-draft-service.d.ts +7 -0
  77. package/dist/server/modules/git/commit-draft-service.js +76 -0
  78. package/dist/server/modules/git/commit-draft-service.js.map +1 -0
  79. package/dist/server/modules/git/commit-orchestrator.d.ts +28 -0
  80. package/dist/server/modules/git/commit-orchestrator.js +47 -0
  81. package/dist/server/modules/git/commit-orchestrator.js.map +1 -0
  82. package/dist/server/modules/git/commit-rule-engine.d.ts +5 -0
  83. package/dist/server/modules/git/commit-rule-engine.js +22 -0
  84. package/dist/server/modules/git/commit-rule-engine.js.map +1 -0
  85. package/dist/server/modules/git/git-command-runner.d.ts +16 -0
  86. package/dist/server/modules/git/git-command-runner.js +102 -0
  87. package/dist/server/modules/git/git-command-runner.js.map +1 -0
  88. package/dist/server/modules/git/git-controller.d.ts +104 -0
  89. package/dist/server/modules/git/git-controller.js +140 -0
  90. package/dist/server/modules/git/git-controller.js.map +1 -0
  91. package/dist/server/modules/git/git-read-service.d.ts +15 -0
  92. package/dist/server/modules/git/git-read-service.js +393 -0
  93. package/dist/server/modules/git/git-read-service.js.map +1 -0
  94. package/dist/server/modules/git/git-rule-repository.d.ts +9 -0
  95. package/dist/server/modules/git/git-rule-repository.js +43 -0
  96. package/dist/server/modules/git/git-rule-repository.js.map +1 -0
  97. package/dist/server/modules/git/git-write-service.d.ts +28 -0
  98. package/dist/server/modules/git/git-write-service.js +330 -0
  99. package/dist/server/modules/git/git-write-service.js.map +1 -0
  100. package/dist/server/modules/git/types.d.ts +99 -0
  101. package/dist/server/modules/git/types.js +2 -0
  102. package/dist/server/modules/git/types.js.map +1 -0
  103. package/dist/server/modules/git/workspace-repo-guard.d.ts +17 -0
  104. package/dist/server/modules/git/workspace-repo-guard.js +124 -0
  105. package/dist/server/modules/git/workspace-repo-guard.js.map +1 -0
  106. package/dist/server/modules/preferences/quick-phrase-controller.d.ts +17 -0
  107. package/dist/server/modules/preferences/quick-phrase-controller.js +37 -0
  108. package/dist/server/modules/preferences/quick-phrase-controller.js.map +1 -0
  109. package/dist/server/modules/preferences/quick-phrase-service.d.ts +13 -0
  110. package/dist/server/modules/preferences/quick-phrase-service.js +67 -0
  111. package/dist/server/modules/preferences/quick-phrase-service.js.map +1 -0
  112. package/dist/server/modules/provider/claude-model-options.d.ts +5 -0
  113. package/dist/server/modules/provider/claude-model-options.js +116 -0
  114. package/dist/server/modules/provider/claude-model-options.js.map +1 -0
  115. package/dist/server/modules/provider/codex-model-options.d.ts +23 -0
  116. package/dist/server/modules/provider/codex-model-options.js +308 -0
  117. package/dist/server/modules/provider/codex-model-options.js.map +1 -0
  118. package/dist/server/modules/provider/opencode-model-options.d.ts +30 -0
  119. package/dist/server/modules/provider/opencode-model-options.js +362 -0
  120. package/dist/server/modules/provider/opencode-model-options.js.map +1 -0
  121. package/dist/server/modules/provider/provider-controller.d.ts +33 -0
  122. package/dist/server/modules/provider/provider-controller.js +50 -0
  123. package/dist/server/modules/provider/provider-controller.js.map +1 -0
  124. package/dist/server/modules/sessions/session-activity-inspector.d.ts +10 -0
  125. package/dist/server/modules/sessions/session-activity-inspector.js +271 -0
  126. package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -0
  127. package/dist/server/modules/sessions/session-changed-file-service.d.ts +14 -0
  128. package/dist/server/modules/sessions/session-changed-file-service.js +175 -0
  129. package/dist/server/modules/sessions/session-changed-file-service.js.map +1 -0
  130. package/dist/server/modules/sessions/session-controller.d.ts +134 -0
  131. package/dist/server/modules/sessions/session-controller.js +253 -0
  132. package/dist/server/modules/sessions/session-controller.js.map +1 -0
  133. package/dist/server/modules/sessions/session-history-service.d.ts +128 -0
  134. package/dist/server/modules/sessions/session-history-service.js +1558 -0
  135. package/dist/server/modules/sessions/session-history-service.js.map +1 -0
  136. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +191 -0
  137. package/dist/server/modules/sessions/session-live-runtime-service.js +1303 -0
  138. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -0
  139. package/dist/server/modules/sessions/session-message-attachment-service.d.ts +42 -0
  140. package/dist/server/modules/sessions/session-message-attachment-service.js +244 -0
  141. package/dist/server/modules/sessions/session-message-attachment-service.js.map +1 -0
  142. package/dist/server/modules/sessions/session-provider-error-mapper.d.ts +2 -0
  143. package/dist/server/modules/sessions/session-provider-error-mapper.js +101 -0
  144. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -0
  145. package/dist/server/modules/terminal/command-template-service.d.ts +48 -0
  146. package/dist/server/modules/terminal/command-template-service.js +273 -0
  147. package/dist/server/modules/terminal/command-template-service.js.map +1 -0
  148. package/dist/server/modules/terminal/runtime/adapters/embedded-pty-runtime-adapter.d.ts +22 -0
  149. package/dist/server/modules/terminal/runtime/adapters/embedded-pty-runtime-adapter.js +30 -0
  150. package/dist/server/modules/terminal/runtime/adapters/embedded-pty-runtime-adapter.js.map +1 -0
  151. package/dist/server/modules/terminal/runtime/adapters/tmux-runtime-adapter.d.ts +31 -0
  152. package/dist/server/modules/terminal/runtime/adapters/tmux-runtime-adapter.js +199 -0
  153. package/dist/server/modules/terminal/runtime/adapters/tmux-runtime-adapter.js.map +1 -0
  154. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.d.ts +36 -0
  155. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.js +141 -0
  156. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.js.map +1 -0
  157. package/dist/server/modules/terminal/runtime/pty-runtime-manager.d.ts +29 -0
  158. package/dist/server/modules/terminal/runtime/pty-runtime-manager.js +138 -0
  159. package/dist/server/modules/terminal/runtime/pty-runtime-manager.js.map +1 -0
  160. package/dist/server/modules/terminal/runtime/terminal-log-file-store.d.ts +14 -0
  161. package/dist/server/modules/terminal/runtime/terminal-log-file-store.js +47 -0
  162. package/dist/server/modules/terminal/runtime/terminal-log-file-store.js.map +1 -0
  163. package/dist/server/modules/terminal/runtime/terminal-log-spooler.d.ts +28 -0
  164. package/dist/server/modules/terminal/runtime/terminal-log-spooler.js +162 -0
  165. package/dist/server/modules/terminal/runtime/terminal-log-spooler.js.map +1 -0
  166. package/dist/server/modules/terminal/runtime/terminal-output-buffer.d.ts +18 -0
  167. package/dist/server/modules/terminal/runtime/terminal-output-buffer.js +109 -0
  168. package/dist/server/modules/terminal/runtime/terminal-output-buffer.js.map +1 -0
  169. package/dist/server/modules/terminal/runtime/terminal-runtime-adapter.d.ts +34 -0
  170. package/dist/server/modules/terminal/runtime/terminal-runtime-adapter.js +2 -0
  171. package/dist/server/modules/terminal/runtime/terminal-runtime-adapter.js.map +1 -0
  172. package/dist/server/modules/terminal/runtime/terminal-runtime-manager.d.ts +41 -0
  173. package/dist/server/modules/terminal/runtime/terminal-runtime-manager.js +138 -0
  174. package/dist/server/modules/terminal/runtime/terminal-runtime-manager.js.map +1 -0
  175. package/dist/server/modules/terminal/template-port-runtime.d.ts +6 -0
  176. package/dist/server/modules/terminal/template-port-runtime.js +199 -0
  177. package/dist/server/modules/terminal/template-port-runtime.js.map +1 -0
  178. package/dist/server/modules/terminal/terminal-controller.d.ts +94 -0
  179. package/dist/server/modules/terminal/terminal-controller.js +236 -0
  180. package/dist/server/modules/terminal/terminal-controller.js.map +1 -0
  181. package/dist/server/modules/terminal/terminal-history.d.ts +18 -0
  182. package/dist/server/modules/terminal/terminal-history.js +2 -0
  183. package/dist/server/modules/terminal/terminal-history.js.map +1 -0
  184. package/dist/server/modules/terminal/terminal-paths.d.ts +1 -0
  185. package/dist/server/modules/terminal/terminal-paths.js +27 -0
  186. package/dist/server/modules/terminal/terminal-paths.js.map +1 -0
  187. package/dist/server/modules/terminal/terminal-service.d.ts +112 -0
  188. package/dist/server/modules/terminal/terminal-service.js +794 -0
  189. package/dist/server/modules/terminal/terminal-service.js.map +1 -0
  190. package/dist/server/modules/terminal/terminal-shell.d.ts +13 -0
  191. package/dist/server/modules/terminal/terminal-shell.js +293 -0
  192. package/dist/server/modules/terminal/terminal-shell.js.map +1 -0
  193. package/dist/server/modules/workbench/workbench-controller.d.ts +7 -0
  194. package/dist/server/modules/workbench/workbench-controller.js +22 -0
  195. package/dist/server/modules/workbench/workbench-controller.js.map +1 -0
  196. package/dist/server/modules/workbench/workbench-service.d.ts +19 -0
  197. package/dist/server/modules/workbench/workbench-service.js +46 -0
  198. package/dist/server/modules/workbench/workbench-service.js.map +1 -0
  199. package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +65 -0
  200. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +176 -0
  201. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -0
  202. package/dist/server/modules/workspace/workspace-controller.d.ts +57 -0
  203. package/dist/server/modules/workspace/workspace-controller.js +38 -0
  204. package/dist/server/modules/workspace/workspace-controller.js.map +1 -0
  205. package/dist/server/modules/workspace/workspace-service.d.ts +81 -0
  206. package/dist/server/modules/workspace/workspace-service.js +659 -0
  207. package/dist/server/modules/workspace/workspace-service.js.map +1 -0
  208. package/dist/server/routes/auth.d.ts +3 -0
  209. package/dist/server/routes/auth.js +6 -0
  210. package/dist/server/routes/auth.js.map +1 -0
  211. package/dist/server/routes/client.d.ts +3 -0
  212. package/dist/server/routes/client.js +6 -0
  213. package/dist/server/routes/client.js.map +1 -0
  214. package/dist/server/routes/files.d.ts +3 -0
  215. package/dist/server/routes/files.js +15 -0
  216. package/dist/server/routes/files.js.map +1 -0
  217. package/dist/server/routes/git.d.ts +3 -0
  218. package/dist/server/routes/git.js +18 -0
  219. package/dist/server/routes/git.js.map +1 -0
  220. package/dist/server/routes/preferences.d.ts +3 -0
  221. package/dist/server/routes/preferences.js +5 -0
  222. package/dist/server/routes/preferences.js.map +1 -0
  223. package/dist/server/routes/providers.d.ts +3 -0
  224. package/dist/server/routes/providers.js +6 -0
  225. package/dist/server/routes/providers.js.map +1 -0
  226. package/dist/server/routes/public.d.ts +3 -0
  227. package/dist/server/routes/public.js +5 -0
  228. package/dist/server/routes/public.js.map +1 -0
  229. package/dist/server/routes/session-contexts.d.ts +3 -0
  230. package/dist/server/routes/session-contexts.js +6 -0
  231. package/dist/server/routes/session-contexts.js.map +1 -0
  232. package/dist/server/routes/sessions.d.ts +3 -0
  233. package/dist/server/routes/sessions.js +24 -0
  234. package/dist/server/routes/sessions.js.map +1 -0
  235. package/dist/server/routes/terminals.d.ts +3 -0
  236. package/dist/server/routes/terminals.js +17 -0
  237. package/dist/server/routes/terminals.js.map +1 -0
  238. package/dist/server/routes/workbench.d.ts +3 -0
  239. package/dist/server/routes/workbench.js +4 -0
  240. package/dist/server/routes/workbench.js.map +1 -0
  241. package/dist/server/routes/workspaces.d.ts +3 -0
  242. package/dist/server/routes/workspaces.js +10 -0
  243. package/dist/server/routes/workspaces.js.map +1 -0
  244. package/dist/server/server/create-server.d.ts +103 -0
  245. package/dist/server/server/create-server.js +259 -0
  246. package/dist/server/server/create-server.js.map +1 -0
  247. package/dist/server/server/start-host.d.ts +8 -0
  248. package/dist/server/server/start-host.js +40 -0
  249. package/dist/server/server/start-host.js.map +1 -0
  250. package/dist/server/server/static-web.d.ts +2 -0
  251. package/dist/server/server/static-web.js +75 -0
  252. package/dist/server/server/static-web.js.map +1 -0
  253. package/dist/server/shared/errors/app-error.d.ts +13 -0
  254. package/dist/server/shared/errors/app-error.js +16 -0
  255. package/dist/server/shared/errors/app-error.js.map +1 -0
  256. package/dist/server/shared/http/error-handler.d.ts +9 -0
  257. package/dist/server/shared/http/error-handler.js +25 -0
  258. package/dist/server/shared/http/error-handler.js.map +1 -0
  259. package/dist/server/shared/utils/hash.d.ts +4 -0
  260. package/dist/server/shared/utils/hash.js +27 -0
  261. package/dist/server/shared/utils/hash.js.map +1 -0
  262. package/dist/server/shared/utils/id.d.ts +1 -0
  263. package/dist/server/shared/utils/id.js +5 -0
  264. package/dist/server/shared/utils/id.js.map +1 -0
  265. package/dist/server/shared/utils/perf-log.d.ts +6 -0
  266. package/dist/server/shared/utils/perf-log.js +40 -0
  267. package/dist/server/shared/utils/perf-log.js.map +1 -0
  268. package/dist/server/shared/utils/time.d.ts +2 -0
  269. package/dist/server/shared/utils/time.js +7 -0
  270. package/dist/server/shared/utils/time.js.map +1 -0
  271. package/dist/server/shared/utils/tokens.d.ts +1 -0
  272. package/dist/server/shared/utils/tokens.js +5 -0
  273. package/dist/server/shared/utils/tokens.js.map +1 -0
  274. package/dist/server/storage/repositories/auth-token-repository.d.ts +9 -0
  275. package/dist/server/storage/repositories/auth-token-repository.js +45 -0
  276. package/dist/server/storage/repositories/auth-token-repository.js.map +1 -0
  277. package/dist/server/storage/repositories/auth-user-repository.d.ts +11 -0
  278. package/dist/server/storage/repositories/auth-user-repository.js +61 -0
  279. package/dist/server/storage/repositories/auth-user-repository.js.map +1 -0
  280. package/dist/server/storage/repositories/bootstrap-state-repository.d.ts +8 -0
  281. package/dist/server/storage/repositories/bootstrap-state-repository.js +29 -0
  282. package/dist/server/storage/repositories/bootstrap-state-repository.js.map +1 -0
  283. package/dist/server/storage/repositories/commit-rule-profile-repository.d.ts +8 -0
  284. package/dist/server/storage/repositories/commit-rule-profile-repository.js +48 -0
  285. package/dist/server/storage/repositories/commit-rule-profile-repository.js.map +1 -0
  286. package/dist/server/storage/repositories/file-context-binding-repository.d.ts +12 -0
  287. package/dist/server/storage/repositories/file-context-binding-repository.js +130 -0
  288. package/dist/server/storage/repositories/file-context-binding-repository.js.map +1 -0
  289. package/dist/server/storage/repositories/recent-file-repository.d.ts +10 -0
  290. package/dist/server/storage/repositories/recent-file-repository.js +64 -0
  291. package/dist/server/storage/repositories/recent-file-repository.js.map +1 -0
  292. package/dist/server/storage/repositories/session-binding-repository.d.ts +10 -0
  293. package/dist/server/storage/repositories/session-binding-repository.js +63 -0
  294. package/dist/server/storage/repositories/session-binding-repository.js.map +1 -0
  295. package/dist/server/storage/repositories/session-changed-file-repository.d.ts +11 -0
  296. package/dist/server/storage/repositories/session-changed-file-repository.js +94 -0
  297. package/dist/server/storage/repositories/session-changed-file-repository.js.map +1 -0
  298. package/dist/server/storage/repositories/session-index-repository.d.ts +11 -0
  299. package/dist/server/storage/repositories/session-index-repository.js +200 -0
  300. package/dist/server/storage/repositories/session-index-repository.js.map +1 -0
  301. package/dist/server/storage/repositories/session-message-attachment-repository.d.ts +13 -0
  302. package/dist/server/storage/repositories/session-message-attachment-repository.js +139 -0
  303. package/dist/server/storage/repositories/session-message-attachment-repository.js.map +1 -0
  304. package/dist/server/storage/repositories/session-send-queue-repository.d.ts +15 -0
  305. package/dist/server/storage/repositories/session-send-queue-repository.js +165 -0
  306. package/dist/server/storage/repositories/session-send-queue-repository.js.map +1 -0
  307. package/dist/server/storage/repositories/session-state-repository.d.ts +8 -0
  308. package/dist/server/storage/repositories/session-state-repository.js +60 -0
  309. package/dist/server/storage/repositories/session-state-repository.js.map +1 -0
  310. package/dist/server/storage/repositories/session-status-snapshot-repository.d.ts +8 -0
  311. package/dist/server/storage/repositories/session-status-snapshot-repository.js +49 -0
  312. package/dist/server/storage/repositories/session-status-snapshot-repository.js.map +1 -0
  313. package/dist/server/storage/repositories/terminal-command-template-repository.d.ts +11 -0
  314. package/dist/server/storage/repositories/terminal-command-template-repository.js +99 -0
  315. package/dist/server/storage/repositories/terminal-command-template-repository.js.map +1 -0
  316. package/dist/server/storage/repositories/terminal-instance-repository.d.ts +23 -0
  317. package/dist/server/storage/repositories/terminal-instance-repository.js +149 -0
  318. package/dist/server/storage/repositories/terminal-instance-repository.js.map +1 -0
  319. package/dist/server/storage/repositories/terminal-log-file-repository.d.ts +20 -0
  320. package/dist/server/storage/repositories/terminal-log-file-repository.js +106 -0
  321. package/dist/server/storage/repositories/terminal-log-file-repository.js.map +1 -0
  322. package/dist/server/storage/repositories/terminal-log-segment-repository.d.ts +11 -0
  323. package/dist/server/storage/repositories/terminal-log-segment-repository.js +110 -0
  324. package/dist/server/storage/repositories/terminal-log-segment-repository.js.map +1 -0
  325. package/dist/server/storage/repositories/terminal-runtime-session-repository.d.ts +24 -0
  326. package/dist/server/storage/repositories/terminal-runtime-session-repository.js +134 -0
  327. package/dist/server/storage/repositories/terminal-runtime-session-repository.js.map +1 -0
  328. package/dist/server/storage/repositories/user-quick-phrase-preference-repository.d.ts +8 -0
  329. package/dist/server/storage/repositories/user-quick-phrase-preference-repository.js +37 -0
  330. package/dist/server/storage/repositories/user-quick-phrase-preference-repository.js.map +1 -0
  331. package/dist/server/storage/repositories/workspace-repository.d.ts +16 -0
  332. package/dist/server/storage/repositories/workspace-repository.js +71 -0
  333. package/dist/server/storage/repositories/workspace-repository.js.map +1 -0
  334. package/dist/server/storage/sqlite/client.d.ts +6 -0
  335. package/dist/server/storage/sqlite/client.js +446 -0
  336. package/dist/server/storage/sqlite/client.js.map +1 -0
  337. package/dist/server/storage/sqlite/schema.sql +357 -0
  338. package/dist/server/types/domain.d.ts +306 -0
  339. package/dist/server/types/domain.js +2 -0
  340. package/dist/server/types/domain.js.map +1 -0
  341. package/dist/server/ws/terminal-ws-hub.d.ts +32 -0
  342. package/dist/server/ws/terminal-ws-hub.js +181 -0
  343. package/dist/server/ws/terminal-ws-hub.js.map +1 -0
  344. package/dist/server/ws/workbench-ws-hub.d.ts +30 -0
  345. package/dist/server/ws/workbench-ws-hub.js +480 -0
  346. package/dist/server/ws/workbench-ws-hub.js.map +1 -0
  347. package/dist/server/ws/ws-auth-guard.d.ts +7 -0
  348. package/dist/server/ws/ws-auth-guard.js +28 -0
  349. package/dist/server/ws/ws-auth-guard.js.map +1 -0
  350. package/dist/server/ws/ws-server.d.ts +11 -0
  351. package/dist/server/ws/ws-server.js +218 -0
  352. package/dist/server/ws/ws-server.js.map +1 -0
  353. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.d.ts +36 -0
  354. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js +213 -0
  355. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js.map +1 -0
  356. package/node_modules/@codingns/session-sync-core/dist/index.d.ts +12 -0
  357. package/node_modules/@codingns/session-sync-core/dist/index.js +13 -0
  358. package/node_modules/@codingns/session-sync-core/dist/index.js.map +1 -0
  359. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +30 -0
  360. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +567 -0
  361. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -0
  362. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +41 -0
  363. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +1365 -0
  364. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -0
  365. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.d.ts +41 -0
  366. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js +280 -0
  367. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js.map +1 -0
  368. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +53 -0
  369. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +745 -0
  370. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -0
  371. package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +25 -0
  372. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +284 -0
  373. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -0
  374. package/node_modules/@codingns/session-sync-core/dist/registry.d.ts +7 -0
  375. package/node_modules/@codingns/session-sync-core/dist/registry.js +22 -0
  376. package/node_modules/@codingns/session-sync-core/dist/registry.js.map +1 -0
  377. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +18 -0
  378. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +236 -0
  379. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -0
  380. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.d.ts +21 -0
  381. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +732 -0
  382. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -0
  383. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.d.ts +1 -0
  384. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js +16 -0
  385. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js.map +1 -0
  386. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +26 -0
  387. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +892 -0
  388. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -0
  389. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.d.ts +31 -0
  390. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js +626 -0
  391. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js.map +1 -0
  392. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.d.ts +18 -0
  393. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js +148 -0
  394. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js.map +1 -0
  395. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +141 -0
  396. package/node_modules/@codingns/session-sync-core/dist/runtime/types.js +2 -0
  397. package/node_modules/@codingns/session-sync-core/dist/runtime/types.js.map +1 -0
  398. package/node_modules/@codingns/session-sync-core/dist/services.d.ts +26 -0
  399. package/node_modules/@codingns/session-sync-core/dist/services.js +85 -0
  400. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -0
  401. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +159 -0
  402. package/node_modules/@codingns/session-sync-core/dist/types.js +2 -0
  403. package/node_modules/@codingns/session-sync-core/dist/types.js.map +1 -0
  404. package/node_modules/@codingns/session-sync-core/package.json +25 -0
  405. package/package.json +34 -0
@@ -0,0 +1,1365 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { basename, dirname, join } from "node:path";
3
+ import { existsSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
4
+ import crypto from "node:crypto";
5
+ import { appendJsonLine, createRawRef, encodeCursor, ensureDirectory, extractTextBlocks, ensureText, messageIdFromRawRef, nextTimestamp, normalizeWorkspacePath, readFirstNonEmptyLine, readJsonLines, readTrailingJsonLines, safeDate, sliceHistory, stringifyStructuredValue, walkJsonlFiles } from "./utils.js";
6
+ const CODEX_SESSION_TITLE_MAX_LENGTH = 48;
7
+ const HISTORY_CACHE_LIMIT = 6;
8
+ const SESSION_SUMMARY_CACHE_LIMIT = 512;
9
+ const RECENT_HISTORY_INITIAL_BYTES = 256 * 1024;
10
+ const RECENT_HISTORY_MAX_BYTES = 4 * 1024 * 1024;
11
+ const RECENT_HISTORY_BUFFER_MESSAGES = 24;
12
+ const CODEX_CONFIG_CONTEXT_WINDOW_PATTERN = /(?:^|\n)\s*model_context_window\s*=\s*(\d+)\s*(?:\n|$)/i;
13
+ const KNOWN_CODEX_CONTEXT_WINDOWS = new Map([
14
+ ["gpt-5.3-codex", 400_000],
15
+ ["codex-mini-latest", 200_000]
16
+ ]);
17
+ export class CodexAdapter {
18
+ options;
19
+ providerId = "codex";
20
+ historyCache = new Map();
21
+ sessionSummaryCache = new Map();
22
+ threadMetadataIndexCache = null;
23
+ constructor(options) {
24
+ this.options = options;
25
+ }
26
+ async detectSessions(workspacePath, options) {
27
+ const targetPath = normalizeWorkspacePath(workspacePath);
28
+ const files = this.listSessionFiles();
29
+ const knownSessions = (options?.knownSessions ?? []).filter((session) => session.provider === this.providerId);
30
+ const knownByRawStoreRef = new Map(knownSessions.map((session) => [session.rawStoreRef, session]));
31
+ const knownByProviderSessionId = new Map(knownSessions.map((session) => [session.providerSessionId, session]));
32
+ const sessionsByProviderSessionId = new Map();
33
+ const retainedSummaries = [];
34
+ const pendingFiles = [];
35
+ for (const filePath of files) {
36
+ const stats = statSync(filePath);
37
+ const cachedSummary = this.sessionSummaryCache.get(filePath);
38
+ const fileSessionId = basename(filePath, ".jsonl");
39
+ const sessionIdentity = this.readSessionIdentity(filePath, fileSessionId);
40
+ if (cachedSummary
41
+ && cachedSummary.mtimeMs === stats.mtimeMs
42
+ && cachedSummary.size === stats.size) {
43
+ this.touchSessionSummaryCache(filePath, cachedSummary);
44
+ if (cachedSummary.summary
45
+ && hasUsableCodexTitle(cachedSummary.summary.title)
46
+ && normalizeWorkspacePath(cachedSummary.summary.workspacePath) === targetPath) {
47
+ retainedSummaries.push({
48
+ filePath,
49
+ stats,
50
+ sessionIdentity,
51
+ summary: cachedSummary.summary
52
+ });
53
+ continue;
54
+ }
55
+ if (cachedSummary.workspacePath
56
+ && normalizeWorkspacePath(cachedSummary.workspacePath) !== targetPath) {
57
+ continue;
58
+ }
59
+ }
60
+ const knownByPath = knownByRawStoreRef.get(filePath);
61
+ if (knownByPath
62
+ && knownByPath.sourceMtimeMs === stats.mtimeMs
63
+ && knownByPath.sourceSizeBytes === stats.size
64
+ && hasUsableCodexTitle(knownByPath.title)) {
65
+ if (normalizeWorkspacePath(knownByPath.workspacePath) === targetPath) {
66
+ retainedSummaries.push({
67
+ filePath,
68
+ stats,
69
+ sessionIdentity,
70
+ summary: knownByPath
71
+ });
72
+ continue;
73
+ }
74
+ this.touchSessionSummaryCache(filePath, {
75
+ filePath,
76
+ mtimeMs: stats.mtimeMs,
77
+ size: stats.size,
78
+ workspacePath: knownByPath.workspacePath,
79
+ summary: null
80
+ });
81
+ continue;
82
+ }
83
+ if (sessionIdentity?.cwd
84
+ && normalizeWorkspacePath(sessionIdentity.cwd) !== targetPath) {
85
+ this.touchSessionSummaryCache(filePath, {
86
+ filePath,
87
+ mtimeMs: stats.mtimeMs,
88
+ size: stats.size,
89
+ workspacePath: sessionIdentity.cwd,
90
+ summary: null
91
+ });
92
+ continue;
93
+ }
94
+ pendingFiles.push({
95
+ filePath,
96
+ fileSessionId,
97
+ stats: {
98
+ mtimeMs: stats.mtimeMs,
99
+ size: stats.size
100
+ },
101
+ sessionIdentity
102
+ });
103
+ }
104
+ if (pendingFiles.length === 0 && retainedSummaries.length === 0) {
105
+ return [...sessionsByProviderSessionId.values()].sort((left, right) => (left.lastMessageAt ?? "").localeCompare(right.lastMessageAt ?? ""));
106
+ }
107
+ const threadMetadataIndex = this.readThreadMetadataIndex();
108
+ const pendingThreadIds = new Set([...pendingFiles, ...retainedSummaries]
109
+ .map((entry) => entry.sessionIdentity?.threadId ?? null)
110
+ .filter((value) => value !== null));
111
+ const spawnedAgentRelationIndex = this.readSpawnedAgentRelationIndex([...pendingFiles, ...retainedSummaries].map((entry) => entry.filePath), targetPath, threadMetadataIndex, pendingThreadIds);
112
+ for (const entry of retainedSummaries) {
113
+ const currentThreadId = entry.sessionIdentity?.threadId ?? entry.summary.providerSessionId;
114
+ const currentThreadMetadata = threadMetadataIndex.get(currentThreadId) ?? null;
115
+ const currentSpawnRelation = spawnedAgentRelationIndex.get(currentThreadId) ?? null;
116
+ const summary = this.hydrateSessionSummary({
117
+ ...entry.summary,
118
+ workspacePath: entry.sessionIdentity?.cwd || entry.summary.workspacePath
119
+ }, entry.filePath, entry.stats, currentThreadMetadata, currentSpawnRelation);
120
+ this.touchSessionSummaryCache(entry.filePath, {
121
+ filePath: entry.filePath,
122
+ mtimeMs: entry.stats.mtimeMs,
123
+ size: entry.stats.size,
124
+ workspacePath: summary.workspacePath,
125
+ summary
126
+ });
127
+ sessionsByProviderSessionId.set(summary.providerSessionId, summary);
128
+ }
129
+ for (const entry of pendingFiles) {
130
+ const { filePath, fileSessionId, stats, sessionIdentity } = entry;
131
+ const records = readJsonLines(filePath);
132
+ const meta = records.find((record) => record.data.type === "session_meta")?.data;
133
+ const metaPayload = (meta?.payload ?? {});
134
+ if (shouldIgnoreCodingNsDraftSession(metaPayload)) {
135
+ this.touchSessionSummaryCache(filePath, {
136
+ filePath,
137
+ mtimeMs: stats.mtimeMs,
138
+ size: stats.size,
139
+ workspacePath: null,
140
+ summary: null
141
+ });
142
+ continue;
143
+ }
144
+ const cwd = ensureText(metaPayload.cwd);
145
+ const cachedWorkspacePath = cwd || null;
146
+ const sessionWorkspacePath = cwd || workspacePath;
147
+ if (normalizeWorkspacePath(cwd) !== targetPath) {
148
+ this.touchSessionSummaryCache(filePath, {
149
+ filePath,
150
+ mtimeMs: stats.mtimeMs,
151
+ size: stats.size,
152
+ workspacePath: cachedWorkspacePath,
153
+ summary: null
154
+ });
155
+ continue;
156
+ }
157
+ const codexSessionId = this.resolveCodexSessionId(metaPayload, fileSessionId);
158
+ const currentThreadMetadata = threadMetadataIndex.get(codexSessionId) ??
159
+ (sessionIdentity ? threadMetadataIndex.get(sessionIdentity.threadId) : null);
160
+ const currentSpawnRelation = spawnedAgentRelationIndex.get(codexSessionId) ??
161
+ (sessionIdentity ? spawnedAgentRelationIndex.get(sessionIdentity.threadId) : null);
162
+ const knownBySessionId = knownByProviderSessionId.get(codexSessionId);
163
+ if (knownBySessionId
164
+ && knownBySessionId.sourceMtimeMs === stats.mtimeMs
165
+ && knownBySessionId.sourceSizeBytes === stats.size
166
+ && hasUsableCodexTitle(knownBySessionId.title)) {
167
+ const summary = this.hydrateSessionSummary({
168
+ ...knownBySessionId,
169
+ workspacePath: sessionWorkspacePath
170
+ }, filePath, stats, currentThreadMetadata, currentSpawnRelation);
171
+ this.touchSessionSummaryCache(filePath, {
172
+ filePath,
173
+ mtimeMs: stats.mtimeMs,
174
+ size: stats.size,
175
+ workspacePath: sessionWorkspacePath,
176
+ summary
177
+ });
178
+ sessionsByProviderSessionId.set(codexSessionId, summary);
179
+ continue;
180
+ }
181
+ const messages = this.parseMessagesFromEntries(filePath, records, codexSessionId);
182
+ const title = this.resolveIndexedTitle(threadMetadataIndex, codexSessionId) ??
183
+ resolveCodexFallbackTitle(messages) ??
184
+ fileSessionId;
185
+ const lastMessageAt = messages.at(-1)?.timestamp ?? (ensureText(metaPayload.timestamp) || null);
186
+ const summary = this.hydrateSessionSummary({
187
+ provider: this.providerId,
188
+ providerSessionId: codexSessionId,
189
+ title,
190
+ workspacePath: sessionWorkspacePath,
191
+ rawStoreRef: filePath,
192
+ lastMessageAt,
193
+ messageCount: messages.length,
194
+ isArchived: false
195
+ }, filePath, stats, currentThreadMetadata, currentSpawnRelation);
196
+ sessionsByProviderSessionId.set(codexSessionId, summary);
197
+ this.touchSessionSummaryCache(filePath, {
198
+ filePath,
199
+ mtimeMs: stats.mtimeMs,
200
+ size: stats.size,
201
+ workspacePath: sessionWorkspacePath,
202
+ summary
203
+ });
204
+ }
205
+ return [...sessionsByProviderSessionId.values()].sort((left, right) => (left.lastMessageAt ?? "").localeCompare(right.lastMessageAt ?? ""));
206
+ }
207
+ async readSessionHistory(providerSessionId, rawStoreRef, cursor, limit, direction = "forward") {
208
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
209
+ const messages = this.getParsedMessages(resolvedStoreRef, providerSessionId);
210
+ return sliceHistory(messages, cursor, limit, direction);
211
+ }
212
+ async readRecentSessionHistory(providerSessionId, rawStoreRef, totalMessageCount, limit) {
213
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
214
+ const stats = statSync(resolvedStoreRef);
215
+ const cached = this.historyCache.get(resolvedStoreRef);
216
+ if (cached
217
+ && cached.providerSessionId === providerSessionId
218
+ && cached.mtimeMs === stats.mtimeMs
219
+ && cached.size === stats.size) {
220
+ this.touchHistoryCache(resolvedStoreRef, cached);
221
+ return sliceHistory(cached.messages, null, limit, "backward");
222
+ }
223
+ const safeLimit = Math.max(1, Math.min(Math.trunc(limit), 100));
224
+ let maxBytes = Math.min(RECENT_HISTORY_INITIAL_BYTES, stats.size);
225
+ while (maxBytes > 0) {
226
+ const lines = readTrailingJsonLines(resolvedStoreRef, maxBytes);
227
+ if (lines.length > 0) {
228
+ const messages = this.parseMessagesFromEntries(resolvedStoreRef, lines, providerSessionId);
229
+ if (messages.length > 0
230
+ && (messages.length >= Math.min(totalMessageCount, safeLimit + RECENT_HISTORY_BUFFER_MESSAGES)
231
+ || maxBytes >= stats.size)) {
232
+ return buildRecentHistoryPage(messages, totalMessageCount, safeLimit);
233
+ }
234
+ }
235
+ if (maxBytes >= stats.size || maxBytes >= RECENT_HISTORY_MAX_BYTES) {
236
+ break;
237
+ }
238
+ maxBytes = Math.min(stats.size, maxBytes * 2, RECENT_HISTORY_MAX_BYTES);
239
+ }
240
+ return null;
241
+ }
242
+ subscribeSession(providerSessionId, rawStoreRef, cursor, limit, onEvent) {
243
+ let currentCursor = cursor;
244
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
245
+ let lastMtime = statSync(resolvedStoreRef).mtimeMs;
246
+ const timer = setInterval(async () => {
247
+ const nextStat = statSync(resolvedStoreRef);
248
+ if (nextStat.mtimeMs <= lastMtime) {
249
+ return;
250
+ }
251
+ lastMtime = nextStat.mtimeMs;
252
+ const page = await this.readSessionHistory(providerSessionId, rawStoreRef, currentCursor, limit);
253
+ if (page.messages.length === 0) {
254
+ return;
255
+ }
256
+ currentCursor = page.cursor;
257
+ await onEvent({
258
+ messages: page.messages,
259
+ cursor: page.cursor
260
+ });
261
+ }, 300);
262
+ return {
263
+ close() {
264
+ clearInterval(timer);
265
+ }
266
+ };
267
+ }
268
+ async resumeSession(providerSessionId, rawStoreRef) {
269
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
270
+ statSync(resolvedStoreRef);
271
+ return {
272
+ provider: this.providerId,
273
+ providerSessionId,
274
+ resumedAt: nextTimestamp(),
275
+ rawStoreRef: resolvedStoreRef
276
+ };
277
+ }
278
+ async startSession(workspacePath, options) {
279
+ const now = new Date();
280
+ const sessionId = `rollout-${now.toISOString().replaceAll(":", "-")}-${crypto.randomUUID()}`;
281
+ const folder = join(this.options.homeDir, "sessions", `${now.getUTCFullYear()}`, `${String(now.getUTCMonth() + 1).padStart(2, "0")}`, `${String(now.getUTCDate()).padStart(2, "0")}`);
282
+ ensureDirectory(folder);
283
+ const filePath = join(folder, `${sessionId}.jsonl`);
284
+ const nowIso = nextTimestamp();
285
+ appendJsonLine(filePath, {
286
+ timestamp: nowIso,
287
+ type: "session_meta",
288
+ payload: {
289
+ id: sessionId,
290
+ timestamp: nowIso,
291
+ cwd: workspacePath,
292
+ originator: "CodingNS Host",
293
+ source: "codingns"
294
+ }
295
+ });
296
+ if (options.initialPrompt) {
297
+ appendJsonLine(filePath, {
298
+ timestamp: nextTimestamp(),
299
+ type: "event_msg",
300
+ payload: {
301
+ type: "user_message",
302
+ message: options.initialPrompt
303
+ }
304
+ });
305
+ }
306
+ return {
307
+ session: {
308
+ provider: this.providerId,
309
+ providerSessionId: sessionId,
310
+ title: options.initialPrompt?.slice(0, CODEX_SESSION_TITLE_MAX_LENGTH) || "New Codex session",
311
+ workspacePath,
312
+ rawStoreRef: filePath,
313
+ isArchived: false,
314
+ lastMessageAt: nextTimestamp(),
315
+ messageCount: options.initialPrompt ? 1 : 0
316
+ },
317
+ initialCursor: encodeCursor(options.initialPrompt ? 1 : 0)
318
+ };
319
+ }
320
+ async sendMessage(providerSessionId, rawStoreRef, content, clientRequestId) {
321
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
322
+ const lineNumber = readJsonLines(resolvedStoreRef).length + 1;
323
+ const acceptedAt = nextTimestamp();
324
+ appendJsonLine(resolvedStoreRef, {
325
+ timestamp: acceptedAt,
326
+ type: "event_msg",
327
+ payload: {
328
+ type: "user_message",
329
+ message: content,
330
+ clientRequestId
331
+ }
332
+ });
333
+ const rawRef = createRawRef(this.providerId, resolvedStoreRef, lineNumber);
334
+ this.historyCache.delete(resolvedStoreRef);
335
+ return {
336
+ acceptedAt,
337
+ clientRequestId,
338
+ message: {
339
+ messageId: messageIdFromRawRef(rawRef),
340
+ provider: this.providerId,
341
+ providerSessionId,
342
+ role: "user",
343
+ kind: "text",
344
+ content,
345
+ toolCall: null,
346
+ timestamp: acceptedAt,
347
+ sequence: this.parseMessages(rawStoreRef, readJsonLines(resolvedStoreRef), providerSessionId).length,
348
+ rawRef
349
+ }
350
+ };
351
+ }
352
+ async readSessionTitle(providerSessionId, rawStoreRef) {
353
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
354
+ const records = readJsonLines(resolvedStoreRef);
355
+ const fileSessionId = basename(resolvedStoreRef, ".jsonl");
356
+ const meta = records.find((record) => record.data.type === "session_meta")?.data;
357
+ const metaPayload = (meta?.payload ?? {});
358
+ const sessionIdentity = this.readSessionIdentity(resolvedStoreRef, fileSessionId);
359
+ const codexSessionId = this.resolveCodexSessionId(metaPayload, providerSessionId || fileSessionId);
360
+ const threadMetadataIndex = this.readThreadMetadataIndex();
361
+ const messages = this.parseMessagesFromEntries(resolvedStoreRef, records, codexSessionId);
362
+ return (this.resolveIndexedTitle(threadMetadataIndex, codexSessionId) ??
363
+ (sessionIdentity
364
+ ? this.resolveIndexedTitle(threadMetadataIndex, sessionIdentity.threadId)
365
+ : null) ??
366
+ resolveCodexFallbackTitle(messages) ??
367
+ fileSessionId);
368
+ }
369
+ async renameSessionTitle(providerSessionId, rawStoreRef, title) {
370
+ const nextTitle = title.trim();
371
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
372
+ const indexPath = join(this.options.homeDir, "session_index.jsonl");
373
+ const stateDbPath = findLatestCodexStateDatabase(this.options.homeDir);
374
+ statSync(resolvedStoreRef);
375
+ ensureDirectory(this.options.homeDir);
376
+ appendJsonLine(indexPath, {
377
+ id: providerSessionId,
378
+ thread_name: nextTitle
379
+ });
380
+ if (stateDbPath) {
381
+ let db = null;
382
+ try {
383
+ db = new DatabaseSync(stateDbPath, { open: true });
384
+ db.prepare("UPDATE threads SET title = ? WHERE id = ?").run(nextTitle, providerSessionId);
385
+ }
386
+ finally {
387
+ db?.close();
388
+ }
389
+ }
390
+ this.sessionSummaryCache.delete(resolvedStoreRef);
391
+ return nextTitle;
392
+ }
393
+ async updateSessionArchiveState(providerSessionId, rawStoreRef, isArchived) {
394
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
395
+ const currentFileName = basename(resolvedStoreRef) || `${providerSessionId}.jsonl`;
396
+ const nextStoreRef = isArchived
397
+ ? join(this.options.homeDir, "archived_sessions", currentFileName)
398
+ : buildCodexActiveSessionPath(this.options.homeDir, currentFileName);
399
+ const stateDbPath = findLatestCodexStateDatabase(this.options.homeDir);
400
+ statSync(resolvedStoreRef);
401
+ if (resolvedStoreRef !== nextStoreRef) {
402
+ ensureDirectory(dirname(nextStoreRef));
403
+ renameSync(resolvedStoreRef, nextStoreRef);
404
+ }
405
+ if (stateDbPath) {
406
+ let db = null;
407
+ try {
408
+ db = new DatabaseSync(stateDbPath, { open: true });
409
+ db.prepare(`UPDATE threads
410
+ SET archived = ?,
411
+ archived_at = ?,
412
+ rollout_path = ?
413
+ WHERE id = ?`).run(isArchived ? 1 : 0, isArchived ? Math.floor(Date.now() / 1000) : null, nextStoreRef, providerSessionId);
414
+ }
415
+ finally {
416
+ db?.close();
417
+ }
418
+ }
419
+ this.sessionSummaryCache.delete(resolvedStoreRef);
420
+ this.sessionSummaryCache.delete(nextStoreRef);
421
+ return {
422
+ rawStoreRef: nextStoreRef,
423
+ isArchived
424
+ };
425
+ }
426
+ getProviderCapabilities() {
427
+ return {
428
+ provider: this.providerId,
429
+ canStartSession: true,
430
+ canResumeSession: true,
431
+ canSendMessage: true,
432
+ inRunInputMode: "none",
433
+ supportsSubagents: true,
434
+ supportsInterrupt: true,
435
+ supportsStructuredToolCalls: true,
436
+ supportsTokenUsage: true,
437
+ supportsAttachments: true,
438
+ supportsPermissionPrompt: true,
439
+ supportsCheckpoint: false,
440
+ limitations: [
441
+ "Codex 产品原生支持将指导加入队列,但当前 SDK 0.116.0 仍未向宿主暴露运行中 queue/steer 提交入口。",
442
+ "当前实现只维护原生会话文件,不负责直接驱动 Codex CLI 进程执行。"
443
+ ]
444
+ };
445
+ }
446
+ async getSessionCapabilities() {
447
+ return this.getProviderCapabilities();
448
+ }
449
+ async readContextUsage(providerSessionId, rawStoreRef) {
450
+ const resolvedStoreRef = this.resolveSessionFilePath(rawStoreRef, providerSessionId);
451
+ const records = readJsonLines(resolvedStoreRef).map((record) => record.data);
452
+ for (let index = records.length - 1; index >= 0; index -= 1) {
453
+ const record = records[index];
454
+ if (ensureText(record.type).trim() !== "event_msg") {
455
+ continue;
456
+ }
457
+ const payload = (record.payload ?? {});
458
+ if (ensureText(payload.type).trim() !== "token_count") {
459
+ continue;
460
+ }
461
+ const info = (payload.info ?? {});
462
+ const lastUsage = (info.last_token_usage ?? {});
463
+ const uncachedInputTokens = readNonNegativeInteger(lastUsage.input_tokens);
464
+ const cachedInputTokens = readNonNegativeInteger(lastUsage.cached_input_tokens);
465
+ if (uncachedInputTokens === null && cachedInputTokens === null) {
466
+ continue;
467
+ }
468
+ const promptTokens = uncachedInputTokens ?? 0;
469
+ const modelId = ensureText(info.model ?? info.model_id).trim() || null;
470
+ const runtimeContextWindow = readNonNegativeInteger(info.model_context_window);
471
+ const contextWindow = runtimeContextWindow
472
+ ?? resolveCodexKnownContextWindow(modelId)
473
+ ?? readCodexConfigContextWindow(this.options.homeDir);
474
+ if (contextWindow === null || contextWindow <= 0) {
475
+ return null;
476
+ }
477
+ return {
478
+ provider: this.providerId,
479
+ promptTokens,
480
+ uncachedInputTokens: uncachedInputTokens ?? 0,
481
+ cachedInputTokens: cachedInputTokens ?? 0,
482
+ contextWindow,
483
+ usageRatio: clampUsageRatio(promptTokens, contextWindow),
484
+ source: "provider-log",
485
+ contextWindowSource: runtimeContextWindow !== null
486
+ ? "provider-log"
487
+ : resolveCodexKnownContextWindow(modelId) !== null
488
+ ? "model-map"
489
+ : "provider-config",
490
+ modelId,
491
+ capturedAt: safeDate(record.timestamp, "").trim() || null,
492
+ isEstimated: runtimeContextWindow === null
493
+ };
494
+ }
495
+ return null;
496
+ }
497
+ readThreadMetadataIndex() {
498
+ const indexPath = join(this.options.homeDir, "session_index.jsonl");
499
+ const indexPathMtimeMs = existsSync(indexPath) ? statSync(indexPath).mtimeMs : null;
500
+ const stateDbPath = findLatestCodexStateDatabase(this.options.homeDir);
501
+ const stateDbMtimeMs = stateDbPath && existsSync(stateDbPath) ? statSync(stateDbPath).mtimeMs : null;
502
+ const cached = this.threadMetadataIndexCache;
503
+ if (cached
504
+ && cached.indexPathMtimeMs === indexPathMtimeMs
505
+ && cached.stateDbPath === stateDbPath
506
+ && cached.stateDbMtimeMs === stateDbMtimeMs) {
507
+ return cached.index;
508
+ }
509
+ const index = new Map();
510
+ if (existsSync(indexPath)) {
511
+ const lines = readFileSync(indexPath, "utf8")
512
+ .split(/\r?\n/)
513
+ .filter((line) => line.trim().length > 0);
514
+ // 这里容忍单行脏数据,避免某一条坏记录把整个会话列表拖死。
515
+ for (const line of lines) {
516
+ try {
517
+ const record = JSON.parse(line);
518
+ const id = ensureText(record.id).trim();
519
+ if (id.length === 0) {
520
+ continue;
521
+ }
522
+ index.set(id, {
523
+ title: normalizeCodexIndexedTitle(ensureText(record.thread_name)) || null,
524
+ cwd: null,
525
+ createdAtMs: null,
526
+ firstUserMessage: null,
527
+ agentNickname: null,
528
+ agentRole: null,
529
+ isArchived: null
530
+ });
531
+ }
532
+ catch {
533
+ continue;
534
+ }
535
+ }
536
+ }
537
+ if (!stateDbPath) {
538
+ this.threadMetadataIndexCache = {
539
+ indexPathMtimeMs,
540
+ stateDbPath: null,
541
+ stateDbMtimeMs: null,
542
+ index
543
+ };
544
+ return index;
545
+ }
546
+ let db = null;
547
+ try {
548
+ db = new DatabaseSync(stateDbPath, { open: true, readOnly: true });
549
+ const rows = db.prepare(`SELECT
550
+ id,
551
+ title,
552
+ cwd,
553
+ created_at,
554
+ archived,
555
+ first_user_message,
556
+ agent_nickname,
557
+ agent_role,
558
+ rollout_path
559
+ FROM threads`).all();
560
+ for (const row of rows) {
561
+ const id = ensureText(row.id).trim();
562
+ if (id.length === 0) {
563
+ continue;
564
+ }
565
+ const current = index.get(id);
566
+ const dbTitle = normalizeCodexIndexedTitle(ensureText(row.title)) || null;
567
+ const createdAtSeconds = typeof row.created_at === "number"
568
+ ? row.created_at
569
+ : Number.parseInt(ensureText(row.created_at), 10);
570
+ index.set(id, {
571
+ title: current?.title ?? dbTitle,
572
+ cwd: ensureText(row.cwd).trim() || (current?.cwd ?? null),
573
+ createdAtMs: Number.isFinite(createdAtSeconds) ? createdAtSeconds * 1000 : null,
574
+ firstUserMessage: ensureText(row.first_user_message).trim() || (current?.firstUserMessage ?? null),
575
+ agentNickname: ensureText(row.agent_nickname).trim() || (current?.agentNickname ?? null),
576
+ agentRole: ensureText(row.agent_role).trim() || (current?.agentRole ?? null),
577
+ isArchived: typeof row.archived === "number"
578
+ ? row.archived === 1
579
+ : ensureText(row.rollout_path).includes("archived_sessions")
580
+ ? true
581
+ : (current?.isArchived ?? null)
582
+ });
583
+ }
584
+ }
585
+ catch {
586
+ this.threadMetadataIndexCache = {
587
+ indexPathMtimeMs,
588
+ stateDbPath,
589
+ stateDbMtimeMs,
590
+ index
591
+ };
592
+ return index;
593
+ }
594
+ finally {
595
+ db?.close();
596
+ }
597
+ this.threadMetadataIndexCache = {
598
+ indexPathMtimeMs,
599
+ stateDbPath,
600
+ stateDbMtimeMs,
601
+ index
602
+ };
603
+ return index;
604
+ }
605
+ listSessionFiles() {
606
+ const activeFiles = walkJsonlFiles(join(this.options.homeDir, "sessions"));
607
+ const archivedFiles = walkJsonlFiles(join(this.options.homeDir, "archived_sessions"));
608
+ return [...activeFiles, ...archivedFiles];
609
+ }
610
+ resolveSessionFilePath(rawStoreRef, providerSessionId) {
611
+ if (existsSync(rawStoreRef)) {
612
+ return rawStoreRef;
613
+ }
614
+ const fileName = basename(rawStoreRef) || `${providerSessionId}.jsonl`;
615
+ const match = fileName.match(/^rollout-(\d{4})-(\d{2})-(\d{2})T.+\.jsonl$/);
616
+ const candidates = [
617
+ join(this.options.homeDir, "archived_sessions", fileName),
618
+ match
619
+ ? join(this.options.homeDir, "sessions", match[1], match[2], match[3], fileName)
620
+ : null
621
+ ].filter((value) => value !== null);
622
+ const matchedPath = candidates.find((candidate) => existsSync(candidate));
623
+ if (matchedPath) {
624
+ return matchedPath;
625
+ }
626
+ const matchedByThreadId = this.findSessionFileByThreadId(providerSessionId);
627
+ if (matchedByThreadId) {
628
+ return matchedByThreadId;
629
+ }
630
+ return rawStoreRef;
631
+ }
632
+ findSessionFileByThreadId(providerSessionId) {
633
+ for (const filePath of this.listSessionFiles()) {
634
+ const threadId = this.readThreadIdFromRawStore(filePath);
635
+ if (threadId === providerSessionId) {
636
+ return filePath;
637
+ }
638
+ }
639
+ return null;
640
+ }
641
+ readThreadIdFromRawStore(filePath) {
642
+ if (!existsSync(filePath)) {
643
+ return null;
644
+ }
645
+ const firstLine = readFirstNonEmptyLine(filePath);
646
+ if (!firstLine) {
647
+ return null;
648
+ }
649
+ try {
650
+ const record = JSON.parse(firstLine);
651
+ if (ensureText(record.type).trim() !== "session_meta") {
652
+ return null;
653
+ }
654
+ const threadId = ensureText(record.payload?.id).trim();
655
+ return threadId.length > 0 ? threadId : null;
656
+ }
657
+ catch {
658
+ return null;
659
+ }
660
+ }
661
+ getParsedMessages(filePath, providerSessionId) {
662
+ const stats = statSync(filePath);
663
+ const cached = this.historyCache.get(filePath);
664
+ if (cached
665
+ && cached.providerSessionId === providerSessionId
666
+ && cached.mtimeMs === stats.mtimeMs
667
+ && cached.size === stats.size) {
668
+ this.touchHistoryCache(filePath, cached);
669
+ return cached.messages;
670
+ }
671
+ const records = readJsonLines(filePath);
672
+ const messages = this.parseMessagesFromEntries(filePath, records, providerSessionId);
673
+ this.touchHistoryCache(filePath, {
674
+ filePath,
675
+ providerSessionId,
676
+ mtimeMs: stats.mtimeMs,
677
+ size: stats.size,
678
+ messages
679
+ });
680
+ return messages;
681
+ }
682
+ touchHistoryCache(filePath, entry) {
683
+ this.historyCache.delete(filePath);
684
+ this.historyCache.set(filePath, entry);
685
+ while (this.historyCache.size > HISTORY_CACHE_LIMIT) {
686
+ const oldestKey = this.historyCache.keys().next().value;
687
+ if (!oldestKey) {
688
+ break;
689
+ }
690
+ this.historyCache.delete(oldestKey);
691
+ }
692
+ }
693
+ touchSessionSummaryCache(filePath, entry) {
694
+ this.sessionSummaryCache.delete(filePath);
695
+ this.sessionSummaryCache.set(filePath, entry);
696
+ while (this.sessionSummaryCache.size > SESSION_SUMMARY_CACHE_LIMIT) {
697
+ const oldestKey = this.sessionSummaryCache.keys().next().value;
698
+ if (!oldestKey) {
699
+ break;
700
+ }
701
+ this.sessionSummaryCache.delete(oldestKey);
702
+ }
703
+ }
704
+ resolveCodexSessionId(metaPayload, providerSessionId) {
705
+ const metaId = ensureText(metaPayload.id).trim();
706
+ const normalizedProviderSessionId = ensureText(providerSessionId).trim();
707
+ if (looksLikeCodexThreadId(metaId)) {
708
+ return metaId;
709
+ }
710
+ const matched = normalizedProviderSessionId.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i);
711
+ if (matched?.[1]) {
712
+ return matched[1];
713
+ }
714
+ return metaId || normalizedProviderSessionId;
715
+ }
716
+ resolveIndexedTitle(index, sessionId) {
717
+ const metadata = index.get(sessionId);
718
+ const indexedTitle = normalizeCodexIndexedTitle(metadata?.title);
719
+ const normalizedFirstUserMessage = normalizeCodexIndexedTitle(metadata?.firstUserMessage);
720
+ if (indexedTitle) {
721
+ // Codex 有时会把第一条用户消息原样回填成 title,这种脏标题仍然按统一长度预算裁掉。
722
+ if (normalizedFirstUserMessage && indexedTitle === normalizedFirstUserMessage) {
723
+ return indexedTitle.slice(0, CODEX_SESSION_TITLE_MAX_LENGTH);
724
+ }
725
+ return indexedTitle;
726
+ }
727
+ return normalizeCodexMessageTitle(metadata?.firstUserMessage);
728
+ }
729
+ readSpawnedAgentRelationIndex(files, targetPath, threadMetadataIndex, candidateThreadIds) {
730
+ const directRelations = new Map();
731
+ const spawnRecords = [];
732
+ for (const filePath of files) {
733
+ const sessionIdentity = this.readSessionIdentity(filePath, basename(filePath, ".jsonl"));
734
+ if (!sessionIdentity) {
735
+ continue;
736
+ }
737
+ if (normalizeWorkspacePath(sessionIdentity.cwd) !== targetPath) {
738
+ continue;
739
+ }
740
+ if (sessionIdentity.parentThreadId) {
741
+ directRelations.set(sessionIdentity.threadId, {
742
+ parentProviderSessionId: sessionIdentity.parentThreadId
743
+ });
744
+ continue;
745
+ }
746
+ const records = readJsonLines(filePath).map((record) => record.data);
747
+ const spawnCallById = new Map();
748
+ for (const record of records) {
749
+ if (record.type !== "response_item") {
750
+ continue;
751
+ }
752
+ const payload = (record.payload ?? {});
753
+ const payloadType = ensureText(payload.type).trim();
754
+ if (payloadType === "function_call" && ensureText(payload.name).trim() === "spawn_agent") {
755
+ const callId = ensureText(payload.call_id).trim();
756
+ const args = parseStructuredJson(ensureText(payload.arguments));
757
+ const message = ensureText(args?.message).trim();
758
+ if (callId.length === 0 || message.length === 0) {
759
+ continue;
760
+ }
761
+ const spawnRecord = {
762
+ parentProviderSessionId: sessionIdentity.threadId,
763
+ workspacePath: sessionIdentity.cwd,
764
+ message,
765
+ timestampMs: toTimestampMs(record.timestamp)
766
+ };
767
+ spawnCallById.set(callId, spawnRecord);
768
+ spawnRecords.push(spawnRecord);
769
+ continue;
770
+ }
771
+ if (payloadType !== "function_call_output") {
772
+ continue;
773
+ }
774
+ const callId = ensureText(payload.call_id).trim();
775
+ const spawnRecord = spawnCallById.get(callId);
776
+ if (!spawnRecord) {
777
+ continue;
778
+ }
779
+ const agentId = parseCodexAgentIdFromToolOutput(ensureText(payload.output));
780
+ if (!agentId) {
781
+ continue;
782
+ }
783
+ directRelations.set(agentId, {
784
+ parentProviderSessionId: spawnRecord.parentProviderSessionId
785
+ });
786
+ }
787
+ }
788
+ const relationCandidates = candidateThreadIds === undefined
789
+ ? [...threadMetadataIndex.entries()]
790
+ : [...new Set(candidateThreadIds)]
791
+ .map((threadId) => [threadId, threadMetadataIndex.get(threadId) ?? null])
792
+ .filter((entry) => entry[1] !== null);
793
+ for (const [threadId, metadata] of relationCandidates) {
794
+ if (directRelations.has(threadId)) {
795
+ continue;
796
+ }
797
+ if (!metadata.agentRole && !metadata.agentNickname) {
798
+ continue;
799
+ }
800
+ const firstUserMessage = metadata.firstUserMessage?.trim();
801
+ const workspacePath = metadata.cwd ? normalizeWorkspacePath(metadata.cwd) : null;
802
+ if (!firstUserMessage || workspacePath !== targetPath) {
803
+ continue;
804
+ }
805
+ const matchedSpawn = pickClosestCodexSpawnRecord(spawnRecords, workspacePath, firstUserMessage, metadata.createdAtMs);
806
+ if (!matchedSpawn) {
807
+ continue;
808
+ }
809
+ directRelations.set(threadId, {
810
+ parentProviderSessionId: matchedSpawn.parentProviderSessionId
811
+ });
812
+ }
813
+ return directRelations;
814
+ }
815
+ readSessionIdentity(filePath, fallbackSessionId) {
816
+ if (!existsSync(filePath)) {
817
+ return null;
818
+ }
819
+ const firstLine = readFirstNonEmptyLine(filePath);
820
+ if (!firstLine) {
821
+ return null;
822
+ }
823
+ try {
824
+ const record = JSON.parse(firstLine);
825
+ if (ensureText(record.type).trim() !== "session_meta") {
826
+ return null;
827
+ }
828
+ const payload = (record.payload ?? {});
829
+ return {
830
+ threadId: this.resolveCodexSessionId(payload, fallbackSessionId),
831
+ cwd: ensureText(payload.cwd).trim(),
832
+ parentThreadId: resolveCodexParentThreadId(payload)
833
+ };
834
+ }
835
+ catch {
836
+ return null;
837
+ }
838
+ }
839
+ hydrateSessionSummary(summary, filePath, stats, metadata, relation) {
840
+ const resolvedRelation = relation ?? null;
841
+ const resolvedMetadata = metadata ?? null;
842
+ const isSubagent = resolvedMetadata || resolvedRelation
843
+ ? isCodexSubagentThread(resolvedMetadata, resolvedRelation)
844
+ : Boolean(summary.isSubagent);
845
+ return {
846
+ ...summary,
847
+ rawStoreRef: filePath,
848
+ isArchived: resolveCodexArchivedState(resolvedMetadata, filePath),
849
+ parentProviderSessionId: resolvedRelation?.parentProviderSessionId ?? summary.parentProviderSessionId ?? null,
850
+ isSubagent,
851
+ subagentLabel: resolvedMetadata !== null
852
+ ? buildCodexSubagentLabel(resolvedMetadata)
853
+ : summary.subagentLabel ?? null,
854
+ sourceMtimeMs: stats.mtimeMs,
855
+ sourceSizeBytes: stats.size
856
+ };
857
+ }
858
+ parseMessages(filePath, records, providerSessionId) {
859
+ return this.parseMessagesFromEntries(filePath, records, providerSessionId);
860
+ }
861
+ parseMessagesFromEntries(filePath, records, providerSessionId) {
862
+ const messages = [];
863
+ const messageIndexesByKey = new Map();
864
+ const toolNameById = new Map();
865
+ let sequence = 0;
866
+ const pushMessage = (source, message) => {
867
+ const dedupeKey = buildCodexMessageDedupeKey(message);
868
+ const candidateIndexes = messageIndexesByKey.get(dedupeKey) ?? [];
869
+ for (let index = candidateIndexes.length - 1; index >= 0; index -= 1) {
870
+ const existingIndex = candidateIndexes[index];
871
+ const existing = messages[existingIndex];
872
+ if (!isEquivalentCodexMessage(existing.message, message)) {
873
+ continue;
874
+ }
875
+ // 同一条逻辑消息如果被 event_msg 和 response_item 同时记录,
876
+ // 优先保留结构更稳定的 response_item,避免时间线重复。
877
+ if (codexMessageSourcePriority(source) > codexMessageSourcePriority(existing.source)) {
878
+ messages[existingIndex] = {
879
+ source,
880
+ dedupeKey,
881
+ message: {
882
+ ...message,
883
+ sequence: existing.message.sequence
884
+ }
885
+ };
886
+ }
887
+ return;
888
+ }
889
+ sequence += 1;
890
+ messageIndexesByKey.set(dedupeKey, [...candidateIndexes, messages.length]);
891
+ messages.push({
892
+ source,
893
+ dedupeKey,
894
+ message: {
895
+ ...message,
896
+ sequence
897
+ }
898
+ });
899
+ };
900
+ records.forEach(({ lineNumber, data: record }) => {
901
+ const rawRef = createRawRef(this.providerId, filePath, lineNumber);
902
+ if (record.type === "event_msg") {
903
+ const payload = (record.payload ?? {});
904
+ const eventType = ensureText(payload.type);
905
+ if (eventType === "user_message") {
906
+ const content = ensureText(payload.message);
907
+ if (content.length > 0) {
908
+ pushMessage("event_msg", {
909
+ messageId: messageIdFromRawRef(rawRef),
910
+ provider: this.providerId,
911
+ providerSessionId,
912
+ role: "user",
913
+ kind: "text",
914
+ content,
915
+ toolCall: null,
916
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
917
+ rawRef
918
+ });
919
+ }
920
+ }
921
+ if (eventType === "agent_message") {
922
+ const content = ensureText(payload.message);
923
+ if (content.length > 0) {
924
+ pushMessage("event_msg", {
925
+ messageId: messageIdFromRawRef(rawRef),
926
+ provider: this.providerId,
927
+ providerSessionId,
928
+ role: "assistant",
929
+ kind: "text",
930
+ content,
931
+ toolCall: null,
932
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
933
+ rawRef
934
+ });
935
+ }
936
+ }
937
+ if (eventType === "agent_reasoning") {
938
+ const content = extractTextBlocks(payload.text ?? payload.message).trim();
939
+ if (content.length > 0) {
940
+ pushMessage("event_msg", {
941
+ messageId: messageIdFromRawRef(rawRef),
942
+ provider: this.providerId,
943
+ providerSessionId,
944
+ role: "assistant",
945
+ kind: "thinking",
946
+ content,
947
+ toolCall: null,
948
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
949
+ rawRef
950
+ });
951
+ }
952
+ }
953
+ }
954
+ if (record.type === "response_item") {
955
+ const payload = (record.payload ?? {});
956
+ const payloadType = ensureText(payload.type);
957
+ if (payloadType === "reasoning") {
958
+ const content = extractTextFromArray(payload.summary);
959
+ if (content.length === 0) {
960
+ return;
961
+ }
962
+ pushMessage("response_item", {
963
+ messageId: messageIdFromRawRef(rawRef),
964
+ provider: this.providerId,
965
+ providerSessionId,
966
+ role: "assistant",
967
+ kind: "thinking",
968
+ content,
969
+ toolCall: null,
970
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
971
+ rawRef
972
+ });
973
+ return;
974
+ }
975
+ if (payloadType === "function_call" || payloadType === "custom_tool_call") {
976
+ const callId = ensureText(payload.call_id).trim() || rawRef;
977
+ const name = ensureText(payload.name).trim() || "tool";
978
+ const inputSource = payloadType === "custom_tool_call" ? payload.input : payload.arguments;
979
+ const input = stringifyStructuredValue(inputSource);
980
+ toolNameById.set(callId, name);
981
+ pushMessage("response_item", {
982
+ messageId: messageIdFromRawRef(rawRef),
983
+ provider: this.providerId,
984
+ providerSessionId,
985
+ role: "tool",
986
+ kind: "tool_call",
987
+ content: input,
988
+ toolCall: {
989
+ callId,
990
+ name,
991
+ input,
992
+ output: null,
993
+ error: null,
994
+ status: "running"
995
+ },
996
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
997
+ rawRef
998
+ });
999
+ return;
1000
+ }
1001
+ if (payloadType === "function_call_output" || payloadType === "custom_tool_call_output") {
1002
+ const callId = ensureText(payload.call_id).trim() || rawRef;
1003
+ const name = toolNameById.get(callId) ?? "tool";
1004
+ const output = extractTextBlocks(payload.output).trim() || stringifyStructuredValue(payload.output);
1005
+ const resultState = resolveToolResultState(payload, output);
1006
+ pushMessage("response_item", {
1007
+ messageId: messageIdFromRawRef(rawRef),
1008
+ provider: this.providerId,
1009
+ providerSessionId,
1010
+ role: "tool",
1011
+ kind: "tool_result",
1012
+ content: output,
1013
+ toolCall: {
1014
+ callId,
1015
+ name,
1016
+ input: "",
1017
+ output: resultState.status === "failed" ? null : output,
1018
+ error: resultState.status === "failed" ? output : null,
1019
+ status: resultState.status
1020
+ },
1021
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
1022
+ rawRef
1023
+ });
1024
+ return;
1025
+ }
1026
+ if (payloadType !== "message") {
1027
+ return;
1028
+ }
1029
+ const role = ensureText(payload.role);
1030
+ const content = extractTextFromArray(payload.content);
1031
+ if (content.length === 0 || (role !== "assistant" && role !== "user")) {
1032
+ return;
1033
+ }
1034
+ pushMessage("response_item", {
1035
+ messageId: messageIdFromRawRef(rawRef),
1036
+ provider: this.providerId,
1037
+ providerSessionId,
1038
+ role,
1039
+ kind: "text",
1040
+ content,
1041
+ toolCall: null,
1042
+ timestamp: safeDate(record.timestamp, nextTimestamp()),
1043
+ rawRef
1044
+ });
1045
+ }
1046
+ });
1047
+ return messages.map((entry) => entry.message);
1048
+ }
1049
+ }
1050
+ function buildRecentHistoryPage(messages, totalMessageCount, limit) {
1051
+ const effectiveTotal = Math.max(totalMessageCount, messages.length);
1052
+ const pageMessages = messages.slice(-Math.min(limit, messages.length)).map((message, index, items) => ({
1053
+ ...message,
1054
+ sequence: effectiveTotal - items.length + index + 1
1055
+ }));
1056
+ const nextCursor = effectiveTotal > pageMessages.length
1057
+ ? encodeCursor(effectiveTotal - pageMessages.length)
1058
+ : null;
1059
+ return {
1060
+ messages: pageMessages,
1061
+ cursor: encodeCursor(effectiveTotal),
1062
+ nextCursor,
1063
+ total: effectiveTotal
1064
+ };
1065
+ }
1066
+ function buildCodexMessageDedupeKey(message) {
1067
+ const comparable = toComparableCodexMessage(message);
1068
+ return JSON.stringify({
1069
+ role: comparable.role,
1070
+ kind: comparable.kind,
1071
+ content: comparable.content,
1072
+ toolCall: comparable.toolCall
1073
+ ? {
1074
+ callId: comparable.toolCall.callId,
1075
+ name: comparable.toolCall.name,
1076
+ input: comparable.toolCall.input,
1077
+ output: comparable.toolCall.output,
1078
+ error: comparable.toolCall.error,
1079
+ status: comparable.toolCall.status
1080
+ }
1081
+ : null
1082
+ });
1083
+ }
1084
+ function resolveCodexFallbackTitle(messages) {
1085
+ const preferredMessage = messages.find((message) => message.role === "user" && !looksLikeCodexRulesMessage(message.content));
1086
+ if (preferredMessage) {
1087
+ return normalizeCodexMessageTitle(preferredMessage.content);
1088
+ }
1089
+ const firstUserMessage = messages.find((message) => message.role === "user");
1090
+ return normalizeCodexMessageTitle(firstUserMessage?.content);
1091
+ }
1092
+ function looksLikeCodexRulesMessage(content) {
1093
+ const normalized = content.trim();
1094
+ const beginsWithRulesHeader = /^#?\s*AGENTS\.md instructions for\b/i.test(normalized);
1095
+ if (beginsWithRulesHeader) {
1096
+ return true;
1097
+ }
1098
+ return /AGENTS\.md instructions for/i.test(normalized)
1099
+ && /<INSTRUCTIONS>/i.test(normalized);
1100
+ }
1101
+ function codexMessageSourcePriority(source) {
1102
+ return source === "response_item" ? 2 : 1;
1103
+ }
1104
+ function isEquivalentCodexMessage(left, right) {
1105
+ const comparableLeft = toComparableCodexMessage(left);
1106
+ const comparableRight = toComparableCodexMessage(right);
1107
+ if (comparableLeft.role !== comparableRight.role ||
1108
+ comparableLeft.kind !== comparableRight.kind ||
1109
+ comparableLeft.content !== comparableRight.content) {
1110
+ return false;
1111
+ }
1112
+ if (JSON.stringify(comparableLeft.toolCall) !== JSON.stringify(comparableRight.toolCall)) {
1113
+ return false;
1114
+ }
1115
+ return areCodexTimestampsNear(left.timestamp, right.timestamp);
1116
+ }
1117
+ function toComparableCodexMessage(message) {
1118
+ return {
1119
+ role: message.role,
1120
+ kind: message.kind,
1121
+ content: normalizeComparableCodexContent(message.kind, message.content),
1122
+ toolCall: message.toolCall
1123
+ ? {
1124
+ callId: message.toolCall.callId,
1125
+ name: message.toolCall.name,
1126
+ input: normalizeComparableCodexLineEndings(message.toolCall.input),
1127
+ output: message.toolCall.output === null
1128
+ ? null
1129
+ : normalizeComparableCodexLineEndings(message.toolCall.output),
1130
+ error: message.toolCall.error === null
1131
+ ? null
1132
+ : normalizeComparableCodexLineEndings(message.toolCall.error),
1133
+ status: message.toolCall.status
1134
+ }
1135
+ : null
1136
+ };
1137
+ }
1138
+ function normalizeComparableCodexContent(kind, content) {
1139
+ const normalized = normalizeComparableCodexLineEndings(content);
1140
+ if (kind === "text" || kind === "thinking") {
1141
+ return normalized.trimEnd();
1142
+ }
1143
+ return normalized;
1144
+ }
1145
+ function normalizeComparableCodexLineEndings(content) {
1146
+ return content.replace(/\r\n/g, "\n");
1147
+ }
1148
+ function areCodexTimestampsNear(left, right) {
1149
+ const leftMs = Date.parse(left);
1150
+ const rightMs = Date.parse(right);
1151
+ if (!Number.isFinite(leftMs) || !Number.isFinite(rightMs)) {
1152
+ return left === right;
1153
+ }
1154
+ return Math.abs(leftMs - rightMs) <= 1000;
1155
+ }
1156
+ function extractTextFromArray(value) {
1157
+ if (!Array.isArray(value)) {
1158
+ return "";
1159
+ }
1160
+ return value
1161
+ .map((item) => extractTextBlocks(item).trim())
1162
+ .filter((item) => item.length > 0)
1163
+ .join("\n");
1164
+ }
1165
+ function resolveToolResultState(payload, output) {
1166
+ const statusText = ensureText(payload.status).trim().toLowerCase();
1167
+ if (statusText === "failed" || statusText === "error") {
1168
+ return { status: "failed" };
1169
+ }
1170
+ if (statusText === "completed" || statusText === "success" || statusText === "succeeded") {
1171
+ return { status: "completed" };
1172
+ }
1173
+ if (typeof payload.success === "boolean") {
1174
+ return {
1175
+ status: payload.success ? "completed" : "failed"
1176
+ };
1177
+ }
1178
+ if (typeof payload.is_error === "boolean") {
1179
+ return {
1180
+ status: payload.is_error ? "failed" : "completed"
1181
+ };
1182
+ }
1183
+ if (typeof payload.exit_code === "number") {
1184
+ return {
1185
+ status: payload.exit_code === 0 ? "completed" : "failed"
1186
+ };
1187
+ }
1188
+ const exitCodeMatch = output.match(/(?:^|\n)Exit code:\s*(-?\d+)/i);
1189
+ if (exitCodeMatch) {
1190
+ return {
1191
+ status: Number(exitCodeMatch[1]) === 0 ? "completed" : "failed"
1192
+ };
1193
+ }
1194
+ if (payload.error != null) {
1195
+ return { status: "failed" };
1196
+ }
1197
+ return { status: "completed" };
1198
+ }
1199
+ function shouldIgnoreCodingNsDraftSession(metaPayload) {
1200
+ const source = ensureText(metaPayload.source).trim().toLowerCase();
1201
+ const sessionId = ensureText(metaPayload.id).trim().toLowerCase();
1202
+ return source === "codingns" && sessionId.startsWith("rollout-");
1203
+ }
1204
+ function looksLikeCodexThreadId(value) {
1205
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
1206
+ }
1207
+ function findLatestCodexStateDatabase(homeDir) {
1208
+ if (!existsSync(homeDir)) {
1209
+ return null;
1210
+ }
1211
+ const candidates = readdirSync(homeDir, { withFileTypes: true })
1212
+ .filter((entry) => entry.isFile() && /^state_\d+\.sqlite$/i.test(entry.name))
1213
+ .map((entry) => {
1214
+ const filePath = join(homeDir, entry.name);
1215
+ return {
1216
+ filePath,
1217
+ mtimeMs: statSync(filePath).mtimeMs
1218
+ };
1219
+ })
1220
+ .sort((left, right) => right.mtimeMs - left.mtimeMs);
1221
+ return candidates[0]?.filePath ?? null;
1222
+ }
1223
+ function parseStructuredJson(value) {
1224
+ const text = value.trim();
1225
+ if (text.length === 0) {
1226
+ return null;
1227
+ }
1228
+ try {
1229
+ const parsed = JSON.parse(text);
1230
+ return parsed && typeof parsed === "object" ? parsed : null;
1231
+ }
1232
+ catch {
1233
+ return null;
1234
+ }
1235
+ }
1236
+ function readNonNegativeInteger(value) {
1237
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
1238
+ return Math.trunc(value);
1239
+ }
1240
+ if (typeof value === "string" && /^\d+$/.test(value.trim())) {
1241
+ return Number.parseInt(value.trim(), 10);
1242
+ }
1243
+ return null;
1244
+ }
1245
+ function clampUsageRatio(promptTokens, contextWindow) {
1246
+ if (contextWindow <= 0) {
1247
+ return 0;
1248
+ }
1249
+ return Math.min(Math.max(promptTokens / contextWindow, 0), 1);
1250
+ }
1251
+ function resolveCodexKnownContextWindow(modelId) {
1252
+ if (!modelId) {
1253
+ return null;
1254
+ }
1255
+ return KNOWN_CODEX_CONTEXT_WINDOWS.get(modelId) ?? null;
1256
+ }
1257
+ function readCodexConfigContextWindow(homeDir) {
1258
+ const configPath = join(homeDir, "config.toml");
1259
+ if (!existsSync(configPath)) {
1260
+ return null;
1261
+ }
1262
+ try {
1263
+ const content = readFileSync(configPath, "utf8");
1264
+ const matched = content.match(CODEX_CONFIG_CONTEXT_WINDOW_PATTERN);
1265
+ if (!matched?.[1]) {
1266
+ return null;
1267
+ }
1268
+ return Number.parseInt(matched[1], 10);
1269
+ }
1270
+ catch {
1271
+ return null;
1272
+ }
1273
+ }
1274
+ function parseCodexAgentIdFromToolOutput(output) {
1275
+ const parsed = parseStructuredJson(output);
1276
+ const agentId = ensureText(parsed?.agent_id ?? parsed?.agentId).trim();
1277
+ if (looksLikeCodexThreadId(agentId)) {
1278
+ return agentId;
1279
+ }
1280
+ const matched = output.match(/"agent(?:_id|Id)"\s*:\s*"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"/i);
1281
+ return matched?.[1] ?? null;
1282
+ }
1283
+ function resolveCodexParentThreadId(payload) {
1284
+ const directParentThreadId = ensureText(payload.forked_from_id).trim();
1285
+ if (directParentThreadId.length > 0) {
1286
+ return directParentThreadId;
1287
+ }
1288
+ const source = typeof payload.source === "object" && payload.source !== null
1289
+ ? payload.source
1290
+ : null;
1291
+ const subagent = typeof source?.subagent === "object" && source.subagent !== null
1292
+ ? source.subagent
1293
+ : null;
1294
+ const threadSpawn = typeof subagent?.thread_spawn === "object" && subagent.thread_spawn !== null
1295
+ ? subagent.thread_spawn
1296
+ : null;
1297
+ const nestedParentThreadId = ensureText(threadSpawn?.parent_thread_id).trim();
1298
+ return nestedParentThreadId.length > 0 ? nestedParentThreadId : null;
1299
+ }
1300
+ function toTimestampMs(value) {
1301
+ const timestampMs = Date.parse(ensureText(value).trim());
1302
+ return Number.isFinite(timestampMs) ? timestampMs : null;
1303
+ }
1304
+ function pickClosestCodexSpawnRecord(spawnRecords, workspacePath, message, createdAtMs) {
1305
+ const matchedRecords = spawnRecords.filter((record) => record.workspacePath !== null &&
1306
+ normalizeWorkspacePath(record.workspacePath) === workspacePath &&
1307
+ record.message === message);
1308
+ if (matchedRecords.length === 0) {
1309
+ return null;
1310
+ }
1311
+ if (createdAtMs === null) {
1312
+ return matchedRecords.at(-1) ?? null;
1313
+ }
1314
+ const closeRecord = matchedRecords
1315
+ .filter((record) => record.timestampMs !== null)
1316
+ .sort((left, right) => Math.abs((left.timestampMs ?? createdAtMs) - createdAtMs) -
1317
+ Math.abs((right.timestampMs ?? createdAtMs) - createdAtMs))
1318
+ .find((record) => Math.abs((record.timestampMs ?? createdAtMs) - createdAtMs) <= 120_000);
1319
+ return closeRecord ?? matchedRecords.at(-1) ?? null;
1320
+ }
1321
+ function isCodexSubagentThread(metadata, relation) {
1322
+ return Boolean(relation?.parentProviderSessionId || metadata?.agentRole || metadata?.agentNickname);
1323
+ }
1324
+ function buildCodexSubagentLabel(metadata) {
1325
+ const agentRole = metadata?.agentRole?.trim() || "";
1326
+ const agentNickname = metadata?.agentNickname?.trim() || "";
1327
+ if (agentRole && agentNickname) {
1328
+ return `${agentRole} · ${agentNickname}`;
1329
+ }
1330
+ return agentNickname || agentRole || null;
1331
+ }
1332
+ function resolveCodexArchivedState(metadata, filePath) {
1333
+ if (isCodexArchivedFilePath(filePath)) {
1334
+ return true;
1335
+ }
1336
+ if (typeof metadata?.isArchived === "boolean") {
1337
+ return metadata.isArchived;
1338
+ }
1339
+ return false;
1340
+ }
1341
+ function isCodexArchivedFilePath(filePath) {
1342
+ return filePath.replaceAll("\\", "/").includes("/archived_sessions/");
1343
+ }
1344
+ function buildCodexActiveSessionPath(homeDir, fileName) {
1345
+ const match = fileName.match(/^rollout-(\d{4})-(\d{2})-(\d{2})T.+\.jsonl$/);
1346
+ if (!match) {
1347
+ return join(homeDir, "sessions", fileName);
1348
+ }
1349
+ return join(homeDir, "sessions", match[1], match[2], match[3], fileName);
1350
+ }
1351
+ function hasUsableCodexTitle(title) {
1352
+ return normalizeCodexIndexedTitle(title) !== null;
1353
+ }
1354
+ function normalizeCodexIndexedTitle(title) {
1355
+ const normalized = ensureText(title).trim();
1356
+ if (normalized.length === 0 || looksLikeCodexRulesMessage(normalized)) {
1357
+ return null;
1358
+ }
1359
+ return normalized;
1360
+ }
1361
+ function normalizeCodexMessageTitle(content) {
1362
+ const normalized = normalizeCodexIndexedTitle(content);
1363
+ return normalized ? normalized.slice(0, CODEX_SESSION_TITLE_MAX_LENGTH) : null;
1364
+ }
1365
+ //# sourceMappingURL=codex.js.map