ys-code-agent 2.0.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 (373) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/SETUP.md +228 -0
  4. package/USAGE.md +437 -0
  5. package/dist/agent/index.d.ts +29 -0
  6. package/dist/agent/index.d.ts.map +1 -0
  7. package/dist/agent/index.js +501 -0
  8. package/dist/agent/index.js.map +1 -0
  9. package/dist/cli/agent.d.ts +10 -0
  10. package/dist/cli/agent.d.ts.map +1 -0
  11. package/dist/cli/agent.js +38 -0
  12. package/dist/cli/agent.js.map +1 -0
  13. package/dist/cli/index.cjs +19187 -0
  14. package/dist/cli/index.cjs.map +7 -0
  15. package/dist/cli/index.d.ts +2 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +326 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/interactive.d.ts +14 -0
  20. package/dist/cli/interactive.d.ts.map +1 -0
  21. package/dist/cli/interactive.js +125 -0
  22. package/dist/cli/interactive.js.map +1 -0
  23. package/dist/commands/CommandRegistry.d.ts +15 -0
  24. package/dist/commands/CommandRegistry.d.ts.map +1 -0
  25. package/dist/commands/CommandRegistry.js +1311 -0
  26. package/dist/commands/CommandRegistry.js.map +1 -0
  27. package/dist/commands/handlers/agents.d.ts +5 -0
  28. package/dist/commands/handlers/agents.d.ts.map +1 -0
  29. package/dist/commands/handlers/agents.js +124 -0
  30. package/dist/commands/handlers/agents.js.map +1 -0
  31. package/dist/commands/handlers/file.d.ts +8 -0
  32. package/dist/commands/handlers/file.d.ts.map +1 -0
  33. package/dist/commands/handlers/file.js +364 -0
  34. package/dist/commands/handlers/file.js.map +1 -0
  35. package/dist/commands/handlers/git.d.ts +2 -0
  36. package/dist/commands/handlers/git.d.ts.map +1 -0
  37. package/dist/commands/handlers/git.js +343 -0
  38. package/dist/commands/handlers/git.js.map +1 -0
  39. package/dist/commands/handlers/memory.d.ts +6 -0
  40. package/dist/commands/handlers/memory.d.ts.map +1 -0
  41. package/dist/commands/handlers/memory.js +149 -0
  42. package/dist/commands/handlers/memory.js.map +1 -0
  43. package/dist/commands/index.d.ts +3 -0
  44. package/dist/commands/index.d.ts.map +1 -0
  45. package/dist/commands/index.js +2 -0
  46. package/dist/commands/index.js.map +1 -0
  47. package/dist/config/index.d.ts +25 -0
  48. package/dist/config/index.d.ts.map +1 -0
  49. package/dist/config/index.js +399 -0
  50. package/dist/config/index.js.map +1 -0
  51. package/dist/context/index.d.ts +31 -0
  52. package/dist/context/index.d.ts.map +1 -0
  53. package/dist/context/index.js +208 -0
  54. package/dist/context/index.js.map +1 -0
  55. package/dist/filesystem/index.d.ts +52 -0
  56. package/dist/filesystem/index.d.ts.map +1 -0
  57. package/dist/filesystem/index.js +481 -0
  58. package/dist/filesystem/index.js.map +1 -0
  59. package/dist/git/index.d.ts +41 -0
  60. package/dist/git/index.d.ts.map +1 -0
  61. package/dist/git/index.js +381 -0
  62. package/dist/git/index.js.map +1 -0
  63. package/dist/logger/index.d.ts +32 -0
  64. package/dist/logger/index.d.ts.map +1 -0
  65. package/dist/logger/index.js +199 -0
  66. package/dist/logger/index.js.map +1 -0
  67. package/dist/memory/index.d.ts +45 -0
  68. package/dist/memory/index.d.ts.map +1 -0
  69. package/dist/memory/index.js +147 -0
  70. package/dist/memory/index.js.map +1 -0
  71. package/dist/project/index.d.ts +14 -0
  72. package/dist/project/index.d.ts.map +1 -0
  73. package/dist/project/index.js +371 -0
  74. package/dist/project/index.js.map +1 -0
  75. package/dist/providers/anthropic.d.ts +22 -0
  76. package/dist/providers/anthropic.d.ts.map +1 -0
  77. package/dist/providers/anthropic.js +202 -0
  78. package/dist/providers/anthropic.js.map +1 -0
  79. package/dist/providers/base.d.ts +29 -0
  80. package/dist/providers/base.d.ts.map +1 -0
  81. package/dist/providers/base.js +119 -0
  82. package/dist/providers/base.js.map +1 -0
  83. package/dist/providers/custom.d.ts +8 -0
  84. package/dist/providers/custom.d.ts.map +1 -0
  85. package/dist/providers/custom.js +13 -0
  86. package/dist/providers/custom.js.map +1 -0
  87. package/dist/providers/deepseek.d.ts +8 -0
  88. package/dist/providers/deepseek.d.ts.map +1 -0
  89. package/dist/providers/deepseek.js +13 -0
  90. package/dist/providers/deepseek.js.map +1 -0
  91. package/dist/providers/gemini.d.ts +18 -0
  92. package/dist/providers/gemini.d.ts.map +1 -0
  93. package/dist/providers/gemini.js +183 -0
  94. package/dist/providers/gemini.js.map +1 -0
  95. package/dist/providers/groq.d.ts +8 -0
  96. package/dist/providers/groq.d.ts.map +1 -0
  97. package/dist/providers/groq.js +13 -0
  98. package/dist/providers/groq.js.map +1 -0
  99. package/dist/providers/index.d.ts +16 -0
  100. package/dist/providers/index.d.ts.map +1 -0
  101. package/dist/providers/index.js +50 -0
  102. package/dist/providers/index.js.map +1 -0
  103. package/dist/providers/lmstudio.d.ts +9 -0
  104. package/dist/providers/lmstudio.d.ts.map +1 -0
  105. package/dist/providers/lmstudio.js +18 -0
  106. package/dist/providers/lmstudio.js.map +1 -0
  107. package/dist/providers/ollama.d.ts +8 -0
  108. package/dist/providers/ollama.d.ts.map +1 -0
  109. package/dist/providers/ollama.js +13 -0
  110. package/dist/providers/ollama.js.map +1 -0
  111. package/dist/providers/openai.d.ts +16 -0
  112. package/dist/providers/openai.d.ts.map +1 -0
  113. package/dist/providers/openai.js +116 -0
  114. package/dist/providers/openai.js.map +1 -0
  115. package/dist/providers/openrouter.d.ts +9 -0
  116. package/dist/providers/openrouter.d.ts.map +1 -0
  117. package/dist/providers/openrouter.js +21 -0
  118. package/dist/providers/openrouter.js.map +1 -0
  119. package/dist/security/index.d.ts +28 -0
  120. package/dist/security/index.d.ts.map +1 -0
  121. package/dist/security/index.js +139 -0
  122. package/dist/security/index.js.map +1 -0
  123. package/dist/session/index.d.ts +36 -0
  124. package/dist/session/index.d.ts.map +1 -0
  125. package/dist/session/index.js +203 -0
  126. package/dist/session/index.js.map +1 -0
  127. package/dist/src/agent/index.d.ts +29 -0
  128. package/dist/src/agent/index.d.ts.map +1 -0
  129. package/dist/src/agent/index.js +504 -0
  130. package/dist/src/agent/index.js.map +1 -0
  131. package/dist/src/cli/agent.d.ts +10 -0
  132. package/dist/src/cli/agent.d.ts.map +1 -0
  133. package/dist/src/cli/agent.js +38 -0
  134. package/dist/src/cli/agent.js.map +1 -0
  135. package/dist/src/cli/index.d.ts +3 -0
  136. package/dist/src/cli/index.d.ts.map +1 -0
  137. package/dist/src/cli/index.js +327 -0
  138. package/dist/src/cli/index.js.map +1 -0
  139. package/dist/src/cli/interactive.d.ts +12 -0
  140. package/dist/src/cli/interactive.d.ts.map +1 -0
  141. package/dist/src/cli/interactive.js +202 -0
  142. package/dist/src/cli/interactive.js.map +1 -0
  143. package/dist/src/config/index.d.ts +25 -0
  144. package/dist/src/config/index.d.ts.map +1 -0
  145. package/dist/src/config/index.js +398 -0
  146. package/dist/src/config/index.js.map +1 -0
  147. package/dist/src/context/index.d.ts +31 -0
  148. package/dist/src/context/index.d.ts.map +1 -0
  149. package/dist/src/context/index.js +208 -0
  150. package/dist/src/context/index.js.map +1 -0
  151. package/dist/src/filesystem/index.d.ts +52 -0
  152. package/dist/src/filesystem/index.d.ts.map +1 -0
  153. package/dist/src/filesystem/index.js +481 -0
  154. package/dist/src/filesystem/index.js.map +1 -0
  155. package/dist/src/git/index.d.ts +41 -0
  156. package/dist/src/git/index.d.ts.map +1 -0
  157. package/dist/src/git/index.js +381 -0
  158. package/dist/src/git/index.js.map +1 -0
  159. package/dist/src/logger/index.d.ts +32 -0
  160. package/dist/src/logger/index.d.ts.map +1 -0
  161. package/dist/src/logger/index.js +199 -0
  162. package/dist/src/logger/index.js.map +1 -0
  163. package/dist/src/memory/index.d.ts +45 -0
  164. package/dist/src/memory/index.d.ts.map +1 -0
  165. package/dist/src/memory/index.js +147 -0
  166. package/dist/src/memory/index.js.map +1 -0
  167. package/dist/src/project/index.d.ts +14 -0
  168. package/dist/src/project/index.d.ts.map +1 -0
  169. package/dist/src/project/index.js +371 -0
  170. package/dist/src/project/index.js.map +1 -0
  171. package/dist/src/providers/anthropic.d.ts +22 -0
  172. package/dist/src/providers/anthropic.d.ts.map +1 -0
  173. package/dist/src/providers/anthropic.js +202 -0
  174. package/dist/src/providers/anthropic.js.map +1 -0
  175. package/dist/src/providers/base.d.ts +29 -0
  176. package/dist/src/providers/base.d.ts.map +1 -0
  177. package/dist/src/providers/base.js +112 -0
  178. package/dist/src/providers/base.js.map +1 -0
  179. package/dist/src/providers/custom.d.ts +8 -0
  180. package/dist/src/providers/custom.d.ts.map +1 -0
  181. package/dist/src/providers/custom.js +13 -0
  182. package/dist/src/providers/custom.js.map +1 -0
  183. package/dist/src/providers/deepseek.d.ts +8 -0
  184. package/dist/src/providers/deepseek.d.ts.map +1 -0
  185. package/dist/src/providers/deepseek.js +13 -0
  186. package/dist/src/providers/deepseek.js.map +1 -0
  187. package/dist/src/providers/gemini.d.ts +18 -0
  188. package/dist/src/providers/gemini.d.ts.map +1 -0
  189. package/dist/src/providers/gemini.js +183 -0
  190. package/dist/src/providers/gemini.js.map +1 -0
  191. package/dist/src/providers/groq.d.ts +8 -0
  192. package/dist/src/providers/groq.d.ts.map +1 -0
  193. package/dist/src/providers/groq.js +13 -0
  194. package/dist/src/providers/groq.js.map +1 -0
  195. package/dist/src/providers/index.d.ts +16 -0
  196. package/dist/src/providers/index.d.ts.map +1 -0
  197. package/dist/src/providers/index.js +50 -0
  198. package/dist/src/providers/index.js.map +1 -0
  199. package/dist/src/providers/lmstudio.d.ts +9 -0
  200. package/dist/src/providers/lmstudio.d.ts.map +1 -0
  201. package/dist/src/providers/lmstudio.js +18 -0
  202. package/dist/src/providers/lmstudio.js.map +1 -0
  203. package/dist/src/providers/ollama.d.ts +8 -0
  204. package/dist/src/providers/ollama.d.ts.map +1 -0
  205. package/dist/src/providers/ollama.js +13 -0
  206. package/dist/src/providers/ollama.js.map +1 -0
  207. package/dist/src/providers/openai.d.ts +16 -0
  208. package/dist/src/providers/openai.d.ts.map +1 -0
  209. package/dist/src/providers/openai.js +116 -0
  210. package/dist/src/providers/openai.js.map +1 -0
  211. package/dist/src/providers/openrouter.d.ts +9 -0
  212. package/dist/src/providers/openrouter.d.ts.map +1 -0
  213. package/dist/src/providers/openrouter.js +21 -0
  214. package/dist/src/providers/openrouter.js.map +1 -0
  215. package/dist/src/security/index.d.ts +28 -0
  216. package/dist/src/security/index.d.ts.map +1 -0
  217. package/dist/src/security/index.js +139 -0
  218. package/dist/src/security/index.js.map +1 -0
  219. package/dist/src/session/index.d.ts +36 -0
  220. package/dist/src/session/index.d.ts.map +1 -0
  221. package/dist/src/session/index.js +203 -0
  222. package/dist/src/session/index.js.map +1 -0
  223. package/dist/src/terminal/index.d.ts +27 -0
  224. package/dist/src/terminal/index.d.ts.map +1 -0
  225. package/dist/src/terminal/index.js +211 -0
  226. package/dist/src/terminal/index.js.map +1 -0
  227. package/dist/src/tools/DeleteFileTool.d.ts +7 -0
  228. package/dist/src/tools/DeleteFileTool.d.ts.map +1 -0
  229. package/dist/src/tools/DeleteFileTool.js +50 -0
  230. package/dist/src/tools/DeleteFileTool.js.map +1 -0
  231. package/dist/src/tools/DirectoryTreeTool.d.ts +7 -0
  232. package/dist/src/tools/DirectoryTreeTool.d.ts.map +1 -0
  233. package/dist/src/tools/DirectoryTreeTool.js +50 -0
  234. package/dist/src/tools/DirectoryTreeTool.js.map +1 -0
  235. package/dist/src/tools/EditFileTool.d.ts +7 -0
  236. package/dist/src/tools/EditFileTool.d.ts.map +1 -0
  237. package/dist/src/tools/EditFileTool.js +69 -0
  238. package/dist/src/tools/EditFileTool.js.map +1 -0
  239. package/dist/src/tools/GitTool.d.ts +9 -0
  240. package/dist/src/tools/GitTool.d.ts.map +1 -0
  241. package/dist/src/tools/GitTool.js +115 -0
  242. package/dist/src/tools/GitTool.js.map +1 -0
  243. package/dist/src/tools/GlobTool.d.ts +7 -0
  244. package/dist/src/tools/GlobTool.d.ts.map +1 -0
  245. package/dist/src/tools/GlobTool.js +51 -0
  246. package/dist/src/tools/GlobTool.js.map +1 -0
  247. package/dist/src/tools/MemoryTool.d.ts +9 -0
  248. package/dist/src/tools/MemoryTool.d.ts.map +1 -0
  249. package/dist/src/tools/MemoryTool.js +109 -0
  250. package/dist/src/tools/MemoryTool.js.map +1 -0
  251. package/dist/src/tools/ReadFileTool.d.ts +7 -0
  252. package/dist/src/tools/ReadFileTool.d.ts.map +1 -0
  253. package/dist/src/tools/ReadFileTool.js +75 -0
  254. package/dist/src/tools/ReadFileTool.js.map +1 -0
  255. package/dist/src/tools/SearchTool.d.ts +7 -0
  256. package/dist/src/tools/SearchTool.d.ts.map +1 -0
  257. package/dist/src/tools/SearchTool.js +67 -0
  258. package/dist/src/tools/SearchTool.js.map +1 -0
  259. package/dist/src/tools/TerminalTool.d.ts +9 -0
  260. package/dist/src/tools/TerminalTool.d.ts.map +1 -0
  261. package/dist/src/tools/TerminalTool.js +93 -0
  262. package/dist/src/tools/TerminalTool.js.map +1 -0
  263. package/dist/src/tools/WebFetchTool.d.ts +7 -0
  264. package/dist/src/tools/WebFetchTool.d.ts.map +1 -0
  265. package/dist/src/tools/WebFetchTool.js +120 -0
  266. package/dist/src/tools/WebFetchTool.js.map +1 -0
  267. package/dist/src/tools/WriteFileTool.d.ts +7 -0
  268. package/dist/src/tools/WriteFileTool.d.ts.map +1 -0
  269. package/dist/src/tools/WriteFileTool.js +46 -0
  270. package/dist/src/tools/WriteFileTool.js.map +1 -0
  271. package/dist/src/tools/base.d.ts +36 -0
  272. package/dist/src/tools/base.d.ts.map +1 -0
  273. package/dist/src/tools/base.js +159 -0
  274. package/dist/src/tools/base.js.map +1 -0
  275. package/dist/src/tools/index.d.ts +14 -0
  276. package/dist/src/tools/index.d.ts.map +1 -0
  277. package/dist/src/tools/index.js +44 -0
  278. package/dist/src/tools/index.js.map +1 -0
  279. package/dist/src/types.d.ts +315 -0
  280. package/dist/src/types.d.ts.map +1 -0
  281. package/dist/src/types.js +2 -0
  282. package/dist/src/types.js.map +1 -0
  283. package/dist/src/ui/index.d.ts +50 -0
  284. package/dist/src/ui/index.d.ts.map +1 -0
  285. package/dist/src/ui/index.js +274 -0
  286. package/dist/src/ui/index.js.map +1 -0
  287. package/dist/src/utils/index.d.ts +26 -0
  288. package/dist/src/utils/index.d.ts.map +1 -0
  289. package/dist/src/utils/index.js +248 -0
  290. package/dist/src/utils/index.js.map +1 -0
  291. package/dist/terminal/index.d.ts +27 -0
  292. package/dist/terminal/index.d.ts.map +1 -0
  293. package/dist/terminal/index.js +211 -0
  294. package/dist/terminal/index.js.map +1 -0
  295. package/dist/tools/DeleteFileTool.d.ts +7 -0
  296. package/dist/tools/DeleteFileTool.d.ts.map +1 -0
  297. package/dist/tools/DeleteFileTool.js +50 -0
  298. package/dist/tools/DeleteFileTool.js.map +1 -0
  299. package/dist/tools/DirectoryTreeTool.d.ts +7 -0
  300. package/dist/tools/DirectoryTreeTool.d.ts.map +1 -0
  301. package/dist/tools/DirectoryTreeTool.js +50 -0
  302. package/dist/tools/DirectoryTreeTool.js.map +1 -0
  303. package/dist/tools/EditFileTool.d.ts +7 -0
  304. package/dist/tools/EditFileTool.d.ts.map +1 -0
  305. package/dist/tools/EditFileTool.js +69 -0
  306. package/dist/tools/EditFileTool.js.map +1 -0
  307. package/dist/tools/GitTool.d.ts +9 -0
  308. package/dist/tools/GitTool.d.ts.map +1 -0
  309. package/dist/tools/GitTool.js +115 -0
  310. package/dist/tools/GitTool.js.map +1 -0
  311. package/dist/tools/GlobTool.d.ts +7 -0
  312. package/dist/tools/GlobTool.d.ts.map +1 -0
  313. package/dist/tools/GlobTool.js +51 -0
  314. package/dist/tools/GlobTool.js.map +1 -0
  315. package/dist/tools/MemoryTool.d.ts +9 -0
  316. package/dist/tools/MemoryTool.d.ts.map +1 -0
  317. package/dist/tools/MemoryTool.js +109 -0
  318. package/dist/tools/MemoryTool.js.map +1 -0
  319. package/dist/tools/ReadFileTool.d.ts +7 -0
  320. package/dist/tools/ReadFileTool.d.ts.map +1 -0
  321. package/dist/tools/ReadFileTool.js +75 -0
  322. package/dist/tools/ReadFileTool.js.map +1 -0
  323. package/dist/tools/SearchTool.d.ts +7 -0
  324. package/dist/tools/SearchTool.d.ts.map +1 -0
  325. package/dist/tools/SearchTool.js +67 -0
  326. package/dist/tools/SearchTool.js.map +1 -0
  327. package/dist/tools/TerminalTool.d.ts +9 -0
  328. package/dist/tools/TerminalTool.d.ts.map +1 -0
  329. package/dist/tools/TerminalTool.js +93 -0
  330. package/dist/tools/TerminalTool.js.map +1 -0
  331. package/dist/tools/WebFetchTool.d.ts +7 -0
  332. package/dist/tools/WebFetchTool.d.ts.map +1 -0
  333. package/dist/tools/WebFetchTool.js +120 -0
  334. package/dist/tools/WebFetchTool.js.map +1 -0
  335. package/dist/tools/WriteFileTool.d.ts +7 -0
  336. package/dist/tools/WriteFileTool.d.ts.map +1 -0
  337. package/dist/tools/WriteFileTool.js +46 -0
  338. package/dist/tools/WriteFileTool.js.map +1 -0
  339. package/dist/tools/base.d.ts +36 -0
  340. package/dist/tools/base.d.ts.map +1 -0
  341. package/dist/tools/base.js +159 -0
  342. package/dist/tools/base.js.map +1 -0
  343. package/dist/tools/index.d.ts +14 -0
  344. package/dist/tools/index.d.ts.map +1 -0
  345. package/dist/tools/index.js +44 -0
  346. package/dist/tools/index.js.map +1 -0
  347. package/dist/types.d.ts +315 -0
  348. package/dist/types.d.ts.map +1 -0
  349. package/dist/types.js +2 -0
  350. package/dist/types.js.map +1 -0
  351. package/dist/ui/CommandPopup.d.ts +33 -0
  352. package/dist/ui/CommandPopup.d.ts.map +1 -0
  353. package/dist/ui/CommandPopup.js +179 -0
  354. package/dist/ui/CommandPopup.js.map +1 -0
  355. package/dist/ui/WelcomeScreen.d.ts +3 -0
  356. package/dist/ui/WelcomeScreen.d.ts.map +1 -0
  357. package/dist/ui/WelcomeScreen.js +168 -0
  358. package/dist/ui/WelcomeScreen.js.map +1 -0
  359. package/dist/ui/index.d.ts +75 -0
  360. package/dist/ui/index.d.ts.map +1 -0
  361. package/dist/ui/index.js +728 -0
  362. package/dist/ui/index.js.map +1 -0
  363. package/dist/ui/phoneOptimizer.d.ts +15 -0
  364. package/dist/ui/phoneOptimizer.d.ts.map +1 -0
  365. package/dist/ui/phoneOptimizer.js +58 -0
  366. package/dist/ui/phoneOptimizer.js.map +1 -0
  367. package/dist/utils/index.d.ts +26 -0
  368. package/dist/utils/index.d.ts.map +1 -0
  369. package/dist/utils/index.js +248 -0
  370. package/dist/utils/index.js.map +1 -0
  371. package/package.json +80 -0
  372. package/scripts/build.mjs +53 -0
  373. package/scripts/setup-termux.sh +84 -0
@@ -0,0 +1,728 @@
1
+ import chalk from 'chalk';
2
+ import { getLogger } from '../logger/index.js';
3
+ import { configManager } from '../config/index.js';
4
+ import { phoneConfig } from './phoneOptimizer.js';
5
+ import { CommandPopup, CATEGORY_ICONS } from './CommandPopup.js';
6
+ import { generateWelcome } from './WelcomeScreen.js';
7
+ const logger = getLogger('ui');
8
+ const INDICATORS = {
9
+ idle: '○',
10
+ thinking: '◐',
11
+ planning: '◑',
12
+ executing: '◓',
13
+ waiting: '◒',
14
+ completed: '●',
15
+ error: '✕',
16
+ };
17
+ const STATUS_COLORS = {
18
+ idle: chalk.gray,
19
+ thinking: chalk.cyan,
20
+ planning: chalk.yellow,
21
+ executing: chalk.magenta,
22
+ waiting: chalk.blue,
23
+ completed: chalk.green,
24
+ error: chalk.red,
25
+ };
26
+ export class TUI {
27
+ status = 'idle';
28
+ approvalMode = 'normal';
29
+ agentMode = 'chat';
30
+ outputLines = [];
31
+ maxOutputLines = 1000;
32
+ onInput = null;
33
+ onSpecialKey = null;
34
+ running = false;
35
+ commandPopup;
36
+ inputBuffer = '';
37
+ inputHistory = [];
38
+ historyIndex = -1;
39
+ cursorPos = 0;
40
+ popupActive = false;
41
+ cancelRequested = false;
42
+ onCancelRequest = null;
43
+ stdinRaw = false;
44
+ constructor() {
45
+ this.commandPopup = new CommandPopup();
46
+ this.loadHistory();
47
+ this.setupRawMode();
48
+ }
49
+ loadHistory() {
50
+ try {
51
+ const { readFileSync, existsSync } = require('fs');
52
+ const { join, homedir } = require('path');
53
+ const histPath = join(homedir(), '.ys', 'history.json');
54
+ if (existsSync(histPath)) {
55
+ this.inputHistory = JSON.parse(readFileSync(histPath, 'utf-8'));
56
+ }
57
+ }
58
+ catch { }
59
+ }
60
+ saveHistory() {
61
+ try {
62
+ const { writeFileSync, mkdirSync, existsSync } = require('fs');
63
+ const { join, homedir, dirname } = require('path');
64
+ const histPath = join(homedir(), '.ys', 'history.json');
65
+ const dir = dirname(histPath);
66
+ if (!existsSync(dir))
67
+ mkdirSync(dir, { recursive: true });
68
+ writeFileSync(histPath, JSON.stringify(this.inputHistory.slice(-500)), 'utf-8');
69
+ }
70
+ catch { }
71
+ }
72
+ setupRawMode() {
73
+ if (!process.stdin.isTTY)
74
+ return;
75
+ try {
76
+ process.stdin.setRawMode?.(true);
77
+ this.stdinRaw = true;
78
+ }
79
+ catch {
80
+ this.stdinRaw = false;
81
+ }
82
+ }
83
+ setOnCancelRequest(cb) {
84
+ this.onCancelRequest = cb;
85
+ }
86
+ start() {
87
+ this.running = true;
88
+ this.clear();
89
+ this.printWelcome();
90
+ this.showPrompt();
91
+ this.startKeyListener();
92
+ }
93
+ startKeyListener() {
94
+ if (!process.stdin.isTTY) {
95
+ this.startLineMode();
96
+ return;
97
+ }
98
+ process.stdin.on('data', (data) => {
99
+ if (!this.running)
100
+ return;
101
+ const input = data.toString('utf-8');
102
+ if (this.popupActive) {
103
+ this.handlePopupKey(input);
104
+ this.renderScreen();
105
+ return;
106
+ }
107
+ if (input === '\x1b' || input === '\x1b[' || input === '\x1b[' && data.length > 2) {
108
+ if (input === '\x1b') {
109
+ if (this.inputBuffer.length === 0) {
110
+ void this.handleSpecialKey('escape');
111
+ }
112
+ else {
113
+ this.inputBuffer = '';
114
+ this.cursorPos = 0;
115
+ this.renderScreen();
116
+ }
117
+ return;
118
+ }
119
+ return;
120
+ }
121
+ if (input === '\x1b[A') {
122
+ void this.handleSpecialKey('up');
123
+ return;
124
+ }
125
+ if (input === '\x1b[B') {
126
+ void this.handleSpecialKey('down');
127
+ return;
128
+ }
129
+ if (input === '\x1b[C') {
130
+ void this.handleSpecialKey('right');
131
+ return;
132
+ }
133
+ if (input === '\x1b[D') {
134
+ void this.handleSpecialKey('left');
135
+ return;
136
+ }
137
+ if (input === '\r' || input === '\n') {
138
+ void this.handleSpecialKey('enter');
139
+ return;
140
+ }
141
+ if (input === '\x7f' || input === '\b') {
142
+ void this.handleSpecialKey('backspace');
143
+ return;
144
+ }
145
+ if (input === '\x03') {
146
+ void this.handleSpecialKey('ctrl_c');
147
+ return;
148
+ }
149
+ if (input === '\x0c') {
150
+ void this.handleSpecialKey('ctrl_l');
151
+ return;
152
+ }
153
+ if (input === '\x01') {
154
+ void this.handleSpecialKey('ctrl_a');
155
+ return;
156
+ }
157
+ if (input === '\x05') {
158
+ void this.handleSpecialKey('ctrl_e');
159
+ return;
160
+ }
161
+ if (input === '\x0a' || input === '\x0d') {
162
+ return;
163
+ }
164
+ if (input === '\x09') {
165
+ void this.handleSpecialKey('tab');
166
+ return;
167
+ }
168
+ if (input === '\x0f') {
169
+ void this.handleSpecialKey('ctrl_o');
170
+ return;
171
+ }
172
+ if (input === '\x18') {
173
+ void this.handleSpecialKey('ctrl_x');
174
+ return;
175
+ }
176
+ this.inputBuffer = this.inputBuffer.slice(0, this.cursorPos) + input + this.inputBuffer.slice(this.cursorPos);
177
+ this.cursorPos += input.length;
178
+ if (input === '/') {
179
+ this.popupActive = true;
180
+ this.commandPopup.open();
181
+ this.commandPopup.setFilter(input);
182
+ }
183
+ else {
184
+ if (this.inputBuffer.startsWith('/') && this.inputBuffer.length > 1) {
185
+ this.popupActive = true;
186
+ this.commandPopup.open();
187
+ this.commandPopup.setFilter(this.inputBuffer);
188
+ }
189
+ }
190
+ this.renderScreen();
191
+ });
192
+ process.stdin.on('end', () => { });
193
+ }
194
+ startLineMode() {
195
+ const { createInterface } = require('readline');
196
+ const rl = createInterface({ input: process.stdin, output: process.stdout, prompt: '' });
197
+ rl.on('line', (line) => {
198
+ this.inputBuffer = line.trim();
199
+ if (this.inputBuffer && this.onInput) {
200
+ this.addHistory(this.inputBuffer);
201
+ this.onInput(this.inputBuffer);
202
+ }
203
+ this.inputBuffer = '';
204
+ this.showPrompt();
205
+ });
206
+ rl.on('SIGINT', () => process.exit(0));
207
+ this.showPrompt();
208
+ }
209
+ handlePopupKey(input) {
210
+ if (input === '\x1b') {
211
+ this.popupActive = false;
212
+ this.commandPopup.close();
213
+ this.inputBuffer = '';
214
+ this.cursorPos = 0;
215
+ return;
216
+ }
217
+ if (input === '\x1b[A' || input === '\x1bOA') {
218
+ this.commandPopup.moveUp();
219
+ return;
220
+ }
221
+ if (input === '\x1b[B' || input === '\x1bOB') {
222
+ this.commandPopup.moveDown();
223
+ return;
224
+ }
225
+ if (input === '\r' || input === '\n') {
226
+ const selectedCmd = this.commandPopup.getSelectedCommand();
227
+ if (selectedCmd) {
228
+ this.popupActive = false;
229
+ this.commandPopup.close();
230
+ const fullCmd = `/${selectedCmd} `;
231
+ this.inputBuffer = fullCmd;
232
+ this.cursorPos = fullCmd.length;
233
+ }
234
+ return;
235
+ }
236
+ if (input === '\x09') {
237
+ const selectedCmd = this.commandPopup.getSelectedCommand();
238
+ if (selectedCmd) {
239
+ this.popupActive = false;
240
+ this.commandPopup.close();
241
+ const fullCmd = `/${selectedCmd} `;
242
+ this.inputBuffer = fullCmd;
243
+ this.cursorPos = fullCmd.length;
244
+ }
245
+ return;
246
+ }
247
+ if (input === '\x7f' || input === '\b') {
248
+ const currentFilter = this.commandPopup.getFilterText();
249
+ if (currentFilter.length <= 1) {
250
+ this.popupActive = false;
251
+ this.commandPopup.close();
252
+ this.inputBuffer = '';
253
+ this.cursorPos = 0;
254
+ return;
255
+ }
256
+ this.commandPopup.deleteChar();
257
+ return;
258
+ }
259
+ if (input.length === 1 && input.charCodeAt(0) >= 32) {
260
+ this.commandPopup.appendChar(input);
261
+ this.inputBuffer = this.commandPopup.getFilterText();
262
+ this.cursorPos = this.inputBuffer.length;
263
+ }
264
+ }
265
+ async handleSpecialKey(key) {
266
+ switch (key) {
267
+ case 'escape':
268
+ if (this.inputBuffer.length > 0) {
269
+ this.inputBuffer = '';
270
+ this.cursorPos = 0;
271
+ this.renderScreen();
272
+ }
273
+ break;
274
+ case 'enter':
275
+ if (this.inputBuffer.trim()) {
276
+ this.addHistory(this.inputBuffer.trim());
277
+ const msg = this.inputBuffer.trim();
278
+ this.inputBuffer = '';
279
+ this.cursorPos = 0;
280
+ this.clearOutputLine();
281
+ if (this.onInput)
282
+ this.onInput(msg);
283
+ }
284
+ this.renderScreen();
285
+ break;
286
+ case 'backspace':
287
+ if (this.cursorPos > 0) {
288
+ this.inputBuffer = this.inputBuffer.slice(0, this.cursorPos - 1) + this.inputBuffer.slice(this.cursorPos);
289
+ this.cursorPos--;
290
+ this.updatePopupFilter();
291
+ }
292
+ this.renderScreen();
293
+ break;
294
+ case 'up':
295
+ if (this.inputHistory.length > 0) {
296
+ if (this.historyIndex === -1) {
297
+ this.historyIndex = this.inputHistory.length - 1;
298
+ }
299
+ else if (this.historyIndex > 0) {
300
+ this.historyIndex--;
301
+ }
302
+ this.inputBuffer = this.inputHistory[this.historyIndex];
303
+ this.cursorPos = this.inputBuffer.length;
304
+ this.renderScreen();
305
+ }
306
+ break;
307
+ case 'down':
308
+ if (this.historyIndex >= 0) {
309
+ this.historyIndex++;
310
+ if (this.historyIndex >= this.inputHistory.length) {
311
+ this.historyIndex = -1;
312
+ this.inputBuffer = '';
313
+ }
314
+ else {
315
+ this.inputBuffer = this.inputHistory[this.historyIndex];
316
+ }
317
+ this.cursorPos = this.inputBuffer.length;
318
+ this.renderScreen();
319
+ }
320
+ break;
321
+ case 'left':
322
+ if (this.cursorPos > 0) {
323
+ this.cursorPos--;
324
+ this.renderScreen();
325
+ }
326
+ break;
327
+ case 'right':
328
+ if (this.cursorPos < this.inputBuffer.length) {
329
+ this.cursorPos++;
330
+ this.renderScreen();
331
+ }
332
+ break;
333
+ case 'ctrl_a':
334
+ this.cursorPos = 0;
335
+ this.renderScreen();
336
+ break;
337
+ case 'ctrl_e':
338
+ this.cursorPos = this.inputBuffer.length;
339
+ this.renderScreen();
340
+ break;
341
+ case 'ctrl_c':
342
+ if (this.cancelRequested || this.status === 'thinking' || this.status === 'executing') {
343
+ if (this.onCancelRequest)
344
+ this.onCancelRequest();
345
+ }
346
+ else {
347
+ this.printLine('\n' + chalk.yellow('Use /exit to quit, or press Ctrl+C again to force quit'));
348
+ this.cancelRequested = true;
349
+ setTimeout(() => { this.cancelRequested = false; }, 2000);
350
+ }
351
+ break;
352
+ case 'ctrl_l':
353
+ this.clear();
354
+ this.printWelcome();
355
+ this.showPrompt();
356
+ break;
357
+ case 'tab': {
358
+ const match = this.inputBuffer.match(/^\/?(\w*)$/);
359
+ if (match) {
360
+ const partial = match[1].toLowerCase();
361
+ const cmds = this.getAllCommands().filter((c) => c.startsWith(partial));
362
+ if (cmds.length === 1) {
363
+ this.inputBuffer = `/${cmds[0]} `;
364
+ this.cursorPos = this.inputBuffer.length;
365
+ this.renderScreen();
366
+ }
367
+ }
368
+ break;
369
+ }
370
+ case 'ctrl_o':
371
+ break;
372
+ case 'ctrl_x':
373
+ void this.openExternalEditor();
374
+ break;
375
+ }
376
+ }
377
+ updatePopupFilter() {
378
+ if (this.popupActive) {
379
+ this.commandPopup.setFilter(this.inputBuffer);
380
+ if (this.inputBuffer === '/' || this.inputBuffer === '') {
381
+ this.popupActive = false;
382
+ this.commandPopup.close();
383
+ }
384
+ }
385
+ }
386
+ getAllCommands() {
387
+ const { ALL_COMMANDS } = require('./CommandPopup.js');
388
+ return ALL_COMMANDS.map((c) => c.command);
389
+ }
390
+ async openExternalEditor() {
391
+ const editor = process.env.EDITOR || 'nano';
392
+ const { writeFileSync, unlinkSync, existsSync, mkdirSync } = await import('fs');
393
+ const { join } = await import('path');
394
+ const tmpDir = '/tmp/ys-agent';
395
+ if (!existsSync(tmpDir))
396
+ mkdirSync(tmpDir, { recursive: true });
397
+ const tmpFile = join(tmpDir, `input-${Date.now()}.md`);
398
+ writeFileSync(tmpFile, this.inputBuffer, 'utf-8');
399
+ const { execSync } = await import('child_process');
400
+ try {
401
+ execSync(`${editor} "${tmpFile}"`, { stdio: 'inherit' });
402
+ const { readFileSync } = await import('fs');
403
+ const content = readFileSync(tmpFile, 'utf-8').trim();
404
+ if (content) {
405
+ this.inputBuffer = content;
406
+ this.cursorPos = content.length;
407
+ this.renderScreen();
408
+ }
409
+ }
410
+ catch { }
411
+ try {
412
+ unlinkSync(tmpFile);
413
+ }
414
+ catch { }
415
+ }
416
+ addHistory(input) {
417
+ if (this.inputHistory[this.inputHistory.length - 1] !== input) {
418
+ this.inputHistory.push(input);
419
+ }
420
+ this.historyIndex = -1;
421
+ this.saveHistory();
422
+ }
423
+ renderScreen() {
424
+ if (!process.stdout.isTTY)
425
+ return;
426
+ const lines = this.buildDisplayLines();
427
+ const clearSeq = `\x1b[0J\x1b[${process.stdout.rows || 24};0H`;
428
+ const output = clearSeq + lines.join('\n');
429
+ try {
430
+ cursorToSync(process.stdout, 0, (process.stdout.rows || 24) - lines.length);
431
+ process.stdout.write(output);
432
+ }
433
+ catch { }
434
+ }
435
+ buildDisplayLines() {
436
+ const lines = [];
437
+ if (this.popupActive) {
438
+ const popupLines = this.commandPopup.render().split('\n');
439
+ lines.push(...popupLines);
440
+ }
441
+ lines.push(this.buildPromptLine());
442
+ return lines;
443
+ }
444
+ stop() {
445
+ this.running = false;
446
+ if (this.stdinRaw && process.stdin.isTTY) {
447
+ try {
448
+ process.stdin.setRawMode?.(false);
449
+ }
450
+ catch { }
451
+ }
452
+ process.stdin.removeAllListeners('data');
453
+ this.showShutdownScreen();
454
+ }
455
+ clear() {
456
+ console.clear();
457
+ }
458
+ clearOutputLine() {
459
+ try {
460
+ const { cursorTo, clearLine } = require('readline');
461
+ cursorTo(process.stdout, 0);
462
+ clearLine(process.stdout, 1);
463
+ }
464
+ catch { }
465
+ }
466
+ printWelcome() {
467
+ const welcome = generateWelcome();
468
+ const lines = welcome.split('\n');
469
+ for (const line of lines) {
470
+ this.printLine(line);
471
+ }
472
+ this.printLine('');
473
+ if (configManager.getConfig().security.readOnlyMode) {
474
+ this.printWarning('Read-only mode active. File modifications will be blocked.');
475
+ }
476
+ if (this.approvalMode === 'yolo') {
477
+ this.printWarning('YOLO mode active. Agent will execute actions without confirmation.');
478
+ }
479
+ }
480
+ printHelp() {
481
+ const { ALL_COMMANDS } = require('./CommandPopup.js');
482
+ const w = Math.min(process.stdout.columns || 80, 72);
483
+ const top = `╔${'═'.repeat(w)}╗`;
484
+ const bottom = `╚${'═'.repeat(w)}╝`;
485
+ const lines = [top];
486
+ const title = ` YS Code Agent — Commands `;
487
+ const titlePad = Math.floor((w - title.length) / 2);
488
+ lines.push(`║${' '.repeat(titlePad)}${chalk.cyan(title)}${' '.repeat(w - titlePad - title.length)}║`);
489
+ lines.push(`╠${'═'.repeat(w)}╣`);
490
+ const categories = {};
491
+ for (const cmd of ALL_COMMANDS) {
492
+ if (!categories[cmd.category])
493
+ categories[cmd.category] = [];
494
+ categories[cmd.category].push(cmd);
495
+ }
496
+ let first = true;
497
+ for (const [cat, cmds] of Object.entries(categories)) {
498
+ if (!first)
499
+ lines.push(`║${' '.repeat(w)}║`);
500
+ first = false;
501
+ const icon = CATEGORY_ICONS[cat] || ' ';
502
+ lines.push(`║ ${icon} ${chalk.white(cat.toUpperCase())}${' '.repeat(Math.max(0, w - 5 - cat.length))}║`);
503
+ for (const cmd of cmds) {
504
+ const usage = cmd.usage || `/${cmd.command}`;
505
+ const cmdStr = chalk.yellow(usage);
506
+ const desc = chalk.gray(cmd.description);
507
+ const padding = ' '.repeat(Math.max(0, w - usage.length - cmd.description.length - 6));
508
+ lines.push(`║ ${cmdStr}${padding}${desc} ║`);
509
+ }
510
+ }
511
+ lines.push(`╠${'═'.repeat(w)}╣`);
512
+ lines.push(`║ ${chalk.gray('Keyboard Shortcuts:')}${' '.repeat(Math.max(0, w - 22))}║`);
513
+ const shortcuts = [
514
+ ['↑/↓', 'History navigation'],
515
+ ['Tab', 'Autocomplete commands'],
516
+ ['Ctrl+C', 'Cancel request'],
517
+ ['Ctrl+L', 'Clear screen'],
518
+ ['Ctrl+A', 'Line start'],
519
+ ['Ctrl+E', 'Line end'],
520
+ ['Ctrl+X', 'Open editor'],
521
+ ['Esc', 'Cancel / clear input'],
522
+ ];
523
+ for (const [key, desc] of shortcuts) {
524
+ const keyStr = chalk.cyan(key);
525
+ const descStr = chalk.gray(desc);
526
+ const padding = ' '.repeat(Math.max(0, w - key.length - desc.length - 6));
527
+ lines.push(`║ ${keyStr}${padding}${descStr} ║`);
528
+ }
529
+ lines.push(bottom);
530
+ for (const l of lines)
531
+ this.printLine(l);
532
+ }
533
+ printWarning(message) {
534
+ const w = Math.min(process.stdout.columns || 80, 60);
535
+ const top = `╔${'═'.repeat(w)}╗`;
536
+ const bottom = `╚${'═'.repeat(w)}╝`;
537
+ this.printLine('');
538
+ this.printLine(chalk.yellow(top));
539
+ const warnLine = ` ⚠ ${chalk.yellow(message)}`;
540
+ const pad = Math.max(0, w - warnLine.length);
541
+ this.printLine(`║${warnLine}${' '.repeat(pad)}║`);
542
+ this.printLine(chalk.yellow(bottom));
543
+ }
544
+ showPrompt() {
545
+ if (!this.running)
546
+ return;
547
+ const promptLine = this.buildPromptLine();
548
+ if (phoneConfig.isTermux) {
549
+ this.printLine(promptLine);
550
+ }
551
+ else {
552
+ this.renderScreen();
553
+ }
554
+ }
555
+ buildPromptLine() {
556
+ const statusIndicator = STATUS_COLORS[this.status](INDICATORS[this.status]);
557
+ const config = configManager.getConfig();
558
+ const model = config.model.model;
559
+ const modelShort = model.length > 18 ? model.slice(0, 16) + '…' : model;
560
+ let modeBadge = '';
561
+ if (this.agentMode === 'plan')
562
+ modeBadge = chalk.blue(' [plan]');
563
+ else if (this.agentMode === 'goal')
564
+ modeBadge = chalk.magenta(' [goal]');
565
+ else if (this.agentMode === 'arena')
566
+ modeBadge = chalk.yellow(' [arena]');
567
+ let approvalBadge = '';
568
+ if (this.approvalMode === 'safe')
569
+ approvalBadge = chalk.cyan(' [safe]');
570
+ else if (this.approvalMode === 'yolo')
571
+ approvalBadge = chalk.red(' [yolo]');
572
+ const promptStr = `${statusIndicator} ${chalk.cyan('ys')} ${chalk.yellow(`[${modelShort}]`)}${modeBadge}${approvalBadge} ${chalk.gray('›')} `;
573
+ const inputStr = this.inputBuffer || ' ';
574
+ const cursorChar = phoneConfig.isTermux ? '█' : '█';
575
+ const cursor = chalk.gray(cursorChar);
576
+ const displayedInput = inputStr.length > 0 ? inputStr : '';
577
+ let cursorLine = '';
578
+ if (this.cursorPos >= displayedInput.length) {
579
+ cursorLine = promptStr + displayedInput + cursor;
580
+ }
581
+ else {
582
+ const before = displayedInput.slice(0, this.cursorPos);
583
+ const after = displayedInput.slice(this.cursorPos);
584
+ cursorLine = promptStr + before + cursor + after;
585
+ }
586
+ return cursorLine + '\n' + chalk.gray(` 💡 / for commands | ↑↓ history | Tab complete`);
587
+ }
588
+ setOnInput(handler) {
589
+ this.onInput = handler;
590
+ }
591
+ setOnSpecialKey(handler) {
592
+ this.onSpecialKey = handler;
593
+ }
594
+ setStatus(status) {
595
+ this.status = status;
596
+ }
597
+ setApprovalMode(mode) {
598
+ this.approvalMode = mode;
599
+ }
600
+ setAgentMode(mode) {
601
+ this.agentMode = mode;
602
+ }
603
+ getApprovalMode() {
604
+ return this.approvalMode;
605
+ }
606
+ getAgentMode() {
607
+ return this.agentMode;
608
+ }
609
+ printLine(line) {
610
+ if (!process.stdout.isTTY) {
611
+ console.log(line);
612
+ return;
613
+ }
614
+ try {
615
+ const { cursorTo, clearLine } = require('readline');
616
+ cursorTo(process.stdout, 0);
617
+ clearLine(process.stdout, 1);
618
+ console.log(line);
619
+ }
620
+ catch {
621
+ console.log(line);
622
+ }
623
+ this.outputLines.push(line);
624
+ if (this.outputLines.length > this.maxOutputLines) {
625
+ this.outputLines.shift();
626
+ }
627
+ }
628
+ printAssistant(message) {
629
+ this.printLine('');
630
+ const formatted = chalk.green(message);
631
+ this.printLine(formatted);
632
+ }
633
+ printError(error) {
634
+ const w = Math.min(process.stdout.columns || 80, 56);
635
+ const top = `╔${'═'.repeat(w)}╗`;
636
+ const bottom = `╚${'═'.repeat(w)}╝`;
637
+ this.printLine('');
638
+ this.printLine(chalk.red(top));
639
+ this.printLine(`║ ${chalk.red('✗')} ${chalk.white(error)}${' '.repeat(Math.max(0, w - error.length - 7))}║`);
640
+ this.printLine(chalk.red(bottom));
641
+ }
642
+ printToolCall(toolName, args) {
643
+ const argsStr = Object.entries(args)
644
+ .slice(0, 3)
645
+ .map(([k, v]) => `${k}=${String(v).slice(0, 50)}`)
646
+ .join(', ');
647
+ this.printLine(chalk.gray(` ⚡ ${toolName}(${argsStr}${Object.keys(args).length > 3 ? ', ...' : ''})`));
648
+ }
649
+ printToolResult(result) {
650
+ if (result.success) {
651
+ this.printLine(chalk.gray(` ✓ ${chalk.green('success')}`));
652
+ }
653
+ else {
654
+ this.printLine(chalk.gray(` ✕ ${chalk.red(result.error || 'failed')}`));
655
+ }
656
+ }
657
+ showStatusBar(info) {
658
+ const statusColor = STATUS_COLORS[info.status];
659
+ const statusIcon = INDICATORS[info.status];
660
+ const truncated = info.task ? info.task.slice(0, 40) + (info.task.length > 40 ? '...' : '') : '';
661
+ const parts = [
662
+ `${statusColor(`${statusIcon} ${info.status}`)}`,
663
+ chalk.gray(`msgs:${info.messages}`),
664
+ chalk.gray(`tok:${info.tokens}`),
665
+ ];
666
+ if (info.provider)
667
+ parts.push(chalk.gray(`prov:${info.provider}`));
668
+ if (truncated)
669
+ parts.push(chalk.gray(`task:${truncated}`));
670
+ }
671
+ showShutdownScreen() {
672
+ const w = Math.min(process.stdout.columns || 80, 50);
673
+ const top = `╭${'─'.repeat(w)}╮`;
674
+ const bottom = `╰${'─'.repeat(w)}╯`;
675
+ console.log('');
676
+ console.log(chalk.cyan(top));
677
+ console.log(`│${' '.repeat(w)}│`);
678
+ const titleLine = ' ◆ YS Code Agent — Session Complete ';
679
+ const titlePad = Math.floor((w - titleLine.length) / 2);
680
+ console.log(`│${' '.repeat(titlePad)}${chalk.cyan(titleLine)}${' '.repeat(w - titlePad - titleLine.length)}│`);
681
+ console.log(`│${' '.repeat(w)}│`);
682
+ const { sessionManager } = require('../session/index.js');
683
+ const session = sessionManager.getCurrentSession();
684
+ if (session) {
685
+ const sessionId = session.id.slice(0, 8);
686
+ const duration = formatDuration(Date.now() - session.createdAt);
687
+ const msgCount = session.state.messages.length;
688
+ console.log(`│ ${chalk.white('Session')}: ${chalk.yellow(sessionId.padEnd(w - 13))}│`);
689
+ console.log(`│ ${chalk.white('Duration')}: ${chalk.yellow(duration.padEnd(w - 14))}│`);
690
+ console.log(`│ ${chalk.white('Messages')}: ${chalk.yellow(String(msgCount).padEnd(w - 14))}│`);
691
+ }
692
+ console.log(`│${' '.repeat(w)}│`);
693
+ console.log(`│ ${chalk.gray('Session saved. Resume with:')} ${chalk.yellow('ys --resume <session>')}${' '.repeat(Math.max(0, w - 43))}│`);
694
+ console.log(`│${' '.repeat(w)}│`);
695
+ console.log(chalk.cyan(bottom));
696
+ console.log('');
697
+ }
698
+ destroy() {
699
+ if (this.stdinRaw && process.stdin.isTTY) {
700
+ try {
701
+ process.stdin.setRawMode?.(false);
702
+ }
703
+ catch { }
704
+ }
705
+ process.stdin.removeAllListeners('data');
706
+ }
707
+ getOutputLineCount() {
708
+ return this.outputLines.length;
709
+ }
710
+ }
711
+ function formatDuration(ms) {
712
+ if (ms < 1000)
713
+ return `${ms}ms`;
714
+ if (ms < 60000)
715
+ return `${(ms / 1000).toFixed(1)}s`;
716
+ const m = Math.floor(ms / 60000);
717
+ const s = Math.floor((ms % 60000) / 1000);
718
+ return `${m}m ${s}s`;
719
+ }
720
+ function cursorToSync(stream, x, y) {
721
+ try {
722
+ const { cursorTo } = require('readline');
723
+ cursorTo(stream, x, y);
724
+ }
725
+ catch { }
726
+ }
727
+ export const tui = new TUI();
728
+ //# sourceMappingURL=index.js.map