@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,794 @@
1
+ import { EventEmitter } from "node:events";
2
+ import path from "node:path";
3
+ import { AppError } from "../../shared/errors/app-error.js";
4
+ import { createId } from "../../shared/utils/id.js";
5
+ import { nowIso } from "../../shared/utils/time.js";
6
+ import { resolveWorkspaceCwd } from "./terminal-paths.js";
7
+ import { getDefaultShell, resolveRequestedShell } from "./terminal-shell.js";
8
+ import { captureTmuxPaneContent } from "./runtime/adapters/tmux-runtime-adapter.js";
9
+ import { TerminalLogFileStore } from "./runtime/terminal-log-file-store.js";
10
+ import { TerminalLogSpooler } from "./runtime/terminal-log-spooler.js";
11
+ import { TerminalOutputBuffer } from "./runtime/terminal-output-buffer.js";
12
+ import { TerminalRuntimeManager } from "./runtime/terminal-runtime-manager.js";
13
+ export class TerminalService extends EventEmitter {
14
+ db;
15
+ terminalInstanceRepository;
16
+ terminalRuntimeSessionRepository;
17
+ workspaceService;
18
+ outputBuffer = new TerminalOutputBuffer();
19
+ runtimeManager = new TerminalRuntimeManager();
20
+ lastPersistedActivity = new Map();
21
+ terminalSubscriptionCounts = new Map();
22
+ pendingCloseReasons = new Map();
23
+ pendingDeletedTerminalIds = new Set();
24
+ terminalLogSpooler;
25
+ terminalLogFileRepository;
26
+ terminalLogSegmentRepository;
27
+ terminalLogFileStore;
28
+ isDisposing = false;
29
+ constructor(db, terminalInstanceRepository, terminalRuntimeSessionRepository, workspaceService, _idleTimeoutSeconds, options = {}) {
30
+ super();
31
+ this.db = db;
32
+ this.terminalInstanceRepository = terminalInstanceRepository;
33
+ this.terminalRuntimeSessionRepository = terminalRuntimeSessionRepository;
34
+ this.workspaceService = workspaceService;
35
+ this.terminalLogFileRepository = options.terminalLogFileRepository ?? null;
36
+ this.terminalLogSegmentRepository = options.terminalLogSegmentRepository ?? null;
37
+ this.terminalLogFileStore = options.terminalLogRootDir
38
+ ? new TerminalLogFileStore(options.terminalLogRootDir)
39
+ : null;
40
+ this.terminalLogSpooler =
41
+ options.terminalLogRootDir &&
42
+ options.terminalLogFileRepository &&
43
+ options.terminalLogSegmentRepository
44
+ ? new TerminalLogSpooler({
45
+ logRootDir: options.terminalLogRootDir,
46
+ fileRepository: options.terminalLogFileRepository,
47
+ segmentRepository: options.terminalLogSegmentRepository
48
+ })
49
+ : null;
50
+ this.runtimeManager.on("output", (event) => {
51
+ this.handleRuntimeOutput(event.terminalId, event.content);
52
+ });
53
+ this.runtimeManager.on("exit", (event) => {
54
+ this.handleRuntimeExit(event);
55
+ });
56
+ this.recoverRuntimeStates();
57
+ }
58
+ createTerminal(input) {
59
+ const workspace = this.workspaceService.getWorkspaceOrThrow(input.workspaceId);
60
+ const now = nowIso();
61
+ const shell = resolveRequestedShell(sanitizeShell(input.shell) ?? getDefaultShell());
62
+ const cwd = resolveWorkspaceCwd(workspace.path, input.cwd);
63
+ const runtimeType = resolveRequestedRuntimeType(input.runtimeType);
64
+ const runtimeSessionId = createId();
65
+ const attachTarget = buildAttachTarget(runtimeType, runtimeSessionId);
66
+ const terminal = {
67
+ id: createId(),
68
+ workspaceId: workspace.id,
69
+ name: input.name?.trim() || buildDefaultTerminalName(cwd),
70
+ cwd,
71
+ shell,
72
+ runtimeType,
73
+ runtimeSessionId,
74
+ attachTarget,
75
+ status: "creating",
76
+ processId: null,
77
+ createdByUserId: input.createdByUserId,
78
+ createdAt: now,
79
+ lastActiveAt: now,
80
+ closedAt: null,
81
+ exitCode: null,
82
+ statusDetail: null
83
+ };
84
+ const runtimeSession = {
85
+ id: runtimeSessionId,
86
+ terminalId: terminal.id,
87
+ runtimeType,
88
+ sessionKey: runtimeSessionId,
89
+ attachTarget,
90
+ hostInstanceId: null,
91
+ agentPid: null,
92
+ shellPid: null,
93
+ state: "starting",
94
+ lastHeartbeatAt: null,
95
+ lastCheckedAt: now,
96
+ lastErrorDetail: null,
97
+ createdAt: now,
98
+ updatedAt: now
99
+ };
100
+ const persist = this.db.transaction(() => {
101
+ this.terminalInstanceRepository.create(terminal);
102
+ this.terminalRuntimeSessionRepository.create(runtimeSession);
103
+ });
104
+ persist();
105
+ try {
106
+ const env = buildTerminalEnv(input.env);
107
+ const createdInspection = this.runtimeManager.createPersistentSession(terminal, runtimeSession, env);
108
+ const attachmentProcessId = this.runtimeManager.ensureAttached(terminal, runtimeSession, env);
109
+ const processId = createdInspection.shellPid ?? attachmentProcessId;
110
+ const runningTerminal = {
111
+ ...terminal,
112
+ status: "running",
113
+ processId
114
+ };
115
+ this.terminalInstanceRepository.updateLifecycle({
116
+ id: runningTerminal.id,
117
+ status: runningTerminal.status,
118
+ processId: runningTerminal.processId,
119
+ lastActiveAt: runningTerminal.lastActiveAt,
120
+ closedAt: null,
121
+ exitCode: null,
122
+ statusDetail: null
123
+ });
124
+ this.terminalRuntimeSessionRepository.updateState({
125
+ id: runtimeSession.id,
126
+ shellPid: processId,
127
+ state: "running",
128
+ lastCheckedAt: nowIso(),
129
+ lastErrorDetail: createdInspection.detail,
130
+ updatedAt: nowIso()
131
+ });
132
+ this.emit("status", runningTerminal);
133
+ return runningTerminal;
134
+ }
135
+ catch (error) {
136
+ const failedAt = nowIso();
137
+ this.terminalInstanceRepository.updateLifecycle({
138
+ id: terminal.id,
139
+ status: "error",
140
+ processId: terminal.processId,
141
+ lastActiveAt: failedAt,
142
+ closedAt: failedAt,
143
+ exitCode: null,
144
+ statusDetail: error instanceof Error ? error.message : "PTY 启动失败"
145
+ });
146
+ this.terminalRuntimeSessionRepository.updateState({
147
+ id: runtimeSession.id,
148
+ shellPid: null,
149
+ state: "error",
150
+ lastCheckedAt: failedAt,
151
+ lastErrorDetail: error instanceof Error ? error.message : "PTY 启动失败",
152
+ updatedAt: failedAt
153
+ });
154
+ const failedTerminal = this.getTerminalOrThrow(terminal.id);
155
+ this.emit("status", failedTerminal);
156
+ throw error;
157
+ }
158
+ }
159
+ listTerminals(workspaceId) {
160
+ this.workspaceService.getWorkspaceOrThrow(workspaceId);
161
+ const terminals = this.terminalInstanceRepository.listByWorkspace(workspaceId);
162
+ let hasLifecycleChange = false;
163
+ for (const terminal of terminals) {
164
+ if (this.reconcileTerminalRuntime(terminal)) {
165
+ hasLifecycleChange = true;
166
+ }
167
+ }
168
+ return hasLifecycleChange
169
+ ? this.terminalInstanceRepository.listByWorkspace(workspaceId)
170
+ : terminals;
171
+ }
172
+ getTerminalOrThrow(terminalId) {
173
+ const terminal = this.terminalInstanceRepository.findById(terminalId);
174
+ if (!terminal) {
175
+ throw new AppError({
176
+ statusCode: 404,
177
+ errorCode: "TERMINAL_NOT_FOUND",
178
+ detail: "指定终端不存在"
179
+ });
180
+ }
181
+ return terminal;
182
+ }
183
+ getRuntimeSessionOrThrow(runtimeSessionId) {
184
+ const session = this.terminalRuntimeSessionRepository.findById(runtimeSessionId);
185
+ if (!session) {
186
+ throw new AppError({
187
+ statusCode: 404,
188
+ errorCode: "RUNTIME_SESSION_NOT_FOUND",
189
+ detail: "指定终端运行时会话不存在"
190
+ });
191
+ }
192
+ return session;
193
+ }
194
+ closeTerminal(terminalId, reason = "user_closed") {
195
+ const terminal = this.getTerminalOrThrow(terminalId);
196
+ const session = this.getRuntimeSessionOrThrow(terminal.runtimeSessionId);
197
+ this.pendingCloseReasons.set(terminalId, reason);
198
+ if (terminal.status === "closed" || terminal.status === "error") {
199
+ this.pendingCloseReasons.delete(terminalId);
200
+ return { success: true };
201
+ }
202
+ this.flushTerminalLogs(terminalId);
203
+ const willEmitExit = this.runtimeManager.terminateSession(terminal, session);
204
+ if (!willEmitExit) {
205
+ this.finalizeTerminalClosure(terminal, session, {
206
+ requestedClose: true,
207
+ exitCode: 0,
208
+ sessionAlive: false,
209
+ sessionDetail: null,
210
+ shellPid: null
211
+ });
212
+ }
213
+ return { success: true };
214
+ }
215
+ deleteTerminal(terminalId) {
216
+ const terminal = this.getTerminalOrThrow(terminalId);
217
+ const session = this.getRuntimeSessionOrThrow(terminal.runtimeSessionId);
218
+ this.pendingCloseReasons.delete(terminalId);
219
+ this.lastPersistedActivity.delete(terminalId);
220
+ this.flushTerminalLogs(terminalId);
221
+ this.pendingDeletedTerminalIds.add(terminalId);
222
+ const deleteRecords = this.db.transaction(() => {
223
+ this.terminalRuntimeSessionRepository.deleteByTerminalId(terminalId);
224
+ this.terminalInstanceRepository.delete(terminalId);
225
+ });
226
+ try {
227
+ deleteRecords();
228
+ }
229
+ catch (error) {
230
+ this.pendingDeletedTerminalIds.delete(terminalId);
231
+ throw error;
232
+ }
233
+ let willEmitExit = false;
234
+ try {
235
+ willEmitExit = this.runtimeManager.terminateSession(terminal, session);
236
+ }
237
+ catch (error) {
238
+ this.pendingDeletedTerminalIds.delete(terminalId);
239
+ this.clearTerminalLogs(terminalId);
240
+ console.warn("[terminal-delete-runtime-cleanup-failed]", {
241
+ terminalId,
242
+ runtimeSessionId: session.id,
243
+ runtimeType: session.runtimeType,
244
+ error: error instanceof Error ? error.message : String(error)
245
+ });
246
+ }
247
+ if (!willEmitExit) {
248
+ this.pendingDeletedTerminalIds.delete(terminalId);
249
+ this.clearTerminalLogs(terminalId);
250
+ }
251
+ return { success: true };
252
+ }
253
+ writeInput(terminalId, content) {
254
+ if (!content) {
255
+ throw new AppError({
256
+ statusCode: 400,
257
+ errorCode: "INVALID_INPUT",
258
+ detail: "终端输入不能为空",
259
+ field: "content"
260
+ });
261
+ }
262
+ const terminal = this.ensureTerminalInteractive(terminalId);
263
+ this.runtimeManager.write(terminal.id, content);
264
+ this.touchLastActiveAt(terminalId);
265
+ return { accepted: true };
266
+ }
267
+ resizeTerminal(terminalId, cols, rows) {
268
+ if (!Number.isInteger(cols) || !Number.isInteger(rows) || cols < 20 || rows < 5) {
269
+ throw new AppError({
270
+ statusCode: 400,
271
+ errorCode: "INVALID_TERMINAL_SIZE",
272
+ detail: "终端尺寸不合法",
273
+ field: "cols"
274
+ });
275
+ }
276
+ const terminal = this.ensureTerminalInteractive(terminalId);
277
+ this.runtimeManager.resize(terminal.id, cols, rows);
278
+ this.touchLastActiveAt(terminalId);
279
+ return { accepted: true };
280
+ }
281
+ subscribeTerminal(terminalId, lastCursor, callbacks) {
282
+ const outputListener = (event) => {
283
+ if (event.terminalId !== terminalId) {
284
+ return;
285
+ }
286
+ for (const chunk of event.chunks) {
287
+ void callbacks.onOutput(chunk);
288
+ }
289
+ };
290
+ const statusListener = (nextTerminal) => {
291
+ if (nextTerminal.id !== terminalId) {
292
+ return;
293
+ }
294
+ void callbacks.onStatus(nextTerminal);
295
+ };
296
+ const exitListener = (event) => {
297
+ if (event.terminal.id !== terminalId) {
298
+ return;
299
+ }
300
+ void callbacks.onExit(event);
301
+ };
302
+ this.on("output", outputListener);
303
+ this.on("status", statusListener);
304
+ this.on("exit", exitListener);
305
+ this.retainTerminalSubscription(terminalId);
306
+ try {
307
+ const current = this.ensureTerminalAttachedForSubscription(terminalId);
308
+ const backfill = this.outputBuffer.readSince(terminalId, lastCursor);
309
+ void callbacks.onStatus(current);
310
+ void callbacks.onBackfill(backfill);
311
+ }
312
+ catch (error) {
313
+ this.off("output", outputListener);
314
+ this.off("status", statusListener);
315
+ this.off("exit", exitListener);
316
+ this.releaseTerminalSubscription(terminalId);
317
+ throw error;
318
+ }
319
+ let closed = false;
320
+ return {
321
+ close: () => {
322
+ if (closed) {
323
+ return;
324
+ }
325
+ closed = true;
326
+ this.off("output", outputListener);
327
+ this.off("status", statusListener);
328
+ this.off("exit", exitListener);
329
+ this.releaseTerminalSubscription(terminalId);
330
+ }
331
+ };
332
+ }
333
+ async dispose() {
334
+ this.isDisposing = true;
335
+ this.terminalLogSpooler?.flushAll();
336
+ this.runtimeManager.closeAllAttachments();
337
+ await new Promise((resolve) => setTimeout(resolve, 100));
338
+ }
339
+ readTerminalHistory(terminalId, beforeSeq, limit) {
340
+ const terminal = this.getTerminalOrThrow(terminalId);
341
+ const runtimeSession = terminal.runtimeSessionId
342
+ ? this.terminalRuntimeSessionRepository.findById(terminal.runtimeSessionId)
343
+ : null;
344
+ if (beforeSeq === 1 && runtimeSession?.runtimeType === "tmux") {
345
+ const capturedContent = normalizeTerminalHistoryContent(captureTmuxPaneContent(runtimeSession.sessionKey));
346
+ const capturedLineCount = countTerminalHistoryLines(capturedContent);
347
+ return {
348
+ terminalId,
349
+ content: capturedContent,
350
+ lineCount: capturedLineCount,
351
+ anchorLine: 0,
352
+ replaceContent: true,
353
+ hasMore: false,
354
+ nextBeforeSeq: null
355
+ };
356
+ }
357
+ const historyPage = this.readTerminalHistorySegments(terminalId, beforeSeq, limit);
358
+ const orderedSegments = [...historyPage.segments].reverse();
359
+ const content = normalizeTerminalHistoryContent(orderedSegments.map((segment) => segment.content).join(""));
360
+ const lineCount = countTerminalHistoryLines(content);
361
+ const shouldFallbackToTmuxPane = runtimeSession?.runtimeType === "tmux" &&
362
+ !historyPage.hasMore &&
363
+ historyPage.nextBeforeSeq === 1;
364
+ return {
365
+ terminalId,
366
+ content,
367
+ lineCount,
368
+ anchorLine: lineCount,
369
+ hasMore: shouldFallbackToTmuxPane ? true : historyPage.hasMore,
370
+ nextBeforeSeq: historyPage.nextBeforeSeq
371
+ };
372
+ }
373
+ readTerminalHistorySegments(terminalId, beforeSeq, limit) {
374
+ this.getTerminalOrThrow(terminalId);
375
+ if (!this.terminalLogSegmentRepository || !this.terminalLogFileRepository || !this.terminalLogFileStore) {
376
+ return {
377
+ terminalId,
378
+ segments: [],
379
+ hasMore: false,
380
+ nextBeforeSeq: null
381
+ };
382
+ }
383
+ const terminalLogSegmentRepository = this.terminalLogSegmentRepository;
384
+ const terminalLogFileRepository = this.terminalLogFileRepository;
385
+ const terminalLogFileStore = this.terminalLogFileStore;
386
+ const segments = this.terminalLogSegmentRepository.listBeforeSeq(terminalId, beforeSeq, limit);
387
+ const historySegments = segments.map((segment) => {
388
+ const logFile = terminalLogFileRepository.findById(segment.fileId);
389
+ if (!logFile) {
390
+ throw new AppError({
391
+ statusCode: 409,
392
+ errorCode: "TERMINAL_LOG_INDEX_INVALID",
393
+ detail: "终端日志索引缺少对应文件记录"
394
+ });
395
+ }
396
+ try {
397
+ return {
398
+ id: segment.id,
399
+ fileId: segment.fileId,
400
+ startSeq: segment.startSeq,
401
+ endSeq: segment.endSeq,
402
+ content: terminalLogFileStore.read(logFile.relativePath, segment.startOffset, segment.byteLength),
403
+ byteLength: segment.byteLength,
404
+ createdAt: segment.createdAt
405
+ };
406
+ }
407
+ catch (error) {
408
+ throw new AppError({
409
+ statusCode: 409,
410
+ errorCode: "TERMINAL_LOG_FILE_MISSING",
411
+ detail: error instanceof Error ? error.message : "终端日志文件不存在,无法回放历史"
412
+ });
413
+ }
414
+ });
415
+ const oldestSeq = historySegments.at(-1)?.startSeq ?? null;
416
+ const hasMore = oldestSeq !== null
417
+ ? terminalLogSegmentRepository.listBeforeSeq(terminalId, oldestSeq, 1).length > 0
418
+ : false;
419
+ return {
420
+ terminalId,
421
+ segments: historySegments,
422
+ hasMore,
423
+ nextBeforeSeq: oldestSeq
424
+ };
425
+ }
426
+ handleRuntimeOutput(terminalId, content) {
427
+ if (this.isDisposing) {
428
+ return;
429
+ }
430
+ const chunks = this.outputBuffer.append(terminalId, content);
431
+ if (chunks.length === 0) {
432
+ return;
433
+ }
434
+ this.terminalLogSpooler?.appendChunks(terminalId, chunks);
435
+ this.touchLastActiveAt(terminalId);
436
+ this.emit("output", {
437
+ terminalId,
438
+ chunks
439
+ });
440
+ }
441
+ handleRuntimeExit(event) {
442
+ if (this.isDisposing) {
443
+ return;
444
+ }
445
+ if (this.pendingDeletedTerminalIds.delete(event.terminalId)) {
446
+ this.pendingCloseReasons.delete(event.terminalId);
447
+ this.lastPersistedActivity.delete(event.terminalId);
448
+ this.clearTerminalLogs(event.terminalId);
449
+ return;
450
+ }
451
+ this.flushTerminalLogs(event.terminalId);
452
+ const current = this.getTerminalOrThrow(event.terminalId);
453
+ const session = this.getRuntimeSessionOrThrow(current.runtimeSessionId);
454
+ if (event.sessionAlive && !event.requestedClose) {
455
+ this.markTerminalRunning(current, session, event.shellPid, event.sessionDetail);
456
+ return;
457
+ }
458
+ this.finalizeTerminalClosure(current, session, event);
459
+ }
460
+ touchLastActiveAt(terminalId) {
461
+ if (this.isDisposing) {
462
+ return;
463
+ }
464
+ const now = Date.now();
465
+ const previous = this.lastPersistedActivity.get(terminalId) ?? 0;
466
+ if (now - previous >= 500) {
467
+ this.lastPersistedActivity.set(terminalId, now);
468
+ this.terminalInstanceRepository.touchLastActiveAt(terminalId, nowIso(new Date(now)));
469
+ }
470
+ }
471
+ ensureTerminalInteractive(terminalId) {
472
+ const terminal = this.getTerminalOrThrow(terminalId);
473
+ const session = this.getRuntimeSessionOrThrow(terminal.runtimeSessionId);
474
+ const nextTerminal = this.ensureTerminalRunning(terminal, session, true);
475
+ if (nextTerminal.status !== "running") {
476
+ throw new AppError({
477
+ statusCode: 409,
478
+ errorCode: "TERMINAL_NOT_RUNNING",
479
+ detail: nextTerminal.statusDetail ?? "终端当前不可写入"
480
+ });
481
+ }
482
+ return nextTerminal;
483
+ }
484
+ ensureTerminalAttachedForSubscription(terminalId) {
485
+ const terminal = this.getTerminalOrThrow(terminalId);
486
+ const session = this.getRuntimeSessionOrThrow(terminal.runtimeSessionId);
487
+ return this.ensureTerminalRunning(terminal, session, true);
488
+ }
489
+ ensureTerminalRunning(terminal, session, ensureAttached) {
490
+ if (terminal.status === "closed" || terminal.status === "error") {
491
+ return terminal;
492
+ }
493
+ const inspection = this.runtimeManager.inspectPersistentSession(terminal, session);
494
+ if (!inspection.alive) {
495
+ if (shouldMarkRuntimeLost(terminal, inspection.detail)) {
496
+ return this.markTerminalLost(terminal, session, inspection.detail);
497
+ }
498
+ return this.markTerminalError(terminal, session, inspection.detail ?? buildMissingProcessStatusDetail(terminal));
499
+ }
500
+ if (ensureAttached) {
501
+ const attachmentProcessId = this.runtimeManager.ensureAttached(terminal, session, buildTerminalEnv());
502
+ return this.markTerminalRunning(terminal, session, inspection.shellPid ?? attachmentProcessId, inspection.detail);
503
+ }
504
+ return this.markTerminalRunning(terminal, session, inspection.shellPid, inspection.detail);
505
+ }
506
+ reconcileTerminalRuntime(terminal) {
507
+ if (terminal.status === "closed" || terminal.status === "error") {
508
+ return false;
509
+ }
510
+ const before = JSON.stringify({
511
+ status: terminal.status,
512
+ processId: terminal.processId,
513
+ statusDetail: terminal.statusDetail
514
+ });
515
+ const session = this.getRuntimeSessionOrThrow(terminal.runtimeSessionId);
516
+ const nextTerminal = this.ensureTerminalRunning(terminal, session, false);
517
+ const after = JSON.stringify({
518
+ status: nextTerminal.status,
519
+ processId: nextTerminal.processId,
520
+ statusDetail: nextTerminal.statusDetail
521
+ });
522
+ return before !== after;
523
+ }
524
+ markTerminalRunning(terminal, session, processId, detail) {
525
+ const shouldUpdate = terminal.status !== "running" ||
526
+ terminal.processId !== processId ||
527
+ terminal.closedAt !== null ||
528
+ (terminal.statusDetail ?? null) !== (detail ?? null) ||
529
+ session.state !== "running" ||
530
+ session.shellPid !== processId ||
531
+ (session.lastErrorDetail ?? null) !== (detail ?? null);
532
+ if (!shouldUpdate) {
533
+ return terminal;
534
+ }
535
+ const updatedAt = nowIso();
536
+ this.terminalInstanceRepository.updateLifecycle({
537
+ id: terminal.id,
538
+ status: "running",
539
+ processId,
540
+ lastActiveAt: terminal.lastActiveAt,
541
+ closedAt: null,
542
+ exitCode: null,
543
+ statusDetail: detail ?? null
544
+ });
545
+ this.terminalRuntimeSessionRepository.updateState({
546
+ id: session.id,
547
+ shellPid: processId,
548
+ state: "running",
549
+ lastCheckedAt: updatedAt,
550
+ lastErrorDetail: detail ?? null,
551
+ updatedAt
552
+ });
553
+ const updated = this.getTerminalOrThrow(terminal.id);
554
+ this.emit("status", updated);
555
+ return updated;
556
+ }
557
+ markTerminalLost(terminal, session, detail) {
558
+ const updatedAt = nowIso();
559
+ this.terminalRuntimeSessionRepository.updateState({
560
+ id: session.id,
561
+ shellPid: terminal.processId,
562
+ state: "lost",
563
+ lastCheckedAt: updatedAt,
564
+ lastErrorDetail: detail ?? "RUNTIME_LOST",
565
+ updatedAt
566
+ });
567
+ this.terminalInstanceRepository.updateLifecycle({
568
+ id: terminal.id,
569
+ status: "running",
570
+ processId: terminal.processId,
571
+ lastActiveAt: terminal.lastActiveAt,
572
+ closedAt: null,
573
+ exitCode: null,
574
+ statusDetail: detail ?? terminal.statusDetail
575
+ });
576
+ const updated = this.getTerminalOrThrow(terminal.id);
577
+ this.emit("status", updated);
578
+ return updated;
579
+ }
580
+ markTerminalError(terminal, session, detail) {
581
+ const closedAt = nowIso();
582
+ this.terminalInstanceRepository.updateLifecycle({
583
+ id: terminal.id,
584
+ status: "error",
585
+ processId: terminal.processId,
586
+ lastActiveAt: closedAt,
587
+ closedAt,
588
+ exitCode: terminal.exitCode,
589
+ statusDetail: detail
590
+ });
591
+ this.terminalRuntimeSessionRepository.updateState({
592
+ id: session.id,
593
+ shellPid: terminal.processId,
594
+ state: "error",
595
+ lastCheckedAt: closedAt,
596
+ lastErrorDetail: detail,
597
+ updatedAt: closedAt
598
+ });
599
+ const updated = this.getTerminalOrThrow(terminal.id);
600
+ this.emit("status", updated);
601
+ return updated;
602
+ }
603
+ finalizeTerminalClosure(terminal, session, event) {
604
+ const closeReason = this.pendingCloseReasons.get(terminal.id) ?? "user_closed";
605
+ this.pendingCloseReasons.delete(terminal.id);
606
+ const finishedAt = nowIso();
607
+ const status = event.requestedClose || event.exitCode === 0 ? "closed" : "error";
608
+ const statusDetail = status === "error"
609
+ ? event.sessionDetail ?? `终端异常退出,exitCode=${event.exitCode ?? "unknown"}`
610
+ : resolveClosedStatusDetail(closeReason, terminal.statusDetail);
611
+ this.terminalInstanceRepository.updateLifecycle({
612
+ id: terminal.id,
613
+ status,
614
+ processId: event.shellPid ?? terminal.processId,
615
+ lastActiveAt: finishedAt,
616
+ closedAt: finishedAt,
617
+ exitCode: event.exitCode,
618
+ statusDetail
619
+ });
620
+ this.terminalRuntimeSessionRepository.updateState({
621
+ id: session.id,
622
+ shellPid: event.shellPid,
623
+ state: status === "closed" ? "closed" : "error",
624
+ lastCheckedAt: finishedAt,
625
+ lastErrorDetail: status === "error" ? statusDetail : null,
626
+ updatedAt: finishedAt
627
+ });
628
+ const updated = this.getTerminalOrThrow(terminal.id);
629
+ this.emit("status", updated);
630
+ this.emit("exit", {
631
+ terminal: updated,
632
+ requestedClose: event.requestedClose
633
+ });
634
+ if (status === "closed") {
635
+ this.clearTerminalLogs(terminal.id);
636
+ }
637
+ }
638
+ recoverRuntimeStates() {
639
+ const terminals = this.terminalInstanceRepository.listRecoverable();
640
+ for (const terminal of terminals) {
641
+ const session = this.terminalRuntimeSessionRepository.findById(terminal.runtimeSessionId);
642
+ if (!session) {
643
+ this.markTerminalError(terminal, {
644
+ id: terminal.runtimeSessionId,
645
+ terminalId: terminal.id,
646
+ runtimeType: terminal.runtimeType,
647
+ sessionKey: terminal.runtimeSessionId,
648
+ attachTarget: terminal.attachTarget,
649
+ hostInstanceId: null,
650
+ agentPid: null,
651
+ shellPid: terminal.processId,
652
+ state: "error",
653
+ lastHeartbeatAt: null,
654
+ lastCheckedAt: null,
655
+ lastErrorDetail: "RUNTIME_SESSION_MISSING",
656
+ createdAt: terminal.createdAt,
657
+ updatedAt: terminal.lastActiveAt
658
+ }, "RUNTIME_SESSION_MISSING");
659
+ continue;
660
+ }
661
+ this.ensureTerminalRunning(terminal, session, false);
662
+ }
663
+ }
664
+ retainTerminalSubscription(terminalId) {
665
+ const currentCount = this.terminalSubscriptionCounts.get(terminalId) ?? 0;
666
+ this.terminalSubscriptionCounts.set(terminalId, currentCount + 1);
667
+ }
668
+ releaseTerminalSubscription(terminalId) {
669
+ const currentCount = this.terminalSubscriptionCounts.get(terminalId) ?? 0;
670
+ if (currentCount <= 1) {
671
+ this.terminalSubscriptionCounts.delete(terminalId);
672
+ this.detachRuntimeAttachmentIfIdle(terminalId);
673
+ return;
674
+ }
675
+ this.terminalSubscriptionCounts.set(terminalId, currentCount - 1);
676
+ }
677
+ detachRuntimeAttachmentIfIdle(terminalId) {
678
+ if (this.isDisposing) {
679
+ return;
680
+ }
681
+ const terminal = this.terminalInstanceRepository.findById(terminalId);
682
+ if (!terminal || terminal.status !== "running") {
683
+ return;
684
+ }
685
+ const session = this.terminalRuntimeSessionRepository.findById(terminal.runtimeSessionId);
686
+ if (!session || session.runtimeType === "embedded-pty") {
687
+ return;
688
+ }
689
+ this.runtimeManager.detach(terminalId);
690
+ }
691
+ flushTerminalLogs(terminalId) {
692
+ this.terminalLogSpooler?.flushTerminal(terminalId);
693
+ }
694
+ clearTerminalLogs(terminalId) {
695
+ this.outputBuffer.clear(terminalId);
696
+ this.terminalLogSegmentRepository?.deleteByTerminalId(terminalId);
697
+ this.terminalLogFileRepository?.deleteByTerminalId(terminalId);
698
+ this.terminalLogSpooler?.deleteTerminalLogs(terminalId);
699
+ }
700
+ }
701
+ function normalizeTerminalHistoryContent(content) {
702
+ return content
703
+ .replace(/\u001b\][^\u0007]*(?:\u0007|\u001b\\)/g, "")
704
+ .replace(/\u001bP[\s\S]*?\u001b\\/g, "")
705
+ .replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "")
706
+ .replace(/\r/g, "");
707
+ }
708
+ function countTerminalHistoryLines(content) {
709
+ if (!content) {
710
+ return 0;
711
+ }
712
+ const normalized = content.endsWith("\n") ? content.slice(0, -1) : content;
713
+ if (!normalized) {
714
+ return 0;
715
+ }
716
+ return normalized.split("\n").length;
717
+ }
718
+ function sanitizeShell(shell) {
719
+ const value = shell?.trim();
720
+ if (!value) {
721
+ return null;
722
+ }
723
+ if (value.includes("\0") || value.includes("\n") || value.includes("\r")) {
724
+ throw new AppError({
725
+ statusCode: 400,
726
+ errorCode: "INVALID_SHELL",
727
+ detail: "shell 不能包含非法控制字符",
728
+ field: "shell"
729
+ });
730
+ }
731
+ return value;
732
+ }
733
+ function resolveRequestedRuntimeType(input) {
734
+ const runtimeType = input ?? (process.platform === "win32" ? "embedded-pty" : "tmux");
735
+ if (runtimeType !== "embedded-pty" &&
736
+ runtimeType !== "tmux") {
737
+ throw new AppError({
738
+ statusCode: 400,
739
+ errorCode: "UNSUPPORTED_TERMINAL_RUNTIME",
740
+ detail: `当前 Host 还未实现 runtime=${runtimeType}`
741
+ });
742
+ }
743
+ return runtimeType;
744
+ }
745
+ function buildAttachTarget(runtimeType, runtimeSessionId) {
746
+ if (runtimeType === "embedded-pty") {
747
+ return `embedded:${runtimeSessionId}`;
748
+ }
749
+ return `${runtimeType}:${runtimeSessionId}`;
750
+ }
751
+ function buildTerminalEnv(extraEnv) {
752
+ const env = {};
753
+ for (const [key, value] of Object.entries(process.env)) {
754
+ if (typeof value === "string") {
755
+ env[key] = value;
756
+ }
757
+ }
758
+ for (const [key, value] of Object.entries(extraEnv ?? {})) {
759
+ env[key] = value;
760
+ }
761
+ return env;
762
+ }
763
+ function buildDefaultTerminalName(cwd) {
764
+ const folderName = path.basename(cwd).trim();
765
+ return folderName || "终端";
766
+ }
767
+ function buildMissingProcessStatusDetail(terminal) {
768
+ if (terminal.processId && !isProcessAlive(terminal.processId)) {
769
+ return `终端绑定进程已停止,PID=${terminal.processId}`;
770
+ }
771
+ if (terminal.processId) {
772
+ return `终端运行时已经失联,PID=${terminal.processId}`;
773
+ }
774
+ return "终端运行时已经失联";
775
+ }
776
+ function isProcessAlive(processId) {
777
+ try {
778
+ process.kill(processId, 0);
779
+ return true;
780
+ }
781
+ catch {
782
+ return false;
783
+ }
784
+ }
785
+ function resolveClosedStatusDetail(reason, currentStatusDetail) {
786
+ if (reason === "idle_timeout") {
787
+ return "TERMINAL_IDLE_TIMEOUT";
788
+ }
789
+ return currentStatusDetail;
790
+ }
791
+ function shouldMarkRuntimeLost(terminal, detail) {
792
+ return terminal.runtimeType !== "embedded-pty" && Boolean(detail?.includes("检查失败"));
793
+ }
794
+ //# sourceMappingURL=terminal-service.js.map