sema-core 1.0.2

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 (411) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/constants/config.d.ts +20 -0
  4. package/dist/constants/config.d.ts.map +1 -0
  5. package/dist/constants/config.js +31 -0
  6. package/dist/constants/config.js.map +1 -0
  7. package/dist/constants/message.d.ts +10 -0
  8. package/dist/constants/message.d.ts.map +1 -0
  9. package/dist/constants/message.js +25 -0
  10. package/dist/constants/message.js.map +1 -0
  11. package/dist/constants/product.d.ts +5 -0
  12. package/dist/constants/product.d.ts.map +1 -0
  13. package/dist/constants/product.js +8 -0
  14. package/dist/constants/product.js.map +1 -0
  15. package/dist/core/Conversation.d.ts +16 -0
  16. package/dist/core/Conversation.d.ts.map +1 -0
  17. package/dist/core/Conversation.js +226 -0
  18. package/dist/core/Conversation.js.map +1 -0
  19. package/dist/core/RunTools.d.ts +11 -0
  20. package/dist/core/RunTools.d.ts.map +1 -0
  21. package/dist/core/RunTools.js +244 -0
  22. package/dist/core/RunTools.js.map +1 -0
  23. package/dist/core/SemaCore.d.ts +49 -0
  24. package/dist/core/SemaCore.d.ts.map +1 -0
  25. package/dist/core/SemaCore.js +94 -0
  26. package/dist/core/SemaCore.js.map +1 -0
  27. package/dist/core/SemaEngine.d.ts +54 -0
  28. package/dist/core/SemaEngine.d.ts.map +1 -0
  29. package/dist/core/SemaEngine.js +335 -0
  30. package/dist/core/SemaEngine.js.map +1 -0
  31. package/dist/events/EventSystem.d.ts +42 -0
  32. package/dist/events/EventSystem.d.ts.map +1 -0
  33. package/dist/events/EventSystem.js +134 -0
  34. package/dist/events/EventSystem.js.map +1 -0
  35. package/dist/events/types.d.ts +300 -0
  36. package/dist/events/types.d.ts.map +1 -0
  37. package/dist/events/types.js +4 -0
  38. package/dist/events/types.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +6 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/manager/ConfManager.d.ts +76 -0
  44. package/dist/manager/ConfManager.d.ts.map +1 -0
  45. package/dist/manager/ConfManager.js +329 -0
  46. package/dist/manager/ConfManager.js.map +1 -0
  47. package/dist/manager/ModelManager.d.ts +51 -0
  48. package/dist/manager/ModelManager.d.ts.map +1 -0
  49. package/dist/manager/ModelManager.js +291 -0
  50. package/dist/manager/ModelManager.js.map +1 -0
  51. package/dist/manager/PermissionManager.d.ts +16 -0
  52. package/dist/manager/PermissionManager.d.ts.map +1 -0
  53. package/dist/manager/PermissionManager.js +308 -0
  54. package/dist/manager/PermissionManager.js.map +1 -0
  55. package/dist/manager/StateManager.d.ts +164 -0
  56. package/dist/manager/StateManager.d.ts.map +1 -0
  57. package/dist/manager/StateManager.js +357 -0
  58. package/dist/manager/StateManager.js.map +1 -0
  59. package/dist/services/agents/agentsManager.d.ts +112 -0
  60. package/dist/services/agents/agentsManager.d.ts.map +1 -0
  61. package/dist/services/agents/agentsManager.js +394 -0
  62. package/dist/services/agents/agentsManager.js.map +1 -0
  63. package/dist/services/agents/defaultBuiltInAgentsConfs.d.ts +3 -0
  64. package/dist/services/agents/defaultBuiltInAgentsConfs.d.ts.map +1 -0
  65. package/dist/services/agents/defaultBuiltInAgentsConfs.js +102 -0
  66. package/dist/services/agents/defaultBuiltInAgentsConfs.js.map +1 -0
  67. package/dist/services/agents/genSystemPrompt.d.ts +23 -0
  68. package/dist/services/agents/genSystemPrompt.d.ts.map +1 -0
  69. package/dist/services/agents/genSystemPrompt.js +189 -0
  70. package/dist/services/agents/genSystemPrompt.js.map +1 -0
  71. package/dist/services/agents/prompt.d.ts +12 -0
  72. package/dist/services/agents/prompt.d.ts.map +1 -0
  73. package/dist/services/agents/prompt.js +162 -0
  74. package/dist/services/agents/prompt.js.map +1 -0
  75. package/dist/services/api/adapt/anthropic.d.ts +10 -0
  76. package/dist/services/api/adapt/anthropic.d.ts.map +1 -0
  77. package/dist/services/api/adapt/anthropic.js +233 -0
  78. package/dist/services/api/adapt/anthropic.js.map +1 -0
  79. package/dist/services/api/adapt/openai.d.ts +8 -0
  80. package/dist/services/api/adapt/openai.d.ts.map +1 -0
  81. package/dist/services/api/adapt/openai.js +412 -0
  82. package/dist/services/api/adapt/openai.js.map +1 -0
  83. package/dist/services/api/adapt/util.d.ts +7 -0
  84. package/dist/services/api/adapt/util.d.ts.map +1 -0
  85. package/dist/services/api/adapt/util.js +24 -0
  86. package/dist/services/api/adapt/util.js.map +1 -0
  87. package/dist/services/api/apiUtil.d.ts +10 -0
  88. package/dist/services/api/apiUtil.d.ts.map +1 -0
  89. package/dist/services/api/apiUtil.js +256 -0
  90. package/dist/services/api/apiUtil.js.map +1 -0
  91. package/dist/services/api/cache.d.ts +11 -0
  92. package/dist/services/api/cache.d.ts.map +1 -0
  93. package/dist/services/api/cache.js +128 -0
  94. package/dist/services/api/cache.js.map +1 -0
  95. package/dist/services/api/queryLLM.d.ts +18 -0
  96. package/dist/services/api/queryLLM.d.ts.map +1 -0
  97. package/dist/services/api/queryLLM.js +147 -0
  98. package/dist/services/api/queryLLM.js.map +1 -0
  99. package/dist/services/command/runCommand.d.ts +18 -0
  100. package/dist/services/command/runCommand.d.ts.map +1 -0
  101. package/dist/services/command/runCommand.js +149 -0
  102. package/dist/services/command/runCommand.js.map +1 -0
  103. package/dist/services/mcp/MCPClient.d.ts +35 -0
  104. package/dist/services/mcp/MCPClient.d.ts.map +1 -0
  105. package/dist/services/mcp/MCPClient.js +166 -0
  106. package/dist/services/mcp/MCPClient.js.map +1 -0
  107. package/dist/services/mcp/MCPManager.d.ts +140 -0
  108. package/dist/services/mcp/MCPManager.d.ts.map +1 -0
  109. package/dist/services/mcp/MCPManager.js +650 -0
  110. package/dist/services/mcp/MCPManager.js.map +1 -0
  111. package/dist/services/mcp/MCPToolAdapter.d.ts +22 -0
  112. package/dist/services/mcp/MCPToolAdapter.d.ts.map +1 -0
  113. package/dist/services/mcp/MCPToolAdapter.js +177 -0
  114. package/dist/services/mcp/MCPToolAdapter.js.map +1 -0
  115. package/dist/services/plugins/customCommands.d.ts +29 -0
  116. package/dist/services/plugins/customCommands.d.ts.map +1 -0
  117. package/dist/services/plugins/customCommands.js +227 -0
  118. package/dist/services/plugins/customCommands.js.map +1 -0
  119. package/dist/services/skill/skillLoader.d.ts +17 -0
  120. package/dist/services/skill/skillLoader.d.ts.map +1 -0
  121. package/dist/services/skill/skillLoader.js +122 -0
  122. package/dist/services/skill/skillLoader.js.map +1 -0
  123. package/dist/services/skill/skillParser.d.ts +15 -0
  124. package/dist/services/skill/skillParser.d.ts.map +1 -0
  125. package/dist/services/skill/skillParser.js +66 -0
  126. package/dist/services/skill/skillParser.js.map +1 -0
  127. package/dist/services/skill/skillRegistry.d.ts +34 -0
  128. package/dist/services/skill/skillRegistry.d.ts.map +1 -0
  129. package/dist/services/skill/skillRegistry.js +98 -0
  130. package/dist/services/skill/skillRegistry.js.map +1 -0
  131. package/dist/tools/AskUserQuestion/AskUserQuestion.d.ts +179 -0
  132. package/dist/tools/AskUserQuestion/AskUserQuestion.d.ts.map +1 -0
  133. package/dist/tools/AskUserQuestion/AskUserQuestion.js +165 -0
  134. package/dist/tools/AskUserQuestion/AskUserQuestion.js.map +1 -0
  135. package/dist/tools/AskUserQuestion/prompt.d.ts +3 -0
  136. package/dist/tools/AskUserQuestion/prompt.d.ts.map +1 -0
  137. package/dist/tools/AskUserQuestion/prompt.js +17 -0
  138. package/dist/tools/AskUserQuestion/prompt.js.map +1 -0
  139. package/dist/tools/Bash/Bash.d.ts +75 -0
  140. package/dist/tools/Bash/Bash.d.ts.map +1 -0
  141. package/dist/tools/Bash/Bash.js +200 -0
  142. package/dist/tools/Bash/Bash.js.map +1 -0
  143. package/dist/tools/Bash/prompt.d.ts +8 -0
  144. package/dist/tools/Bash/prompt.d.ts.map +1 -0
  145. package/dist/tools/Bash/prompt.js +167 -0
  146. package/dist/tools/Bash/prompt.js.map +1 -0
  147. package/dist/tools/Bash/utils.d.ts +5 -0
  148. package/dist/tools/Bash/utils.d.ts.map +1 -0
  149. package/dist/tools/Bash/utils.js +21 -0
  150. package/dist/tools/Bash/utils.js.map +1 -0
  151. package/dist/tools/Edit/Edit.d.ts +110 -0
  152. package/dist/tools/Edit/Edit.d.ts.map +1 -0
  153. package/dist/tools/Edit/Edit.js +213 -0
  154. package/dist/tools/Edit/Edit.js.map +1 -0
  155. package/dist/tools/Edit/prompt.d.ts +3 -0
  156. package/dist/tools/Edit/prompt.d.ts.map +1 -0
  157. package/dist/tools/Edit/prompt.js +15 -0
  158. package/dist/tools/Edit/prompt.js.map +1 -0
  159. package/dist/tools/Edit/utils.d.ts +10 -0
  160. package/dist/tools/Edit/utils.d.ts.map +1 -0
  161. package/dist/tools/Edit/utils.js +51 -0
  162. package/dist/tools/Edit/utils.js.map +1 -0
  163. package/dist/tools/ExitPlanMode/ExitPlanMode.d.ts +42 -0
  164. package/dist/tools/ExitPlanMode/ExitPlanMode.d.ts.map +1 -0
  165. package/dist/tools/ExitPlanMode/ExitPlanMode.js +157 -0
  166. package/dist/tools/ExitPlanMode/ExitPlanMode.js.map +1 -0
  167. package/dist/tools/ExitPlanMode/prompt.d.ts +3 -0
  168. package/dist/tools/ExitPlanMode/prompt.d.ts.map +1 -0
  169. package/dist/tools/ExitPlanMode/prompt.js +28 -0
  170. package/dist/tools/ExitPlanMode/prompt.js.map +1 -0
  171. package/dist/tools/Glob/Glob.d.ts +44 -0
  172. package/dist/tools/Glob/Glob.d.ts.map +1 -0
  173. package/dist/tools/Glob/Glob.js +113 -0
  174. package/dist/tools/Glob/Glob.js.map +1 -0
  175. package/dist/tools/Glob/prompt.d.ts +3 -0
  176. package/dist/tools/Glob/prompt.d.ts.map +1 -0
  177. package/dist/tools/Glob/prompt.js +11 -0
  178. package/dist/tools/Glob/prompt.js.map +1 -0
  179. package/dist/tools/Grep/Grep.d.ts +106 -0
  180. package/dist/tools/Grep/Grep.d.ts.map +1 -0
  181. package/dist/tools/Grep/Grep.js +301 -0
  182. package/dist/tools/Grep/Grep.js.map +1 -0
  183. package/dist/tools/Grep/prompt.d.ts +3 -0
  184. package/dist/tools/Grep/prompt.d.ts.map +1 -0
  185. package/dist/tools/Grep/prompt.js +17 -0
  186. package/dist/tools/Grep/prompt.js.map +1 -0
  187. package/dist/tools/NotebookEdit/NotebookEdit.d.ts +98 -0
  188. package/dist/tools/NotebookEdit/NotebookEdit.d.ts.map +1 -0
  189. package/dist/tools/NotebookEdit/NotebookEdit.js +228 -0
  190. package/dist/tools/NotebookEdit/NotebookEdit.js.map +1 -0
  191. package/dist/tools/NotebookEdit/prompt.d.ts +3 -0
  192. package/dist/tools/NotebookEdit/prompt.d.ts.map +1 -0
  193. package/dist/tools/NotebookEdit/prompt.js +6 -0
  194. package/dist/tools/NotebookEdit/prompt.js.map +1 -0
  195. package/dist/tools/Read/Read.d.ts +107 -0
  196. package/dist/tools/Read/Read.d.ts.map +1 -0
  197. package/dist/tools/Read/Read.js +175 -0
  198. package/dist/tools/Read/Read.js.map +1 -0
  199. package/dist/tools/Read/prompt.d.ts +4 -0
  200. package/dist/tools/Read/prompt.d.ts.map +1 -0
  201. package/dist/tools/Read/prompt.js +21 -0
  202. package/dist/tools/Read/prompt.js.map +1 -0
  203. package/dist/tools/Skill/Skill.d.ts +62 -0
  204. package/dist/tools/Skill/Skill.d.ts.map +1 -0
  205. package/dist/tools/Skill/Skill.js +142 -0
  206. package/dist/tools/Skill/Skill.js.map +1 -0
  207. package/dist/tools/Skill/prompt.d.ts +3 -0
  208. package/dist/tools/Skill/prompt.d.ts.map +1 -0
  209. package/dist/tools/Skill/prompt.js +58 -0
  210. package/dist/tools/Skill/prompt.js.map +1 -0
  211. package/dist/tools/Task/Task.d.ts +59 -0
  212. package/dist/tools/Task/Task.d.ts.map +1 -0
  213. package/dist/tools/Task/Task.js +213 -0
  214. package/dist/tools/Task/Task.js.map +1 -0
  215. package/dist/tools/Task/prompt.d.ts +6 -0
  216. package/dist/tools/Task/prompt.d.ts.map +1 -0
  217. package/dist/tools/Task/prompt.js +75 -0
  218. package/dist/tools/Task/prompt.js.map +1 -0
  219. package/dist/tools/TodoWrite/TodoWrite.d.ts +92 -0
  220. package/dist/tools/TodoWrite/TodoWrite.d.ts.map +1 -0
  221. package/dist/tools/TodoWrite/TodoWrite.js +101 -0
  222. package/dist/tools/TodoWrite/TodoWrite.js.map +1 -0
  223. package/dist/tools/TodoWrite/prompt.d.ts +3 -0
  224. package/dist/tools/TodoWrite/prompt.d.ts.map +1 -0
  225. package/dist/tools/TodoWrite/prompt.js +187 -0
  226. package/dist/tools/TodoWrite/prompt.js.map +1 -0
  227. package/dist/tools/Write/Write.d.ts +77 -0
  228. package/dist/tools/Write/Write.d.ts.map +1 -0
  229. package/dist/tools/Write/Write.js +189 -0
  230. package/dist/tools/Write/Write.js.map +1 -0
  231. package/dist/tools/Write/prompt.d.ts +3 -0
  232. package/dist/tools/Write/prompt.d.ts.map +1 -0
  233. package/dist/tools/Write/prompt.js +13 -0
  234. package/dist/tools/Write/prompt.js.map +1 -0
  235. package/dist/tools/base/Tool.d.ts +36 -0
  236. package/dist/tools/base/Tool.d.ts.map +1 -0
  237. package/dist/tools/base/Tool.js +3 -0
  238. package/dist/tools/base/Tool.js.map +1 -0
  239. package/dist/tools/base/tools.d.ts +9 -0
  240. package/dist/tools/base/tools.d.ts.map +1 -0
  241. package/dist/tools/base/tools.js +105 -0
  242. package/dist/tools/base/tools.js.map +1 -0
  243. package/dist/types/agent.d.ts +30 -0
  244. package/dist/types/agent.d.ts.map +1 -0
  245. package/dist/types/agent.js +3 -0
  246. package/dist/types/agent.js.map +1 -0
  247. package/dist/types/command.d.ts +44 -0
  248. package/dist/types/command.d.ts.map +1 -0
  249. package/dist/types/command.js +6 -0
  250. package/dist/types/command.js.map +1 -0
  251. package/dist/types/config.d.ts +14 -0
  252. package/dist/types/config.d.ts.map +1 -0
  253. package/dist/types/config.js +3 -0
  254. package/dist/types/config.js.map +1 -0
  255. package/dist/types/errors.d.ts +18 -0
  256. package/dist/types/errors.d.ts.map +1 -0
  257. package/dist/types/errors.js +33 -0
  258. package/dist/types/errors.js.map +1 -0
  259. package/dist/types/index.d.ts +91 -0
  260. package/dist/types/index.d.ts.map +1 -0
  261. package/dist/types/index.js +18 -0
  262. package/dist/types/index.js.map +1 -0
  263. package/dist/types/mcp.d.ts +127 -0
  264. package/dist/types/mcp.d.ts.map +1 -0
  265. package/dist/types/mcp.js +6 -0
  266. package/dist/types/mcp.js.map +1 -0
  267. package/dist/types/message.d.ts +31 -0
  268. package/dist/types/message.d.ts.map +1 -0
  269. package/dist/types/message.js +3 -0
  270. package/dist/types/message.js.map +1 -0
  271. package/dist/types/model.d.ts +21 -0
  272. package/dist/types/model.d.ts.map +1 -0
  273. package/dist/types/model.js +3 -0
  274. package/dist/types/model.js.map +1 -0
  275. package/dist/types/notebook.d.ts +57 -0
  276. package/dist/types/notebook.d.ts.map +1 -0
  277. package/dist/types/notebook.js +3 -0
  278. package/dist/types/notebook.js.map +1 -0
  279. package/dist/types/skill.d.ts +34 -0
  280. package/dist/types/skill.d.ts.map +1 -0
  281. package/dist/types/skill.js +8 -0
  282. package/dist/types/skill.js.map +1 -0
  283. package/dist/types/uuid.d.ts +2 -0
  284. package/dist/types/uuid.d.ts.map +1 -0
  285. package/dist/types/uuid.js +3 -0
  286. package/dist/types/uuid.js.map +1 -0
  287. package/dist/util/adapter.d.ts +11 -0
  288. package/dist/util/adapter.d.ts.map +1 -0
  289. package/dist/util/adapter.js +75 -0
  290. package/dist/util/adapter.js.map +1 -0
  291. package/dist/util/agentStats.d.ts +11 -0
  292. package/dist/util/agentStats.d.ts.map +1 -0
  293. package/dist/util/agentStats.js +60 -0
  294. package/dist/util/agentStats.js.map +1 -0
  295. package/dist/util/cacheLLM.d.ts +47 -0
  296. package/dist/util/cacheLLM.d.ts.map +1 -0
  297. package/dist/util/cacheLLM.js +154 -0
  298. package/dist/util/cacheLLM.js.map +1 -0
  299. package/dist/util/commands.d.ts +16 -0
  300. package/dist/util/commands.d.ts.map +1 -0
  301. package/dist/util/commands.js +216 -0
  302. package/dist/util/commands.js.map +1 -0
  303. package/dist/util/compact.d.ts +25 -0
  304. package/dist/util/compact.d.ts.map +1 -0
  305. package/dist/util/compact.js +451 -0
  306. package/dist/util/compact.js.map +1 -0
  307. package/dist/util/cwd.d.ts +44 -0
  308. package/dist/util/cwd.d.ts.map +1 -0
  309. package/dist/util/cwd.js +84 -0
  310. package/dist/util/cwd.js.map +1 -0
  311. package/dist/util/diff.d.ts +10 -0
  312. package/dist/util/diff.d.ts.map +1 -0
  313. package/dist/util/diff.js +127 -0
  314. package/dist/util/diff.js.map +1 -0
  315. package/dist/util/directory.d.ts +37 -0
  316. package/dist/util/directory.d.ts.map +1 -0
  317. package/dist/util/directory.js +137 -0
  318. package/dist/util/directory.js.map +1 -0
  319. package/dist/util/env.d.ts +5 -0
  320. package/dist/util/env.d.ts.map +1 -0
  321. package/dist/util/env.js +39 -0
  322. package/dist/util/env.js.map +1 -0
  323. package/dist/util/exec.d.ts +6 -0
  324. package/dist/util/exec.d.ts.map +1 -0
  325. package/dist/util/exec.js +43 -0
  326. package/dist/util/exec.js.map +1 -0
  327. package/dist/util/file.d.ts +61 -0
  328. package/dist/util/file.d.ts.map +1 -0
  329. package/dist/util/file.js +365 -0
  330. package/dist/util/file.js.map +1 -0
  331. package/dist/util/filePermission.d.ts +14 -0
  332. package/dist/util/filePermission.d.ts.map +1 -0
  333. package/dist/util/filePermission.js +45 -0
  334. package/dist/util/filePermission.js.map +1 -0
  335. package/dist/util/fileReference.d.ts +40 -0
  336. package/dist/util/fileReference.d.ts.map +1 -0
  337. package/dist/util/fileReference.js +343 -0
  338. package/dist/util/fileReference.js.map +1 -0
  339. package/dist/util/format.d.ts +9 -0
  340. package/dist/util/format.d.ts.map +1 -0
  341. package/dist/util/format.js +61 -0
  342. package/dist/util/format.js.map +1 -0
  343. package/dist/util/frontmatter.d.ts +35 -0
  344. package/dist/util/frontmatter.d.ts.map +1 -0
  345. package/dist/util/frontmatter.js +119 -0
  346. package/dist/util/frontmatter.js.map +1 -0
  347. package/dist/util/git.d.ts +4 -0
  348. package/dist/util/git.d.ts.map +1 -0
  349. package/dist/util/git.js +55 -0
  350. package/dist/util/git.js.map +1 -0
  351. package/dist/util/history.d.ts +27 -0
  352. package/dist/util/history.d.ts.map +1 -0
  353. package/dist/util/history.js +248 -0
  354. package/dist/util/history.js.map +1 -0
  355. package/dist/util/log.d.ts +23 -0
  356. package/dist/util/log.d.ts.map +1 -0
  357. package/dist/util/log.js +246 -0
  358. package/dist/util/log.js.map +1 -0
  359. package/dist/util/logLLM.d.ts +20 -0
  360. package/dist/util/logLLM.d.ts.map +1 -0
  361. package/dist/util/logLLM.js +414 -0
  362. package/dist/util/logLLM.js.map +1 -0
  363. package/dist/util/message.d.ts +12 -0
  364. package/dist/util/message.d.ts.map +1 -0
  365. package/dist/util/message.js +156 -0
  366. package/dist/util/message.js.map +1 -0
  367. package/dist/util/model.d.ts +22 -0
  368. package/dist/util/model.d.ts.map +1 -0
  369. package/dist/util/model.js +61 -0
  370. package/dist/util/model.js.map +1 -0
  371. package/dist/util/notebook.d.ts +14 -0
  372. package/dist/util/notebook.d.ts.map +1 -0
  373. package/dist/util/notebook.js +104 -0
  374. package/dist/util/notebook.js.map +1 -0
  375. package/dist/util/ripgrep.d.ts +3 -0
  376. package/dist/util/ripgrep.d.ts.map +1 -0
  377. package/dist/util/ripgrep.js +187 -0
  378. package/dist/util/ripgrep.js.map +1 -0
  379. package/dist/util/rules.d.ts +6 -0
  380. package/dist/util/rules.d.ts.map +1 -0
  381. package/dist/util/rules.js +111 -0
  382. package/dist/util/rules.js.map +1 -0
  383. package/dist/util/savePath.d.ts +73 -0
  384. package/dist/util/savePath.d.ts.map +1 -0
  385. package/dist/util/savePath.js +189 -0
  386. package/dist/util/savePath.js.map +1 -0
  387. package/dist/util/secureFile.d.ts +136 -0
  388. package/dist/util/secureFile.d.ts.map +1 -0
  389. package/dist/util/secureFile.js +496 -0
  390. package/dist/util/secureFile.js.map +1 -0
  391. package/dist/util/session.d.ts +37 -0
  392. package/dist/util/session.d.ts.map +1 -0
  393. package/dist/util/session.js +120 -0
  394. package/dist/util/session.js.map +1 -0
  395. package/dist/util/shell.d.ts +40 -0
  396. package/dist/util/shell.d.ts.map +1 -0
  397. package/dist/util/shell.js +876 -0
  398. package/dist/util/shell.js.map +1 -0
  399. package/dist/util/time.d.ts +24 -0
  400. package/dist/util/time.d.ts.map +1 -0
  401. package/dist/util/time.js +53 -0
  402. package/dist/util/time.js.map +1 -0
  403. package/dist/util/tokens.d.ts +9 -0
  404. package/dist/util/tokens.d.ts.map +1 -0
  405. package/dist/util/tokens.js +79 -0
  406. package/dist/util/tokens.js.map +1 -0
  407. package/dist/util/topic.d.ts +9 -0
  408. package/dist/util/topic.d.ts.map +1 -0
  409. package/dist/util/topic.js +52 -0
  410. package/dist/util/topic.js.map +1 -0
  411. package/package.json +83 -0
@@ -0,0 +1,876 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.PersistentShell = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const fs_1 = require("fs");
42
+ const shell_quote_1 = __importDefault(require("shell-quote"));
43
+ const child_process_1 = require("child_process");
44
+ const path_1 = require("path");
45
+ const os = __importStar(require("os"));
46
+ const crypto = __importStar(require("crypto"));
47
+ const log_1 = require("./log");
48
+ // 临时文件前缀
49
+ const TEMPFILE_PREFIX = os.tmpdir() + `sema-`;
50
+ // 默认超时时间(30分钟)
51
+ const DEFAULT_TIMEOUT = 30 * 60 * 1000;
52
+ // SIGTERM信号的标准退出码
53
+ const SIGTERM_CODE = 143;
54
+ // 文件后缀定义
55
+ const FILE_SUFFIXES = {
56
+ STATUS: '-status', // 状态文件后缀
57
+ STDOUT: '-stdout', // 标准输出文件后缀
58
+ STDERR: '-stderr', // 标准错误文件后缀
59
+ CWD: '-cwd', // 当前工作目录文件后缀
60
+ };
61
+ // Shell配置文件映射
62
+ const SHELL_CONFIGS = {
63
+ '/bin/bash': '.bashrc',
64
+ '/bin/zsh': '.zshrc',
65
+ };
66
+ // 为Bash转义字符串
67
+ function quoteForBash(str) {
68
+ return `'${str.replace(/'/g, "'\\''")}'`;
69
+ }
70
+ // 将路径转换为Bash可识别的格式
71
+ function toBashPath(pathStr, type) {
72
+ // 已经是POSIX绝对路径
73
+ if (pathStr.startsWith('/'))
74
+ return pathStr;
75
+ if (type === 'posix')
76
+ return pathStr;
77
+ // 规范化反斜杠
78
+ const normalized = pathStr.replace(/\\/g, '/').replace(/\\\\/g, '/');
79
+ const driveMatch = /^[A-Za-z]:/.exec(normalized);
80
+ if (driveMatch) {
81
+ const drive = normalized[0].toLowerCase();
82
+ const rest = normalized.slice(2);
83
+ if (type === 'msys') {
84
+ return `/` + drive + (rest.startsWith('/') ? rest : `/${rest}`);
85
+ }
86
+ // wsl格式转换
87
+ return `/mnt/` + drive + (rest.startsWith('/') ? rest : `/${rest}`);
88
+ }
89
+ // 相对路径:只转换斜杠
90
+ return normalized;
91
+ }
92
+ // 检查文件是否存在
93
+ function fileExists(p) {
94
+ return !!p && (0, fs_1.existsSync)(p);
95
+ }
96
+ // 跨平台的PATH环境变量分割器
97
+ function splitPathEntries(pathEnv, platform) {
98
+ if (!pathEnv)
99
+ return [];
100
+ // POSIX系统使用':'作为分隔符
101
+ if (platform !== 'win32') {
102
+ return pathEnv
103
+ .split(':')
104
+ .map(s => s.trim().replace(/^"|"$/g, ''))
105
+ .filter(Boolean);
106
+ }
107
+ // Windows系统:主要使用';',但某些环境可能使用':'
108
+ // 注意不要分割驱动器字母如'C:\\'或'D:foo\\bar'
109
+ const entries = [];
110
+ let current = '';
111
+ const pushCurrent = () => {
112
+ const cleaned = current.trim().replace(/^"|"$/g, '');
113
+ if (cleaned)
114
+ entries.push(cleaned);
115
+ current = '';
116
+ };
117
+ for (let i = 0; i < pathEnv.length; i++) {
118
+ const ch = pathEnv[i];
119
+ if (ch === ';') {
120
+ pushCurrent();
121
+ continue;
122
+ }
123
+ if (ch === ':') {
124
+ const segmentLength = current.length;
125
+ const firstChar = current[0];
126
+ const isDriveLetterPrefix = segmentLength === 1 && /[A-Za-z]/.test(firstChar || '');
127
+ // 只有当不是驱动器字母后的冒号时才作为分隔符处理
128
+ if (!isDriveLetterPrefix) {
129
+ pushCurrent();
130
+ continue;
131
+ }
132
+ }
133
+ current += ch;
134
+ }
135
+ // 处理最后一个段
136
+ pushCurrent();
137
+ return entries;
138
+ }
139
+ // 测试 bash 是否可用
140
+ function testBashAvailability(bashPath, type = 'msys') {
141
+ try {
142
+ (0, log_1.logInfo)(`测试 bash 可用性: ${bashPath}`);
143
+ let testCommand;
144
+ if (type === 'wsl') {
145
+ // WSL bash 测试
146
+ testCommand = `${bashPath} -e bash -c "echo SEMA_TEST_OK"`;
147
+ }
148
+ else {
149
+ // 普通 bash 测试
150
+ testCommand = `"${bashPath}" -c "echo SEMA_TEST_OK"`;
151
+ }
152
+ const result = (0, child_process_1.execSync)(testCommand, {
153
+ stdio: 'pipe',
154
+ timeout: 3000,
155
+ encoding: 'utf8'
156
+ });
157
+ const output = result.toString().trim();
158
+ if (output.includes('SEMA_TEST_OK')) {
159
+ (0, log_1.logInfo)(`✅ bash 测试通过: ${bashPath}`);
160
+ return true;
161
+ }
162
+ else {
163
+ (0, log_1.logWarn)(`❌ bash 测试失败,输出不符合预期: ${bashPath}, 输出: ${output}`);
164
+ return false;
165
+ }
166
+ }
167
+ catch (error) {
168
+ (0, log_1.logWarn)(`❌ bash 测试失败: ${bashPath}, 错误: ${error}`);
169
+ return false;
170
+ }
171
+ }
172
+ // 检测可用的Shell
173
+ function detectShell() {
174
+ const isWin = process.platform === 'win32';
175
+ if (!isWin) {
176
+ const bin = process.env.SHELL || '/bin/bash';
177
+ return { bin, args: ['-l'], type: 'posix' };
178
+ }
179
+ (0, log_1.logInfo)('开始检测 Windows Shell 环境...');
180
+ // Windows 平台 Shell 检测逻辑 - 优化后的检测顺序
181
+ // 1) 显式环境变量优先级最高 (支持 SEMA_BASH 环境变量)
182
+ if (process.env.SEMA_BASH && (0, fs_1.existsSync)(process.env.SEMA_BASH)) {
183
+ if (testBashAvailability(process.env.SEMA_BASH)) {
184
+ (0, log_1.logInfo)(`使用 SEMA_BASH 环境变量指定的 bash: ${process.env.SEMA_BASH}`);
185
+ return { bin: process.env.SEMA_BASH, args: ['-l'], type: 'msys' };
186
+ }
187
+ else {
188
+ (0, log_1.logWarn)(`SEMA_BASH 指定的 bash 测试失败: ${process.env.SEMA_BASH}`);
189
+ }
190
+ }
191
+ // 1.1) 如果SHELL环境变量指向存在的bash.exe,则测试并使用它
192
+ if (process.env.SHELL && /bash\.exe$/i.test(process.env.SHELL) && (0, fs_1.existsSync)(process.env.SHELL)) {
193
+ // 对 System32 bash 进行特殊测试
194
+ const isSystem32Bash = process.env.SHELL.toLowerCase().includes('system32');
195
+ const testType = isSystem32Bash ? 'wsl' : 'msys';
196
+ if (testBashAvailability(process.env.SHELL, testType)) {
197
+ (0, log_1.logInfo)(`使用 SHELL 环境变量指定的 bash: ${process.env.SHELL}`);
198
+ return { bin: process.env.SHELL, args: ['-l'], type: isSystem32Bash ? 'wsl' : 'msys' };
199
+ }
200
+ else {
201
+ (0, log_1.logWarn)(`SHELL 环境变量指定的 bash 测试失败: ${process.env.SHELL}`);
202
+ }
203
+ }
204
+ // 2) 优先在PATH中搜索bash.exe (提前到这里,覆盖更多安装方式)
205
+ (0, log_1.logInfo)('在 PATH 中搜索 bash.exe...');
206
+ // 在Windows上尝试多种PATH环境变量形式
207
+ let pathEnv = process.env.PATH || process.env.Path || process.env.path || '';
208
+ // 如果还是空的,尝试遍历所有环境变量找到PATH
209
+ if (!pathEnv) {
210
+ for (const [key, value] of Object.entries(process.env)) {
211
+ if (key.toLowerCase() === 'path' && value) {
212
+ pathEnv = value;
213
+ (0, log_1.logInfo)(`找到 PATH 环境变量 (${key}): ${value.substring(0, 100)}...`);
214
+ break;
215
+ }
216
+ }
217
+ }
218
+ // 在Windows上,如果PATH看起来不完整,尝试从系统重新获取
219
+ if (process.platform === 'win32' && pathEnv && pathEnv.length < 500) {
220
+ try {
221
+ (0, log_1.logInfo)('PATH看起来不完整,尝试从PowerShell重新获取...');
222
+ const fullPath = (0, child_process_1.execSync)('powershell.exe -Command "$env:PATH"', {
223
+ encoding: 'utf8',
224
+ timeout: 5000
225
+ }).trim();
226
+ if (fullPath && fullPath.length > pathEnv.length) {
227
+ (0, log_1.logInfo)(`从PowerShell获取到更完整的PATH (${fullPath.length} vs ${pathEnv.length} 字符)`);
228
+ pathEnv = fullPath;
229
+ }
230
+ }
231
+ catch (error) {
232
+ (0, log_1.logWarn)(`无法从PowerShell获取PATH: ${error}`);
233
+ }
234
+ }
235
+ (0, log_1.logInfo)(`PATH 环境变量内容: ${pathEnv ? pathEnv.substring(0, 200) + '...' : '(空)'}`);
236
+ const pathEntries = splitPathEntries(pathEnv, process.platform);
237
+ (0, log_1.logInfo)(`解析出的 PATH 条目数量: ${pathEntries.length}`);
238
+ // 打印前几个路径条目用于调试
239
+ pathEntries.slice(0, 5).forEach((entry, index) => {
240
+ (0, log_1.logInfo)(`PATH[${index}]: ${entry}`);
241
+ });
242
+ // 2.1) 首先优先处理PATH中的Git Bash
243
+ (0, log_1.logInfo)('优先检查 PATH 中的 Git Bash...');
244
+ for (const p of pathEntries) {
245
+ const candidate = (0, path_1.join)(p, 'bash.exe');
246
+ (0, log_1.logInfo)(`检查路径: ${candidate}`);
247
+ if ((0, fs_1.existsSync)(candidate)) {
248
+ // 检查是否为Git Bash路径 - 更宽泛的检测
249
+ const candidateLower = candidate.toLowerCase();
250
+ const isGitBash = candidateLower.includes('git') ||
251
+ candidateLower.includes('\\git\\') ||
252
+ candidateLower.includes('/git/') ||
253
+ candidateLower.includes('git for windows');
254
+ (0, log_1.logInfo)(`发现 bash.exe: ${candidate}, 是否Git Bash: ${isGitBash}`);
255
+ if (isGitBash) {
256
+ if (testBashAvailability(candidate, 'msys')) {
257
+ (0, log_1.logInfo)(`在 PATH 中找到可用的 Git Bash: ${candidate}`);
258
+ return { bin: candidate, args: ['-l'], type: 'msys' };
259
+ }
260
+ else {
261
+ (0, log_1.logWarn)(`PATH 中的 Git Bash 测试失败,跳过: ${candidate}`);
262
+ }
263
+ }
264
+ }
265
+ else {
266
+ // 如果是Git的cmd目录,检查对应的bin目录和usr/bin目录
267
+ const pLower = p.toLowerCase();
268
+ if (pLower.includes('git') && (pLower.endsWith('cmd') || pLower.endsWith('cmd\\'))) {
269
+ (0, log_1.logInfo)(`检测到Git cmd目录: ${p},尝试查找对应的bin目录`);
270
+ // 尝试多个可能的bin目录位置
271
+ const gitRoot = p.replace(/[\\\/]cmd[\\\/]?$/i, '');
272
+ const binCandidates = [
273
+ (0, path_1.join)(gitRoot, 'bin', 'bash.exe'),
274
+ (0, path_1.join)(gitRoot, 'usr', 'bin', 'bash.exe'),
275
+ (0, path_1.join)(gitRoot, 'mingw64', 'bin', 'bash.exe')
276
+ ];
277
+ for (const binCandidate of binCandidates) {
278
+ (0, log_1.logInfo)(`尝试Git Bash路径: ${binCandidate}`);
279
+ if ((0, fs_1.existsSync)(binCandidate)) {
280
+ (0, log_1.logInfo)(`发现 bash.exe: ${binCandidate}, 是否Git Bash: true`);
281
+ if (testBashAvailability(binCandidate, 'msys')) {
282
+ (0, log_1.logInfo)(`在 PATH 中找到可用的 Git Bash (通过cmd->bin映射): ${binCandidate}`);
283
+ return { bin: binCandidate, args: ['-l'], type: 'msys' };
284
+ }
285
+ else {
286
+ (0, log_1.logWarn)(`Git Bash 测试失败,跳过: ${binCandidate}`);
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ }
293
+ // 2.2) 然后处理PATH中的其他bash
294
+ (0, log_1.logInfo)('检查 PATH 中的其他 bash...');
295
+ for (const p of pathEntries) {
296
+ const candidate = (0, path_1.join)(p, 'bash.exe');
297
+ if ((0, fs_1.existsSync)(candidate)) {
298
+ // 跳过已经处理过的Git Bash - 使用相同的检测逻辑
299
+ const candidateLower = candidate.toLowerCase();
300
+ const isGitBash = candidateLower.includes('git') ||
301
+ candidateLower.includes('\\git\\') ||
302
+ candidateLower.includes('/git/') ||
303
+ candidateLower.includes('git for windows');
304
+ if (!isGitBash) {
305
+ // 对所有找到的 bash 进行测试验证
306
+ const isSystem32Bash = candidate.toLowerCase().includes('system32');
307
+ const testType = isSystem32Bash ? 'wsl' : 'msys';
308
+ if (testBashAvailability(candidate, testType)) {
309
+ (0, log_1.logInfo)(`在 PATH 中找到可用的 bash: ${candidate}`);
310
+ return { bin: candidate, args: ['-l'], type: isSystem32Bash ? 'wsl' : 'msys' };
311
+ }
312
+ else {
313
+ (0, log_1.logWarn)(`PATH 中的 bash 测试失败,跳过: ${candidate}`);
314
+ }
315
+ }
316
+ }
317
+ }
318
+ // 3) 检测 Git Bash 的常见固定位置 (作为 PATH 搜索的补充)
319
+ (0, log_1.logInfo)('搜索 Git Bash 固定安装位置...');
320
+ const programFiles = [
321
+ process.env['ProgramFiles'],
322
+ process.env['ProgramFiles(x86)'],
323
+ process.env['ProgramW6432'],
324
+ ].filter(Boolean);
325
+ const localAppData = process.env['LocalAppData'];
326
+ const gitBashCandidates = [];
327
+ // Git for Windows 标准安装位置
328
+ for (const base of programFiles) {
329
+ gitBashCandidates.push((0, path_1.join)(base, 'Git', 'bin', 'bash.exe'), (0, path_1.join)(base, 'Git', 'usr', 'bin', 'bash.exe'));
330
+ }
331
+ // 用户级安装位置
332
+ if (localAppData) {
333
+ gitBashCandidates.push((0, path_1.join)(localAppData, 'Programs', 'Git', 'bin', 'bash.exe'), (0, path_1.join)(localAppData, 'Programs', 'Git', 'usr', 'bin', 'bash.exe'));
334
+ }
335
+ // 检查 Git Bash 候选位置
336
+ for (const candidate of gitBashCandidates) {
337
+ if ((0, fs_1.existsSync)(candidate)) {
338
+ if (testBashAvailability(candidate)) {
339
+ (0, log_1.logInfo)(`找到 Git Bash: ${candidate}`);
340
+ return { bin: candidate, args: ['-l'], type: 'msys' };
341
+ }
342
+ else {
343
+ (0, log_1.logWarn)(`Git Bash 测试失败,跳过: ${candidate}`);
344
+ }
345
+ }
346
+ }
347
+ // 3.1) MSYS2 位置
348
+ const msys2Candidates = [
349
+ 'C:/msys64/usr/bin/bash.exe',
350
+ 'C:/msys32/usr/bin/bash.exe',
351
+ ];
352
+ for (const candidate of msys2Candidates) {
353
+ if ((0, fs_1.existsSync)(candidate)) {
354
+ if (testBashAvailability(candidate)) {
355
+ (0, log_1.logInfo)(`找到 MSYS2 bash: ${candidate}`);
356
+ return { bin: candidate, args: ['-l'], type: 'msys' };
357
+ }
358
+ else {
359
+ (0, log_1.logWarn)(`MSYS2 bash 测试失败,跳过: ${candidate}`);
360
+ }
361
+ }
362
+ }
363
+ // 4) 尝试 WSL (仅当明确可用时)
364
+ (0, log_1.logInfo)('检测 WSL 环境...');
365
+ try {
366
+ // 快速探测确保WSL+bash存在且可用
367
+ (0, child_process_1.execSync)('wsl.exe -e bash -lc "echo SEMA_OK"', { stdio: 'ignore', timeout: 2000 });
368
+ (0, log_1.logInfo)('WSL bash 可用');
369
+ return { bin: 'wsl.exe', args: ['-e', 'bash', '-l'], type: 'wsl' };
370
+ }
371
+ catch (error) {
372
+ (0, log_1.logWarn)(`WSL 检测失败: ${error}`);
373
+ }
374
+ // 5) 回退到 PowerShell (Windows 现代 Shell)
375
+ (0, log_1.logInfo)('尝试使用 PowerShell 作为回退方案...');
376
+ const powershellCandidates = [
377
+ 'pwsh.exe', // PowerShell 7+
378
+ 'powershell.exe', // Windows PowerShell 5.x
379
+ ];
380
+ for (const psCandidate of powershellCandidates) {
381
+ try {
382
+ // 测试 PowerShell 是否可用
383
+ // 修复: 增加超时时间,使用NoProfile参数,验证输出
384
+ const result = (0, child_process_1.execSync)(`${psCandidate} -NoProfile -Command "Write-Output 'SEMA_PS_OK'"`, {
385
+ stdio: 'pipe',
386
+ timeout: 3000, // 从1000ms增加到3000ms
387
+ encoding: 'utf8'
388
+ });
389
+ // 验证输出内容
390
+ if (result.toString().trim().includes('SEMA_PS_OK')) {
391
+ (0, log_1.logInfo)(`使用 PowerShell: ${psCandidate}`);
392
+ return { bin: psCandidate, args: ['-NoProfile', '-Command'], type: 'powershell' };
393
+ }
394
+ else {
395
+ (0, log_1.logWarn)(`PowerShell ${psCandidate} 测试输出不符合预期: ${result.toString().trim()}`);
396
+ }
397
+ }
398
+ catch (error) {
399
+ (0, log_1.logWarn)(`PowerShell ${psCandidate} 不可用: ${error}`);
400
+ }
401
+ }
402
+ // 6) 最后回退到 cmd.exe
403
+ (0, log_1.logWarn)('回退到 Windows 命令提示符 (cmd.exe)');
404
+ try {
405
+ const comspec = process.env.ComSpec || 'cmd.exe';
406
+ if ((0, fs_1.existsSync)(comspec)) {
407
+ (0, log_1.logInfo)(`使用 cmd.exe: ${comspec}`);
408
+ return { bin: comspec, args: ['/k'], type: 'cmd' };
409
+ }
410
+ }
411
+ catch (error) {
412
+ (0, log_1.logError)(`cmd.exe 检测失败: ${error}`);
413
+ }
414
+ // 7) 最后的手段:提供详细的错误信息和建议
415
+ const hint = [
416
+ '无法找到任何可用的 Shell 环境!',
417
+ '',
418
+ '建议解决方案:',
419
+ '1. 安装 Git for Windows 获得 bash 支持: https://git-scm.com/download/win',
420
+ '2. 或者启用 WSL: https://learn.microsoft.com/windows/wsl/install',
421
+ '3. 确保 PowerShell 或 cmd.exe 可用',
422
+ '',
423
+ '你也可以通过设置 SEMA_BASH 环境变量指定 bash 路径',
424
+ ].join('\n');
425
+ (0, log_1.logError)(hint);
426
+ throw new Error(hint);
427
+ }
428
+ // 持久化Shell类
429
+ class PersistentShell {
430
+ constructor(cwd) {
431
+ this.commandQueue = []; // 命令队列
432
+ this.isExecuting = false; // 是否正在执行命令
433
+ this.isAlive = true; // Shell是否存活
434
+ this.commandInterrupted = false; // 命令是否被中断
435
+ // 检测可用的Shell
436
+ const { bin, args, type } = detectShell();
437
+ this.binShell = bin;
438
+ this.shellArgs = args;
439
+ this.shellType = type;
440
+ // 启动Shell进程
441
+ const spawnOptions = {
442
+ stdio: ['pipe', 'pipe', 'pipe'],
443
+ cwd,
444
+ env: {
445
+ ...process.env,
446
+ GIT_EDITOR: 'true', // 禁用Git编辑器
447
+ },
448
+ };
449
+ // Windows 特定选项
450
+ if (process.platform === 'win32') {
451
+ spawnOptions.windowsHide = true; // 隐藏控制台窗口
452
+ }
453
+ this.shell = (0, child_process_1.spawn)(this.binShell, this.shellArgs, spawnOptions);
454
+ this.cwd = cwd;
455
+ // 监听Shell退出事件
456
+ this.shell.on('exit', (code, signal) => {
457
+ if (code) {
458
+ // TODO: 最好能通知用户Shell崩溃了
459
+ (0, log_1.logError)(`Shell exited with code ${code} and signal ${signal}`);
460
+ }
461
+ // 清理临时文件
462
+ for (const file of [
463
+ this.statusFile,
464
+ this.stdoutFile,
465
+ this.stderrFile,
466
+ this.cwdFile,
467
+ ]) {
468
+ if (fs.existsSync(file)) {
469
+ fs.unlinkSync(file);
470
+ }
471
+ }
472
+ this.isAlive = false;
473
+ });
474
+ // 生成随机ID用于临时文件
475
+ const id = crypto.randomBytes(2).toString('hex');
476
+ // 初始化临时文件路径
477
+ this.statusFile = TEMPFILE_PREFIX + id + FILE_SUFFIXES.STATUS;
478
+ this.stdoutFile = TEMPFILE_PREFIX + id + FILE_SUFFIXES.STDOUT;
479
+ this.stderrFile = TEMPFILE_PREFIX + id + FILE_SUFFIXES.STDERR;
480
+ this.cwdFile = TEMPFILE_PREFIX + id + FILE_SUFFIXES.CWD;
481
+ // 创建临时文件
482
+ for (const file of [this.statusFile, this.stdoutFile, this.stderrFile]) {
483
+ fs.writeFileSync(file, '');
484
+ }
485
+ // 初始化CWD文件,记录初始目录
486
+ fs.writeFileSync(this.cwdFile, cwd);
487
+ // 计算Bash可见的重定向路径(仅对 bash Shell 需要)
488
+ if (this.shellType === 'msys' || this.shellType === 'wsl' || this.shellType === 'posix') {
489
+ this.statusFileBashPath = toBashPath(this.statusFile, this.shellType);
490
+ this.stdoutFileBashPath = toBashPath(this.stdoutFile, this.shellType);
491
+ this.stderrFileBashPath = toBashPath(this.stderrFile, this.shellType);
492
+ this.cwdFileBashPath = toBashPath(this.cwdFile, this.shellType);
493
+ // 如果存在~/.bashrc则加载(适用于bash在POSIX/MSYS/WSL上)
494
+ this.sendToShell('[ -f ~/.bashrc ] && source ~/.bashrc || true');
495
+ }
496
+ else {
497
+ // 对于非 bash Shell,不需要路径转换
498
+ this.statusFileBashPath = this.statusFile;
499
+ this.stdoutFileBashPath = this.stdoutFile;
500
+ this.stderrFileBashPath = this.stderrFile;
501
+ this.cwdFileBashPath = this.cwdFile;
502
+ (0, log_1.logInfo)(`${this.shellType} Shell 初始化完成,跳过 bashrc 加载`);
503
+ }
504
+ }
505
+ // 重启Shell实例
506
+ static restart() {
507
+ if (PersistentShell.instance) {
508
+ PersistentShell.instance.close();
509
+ PersistentShell.instance = null;
510
+ }
511
+ }
512
+ // 获取单例实例
513
+ static getInstance() {
514
+ if (!PersistentShell.instance || !PersistentShell.instance.isAlive) {
515
+ PersistentShell.instance = new PersistentShell(process.cwd());
516
+ }
517
+ return PersistentShell.instance;
518
+ }
519
+ // 杀死子进程
520
+ killChildren() {
521
+ const parentPid = this.shell.pid;
522
+ if (!parentPid) {
523
+ this.commandInterrupted = true;
524
+ return;
525
+ }
526
+ try {
527
+ if (process.platform === 'win32') {
528
+ // Windows: 使用 taskkill 终止进程树
529
+ try {
530
+ (0, child_process_1.execSync)(`taskkill /f /t /pid ${parentPid}`, { stdio: 'ignore', timeout: 5000 });
531
+ }
532
+ catch (error) {
533
+ // 如果 taskkill 失败,尝试直接终止主进程
534
+ try {
535
+ process.kill(parentPid, 'SIGTERM');
536
+ }
537
+ catch (killError) {
538
+ (0, log_1.logError)(`Failed to kill process ${parentPid}: ${killError}`);
539
+ }
540
+ }
541
+ }
542
+ else {
543
+ // Unix: 使用 pgrep 获取子进程
544
+ const childPids = (0, child_process_1.execSync)(`pgrep -P ${parentPid}`)
545
+ .toString()
546
+ .trim()
547
+ .split('\n')
548
+ .filter(Boolean); // 过滤空字符串
549
+ // 杀死所有子进程
550
+ childPids.forEach(pid => {
551
+ try {
552
+ process.kill(Number(pid), 'SIGTERM');
553
+ }
554
+ catch (error) {
555
+ (0, log_1.logError)(`Failed to kill process ${pid}: ${error}`);
556
+ }
557
+ });
558
+ }
559
+ }
560
+ catch {
561
+ // 当没有找到进程时是预期的行为
562
+ }
563
+ finally {
564
+ this.commandInterrupted = true;
565
+ }
566
+ }
567
+ // 处理命令队列
568
+ async processQueue() {
569
+ /**
570
+ * 从队列中逐个处理命令。
571
+ * 并发不变性:
572
+ * - 一次只有一个实例运行(由isExecuting控制)
573
+ * - 是系统中唯一调用updateCwd()的地方
574
+ * - 在每个命令完成后调用updateCwd()
575
+ * - 通过队列确保命令串行执行
576
+ * - 通过调用killChildren()处理abortSignal中断
577
+ * - 在命令完成或中断后清理abortSignal监听器
578
+ */
579
+ if (this.isExecuting || this.commandQueue.length === 0)
580
+ return;
581
+ this.isExecuting = true;
582
+ const { command, abortSignal, timeout, resolve, reject } = this.commandQueue.shift();
583
+ // 中断处理函数
584
+ const killChildren = () => this.killChildren();
585
+ if (abortSignal) {
586
+ abortSignal.addEventListener('abort', killChildren);
587
+ }
588
+ try {
589
+ const result = await this.exec_(command, timeout);
590
+ // 不需要更新cwd - 在exec_中通过CWD文件处理
591
+ resolve(result);
592
+ }
593
+ catch (error) {
594
+ reject(error);
595
+ }
596
+ finally {
597
+ this.isExecuting = false;
598
+ if (abortSignal) {
599
+ abortSignal.removeEventListener('abort', killChildren);
600
+ }
601
+ // 处理队列中的下一个命令
602
+ this.processQueue();
603
+ }
604
+ }
605
+ // 执行命令(公开方法)
606
+ async exec(command, abortSignal, timeout) {
607
+ return new Promise((resolve, reject) => {
608
+ this.commandQueue.push({ command, abortSignal, timeout, resolve, reject });
609
+ this.processQueue();
610
+ });
611
+ }
612
+ // 执行命令(内部实现)
613
+ async exec_(command, timeout) {
614
+ /**
615
+ * 直接执行命令,不经过队列。
616
+ * 并发不变性:
617
+ * - 不适合并发调用(使用共享文件)
618
+ * - 仅在队列空闲时调用
619
+ * - 依赖基于文件的IPC处理Shell交互
620
+ * - 不修改命令队列状态
621
+ * - 通过commandInterrupted标志跟踪中断状态
622
+ * - 在新命令开始时重置中断状态
623
+ * - 在结果对象中报告中断状态
624
+ *
625
+ * 退出码和CWD处理:
626
+ * - 执行命令并立即将其退出码捕获到Shell变量中
627
+ * - 捕获退出码后更新CWD文件的工作目录
628
+ * - 将保存的退出码作为最后一步写入状态文件
629
+ * - 此序列消除了退出码捕获和CWD更新之间的竞争条件
630
+ * - pwd()方法直接读取CWD文件获取当前目录信息
631
+ */
632
+ // 如果是非 bash Shell,需要特殊处理
633
+ if (this.shellType === 'cmd' || this.shellType === 'powershell') {
634
+ return this.execNonBashShell(command, timeout);
635
+ }
636
+ const quotedCommand = shell_quote_1.default.quote([command]);
637
+ // 检查命令语法
638
+ try {
639
+ if (this.shellType === 'wsl') {
640
+ (0, child_process_1.execSync)(`wsl.exe -e bash -n -c ${quotedCommand}`, {
641
+ stdio: 'ignore',
642
+ timeout: 1000,
643
+ });
644
+ }
645
+ else {
646
+ // Windows 路径可能包含空格(如 "C:\Program Files\Git\bin\bash.exe"),需要用引号包裹
647
+ const quotedBinShell = process.platform === 'win32' ? `"${this.binShell}"` : this.binShell;
648
+ (0, child_process_1.execSync)(`${quotedBinShell} -n -c ${quotedCommand}`, {
649
+ stdio: 'ignore',
650
+ timeout: 1000,
651
+ });
652
+ }
653
+ }
654
+ catch (stderr) {
655
+ // 如果有语法错误,返回错误并记录
656
+ const errorStr = typeof stderr === 'string' ? stderr : String(stderr || '');
657
+ return Promise.resolve({
658
+ stdout: '',
659
+ stderr: errorStr,
660
+ code: 128,
661
+ interrupted: false,
662
+ });
663
+ }
664
+ const commandTimeout = timeout || DEFAULT_TIMEOUT;
665
+ // 为新命令重置中断状态
666
+ this.commandInterrupted = false;
667
+ return new Promise(resolve => {
668
+ // 清空输出文件
669
+ fs.writeFileSync(this.stdoutFile, '');
670
+ fs.writeFileSync(this.stderrFile, '');
671
+ fs.writeFileSync(this.statusFile, '');
672
+ // 使用命令数组清晰地分解命令序列
673
+ const commandParts = [];
674
+ // 1. 使用重定向执行主命令
675
+ commandParts.push(`eval ${quotedCommand} < /dev/null > ${quoteForBash(this.stdoutFileBashPath)} 2> ${quoteForBash(this.stderrFileBashPath)}`);
676
+ // 2. 命令执行后立即捕获退出码,避免丢失
677
+ commandParts.push(`EXEC_EXIT_CODE=$?`);
678
+ // 3. 更新CWD文件
679
+ commandParts.push(`pwd > ${quoteForBash(this.cwdFileBashPath)}`);
680
+ // 4. 将保存的退出码写入状态文件,避免与pwd竞争
681
+ commandParts.push(`echo $EXEC_EXIT_CODE > ${quoteForBash(this.statusFileBashPath)}`);
682
+ // 将组合命令作为单个操作发送以保持原子性
683
+ this.sendToShell(commandParts.join('\n'));
684
+ // 检查命令完成或超时
685
+ const start = Date.now();
686
+ const checkCompletion = setInterval(() => {
687
+ try {
688
+ let statusFileSize = 0;
689
+ if (fs.existsSync(this.statusFile)) {
690
+ statusFileSize = fs.statSync(this.statusFile).size;
691
+ }
692
+ if (statusFileSize > 0 ||
693
+ Date.now() - start > commandTimeout ||
694
+ this.commandInterrupted) {
695
+ clearInterval(checkCompletion);
696
+ const stdout = fs.existsSync(this.stdoutFile)
697
+ ? fs.readFileSync(this.stdoutFile, 'utf8')
698
+ : '';
699
+ let stderr = fs.existsSync(this.stderrFile)
700
+ ? fs.readFileSync(this.stderrFile, 'utf8')
701
+ : '';
702
+ let code;
703
+ if (statusFileSize) {
704
+ code = Number(fs.readFileSync(this.statusFile, 'utf8'));
705
+ }
706
+ else {
707
+ // 发生超时 - 杀死任何正在运行的进程
708
+ this.killChildren();
709
+ code = SIGTERM_CODE;
710
+ stderr += (stderr ? '\n' : '') + 'Command execution timed out';
711
+ }
712
+ resolve({
713
+ stdout,
714
+ stderr,
715
+ code,
716
+ interrupted: this.commandInterrupted,
717
+ });
718
+ }
719
+ }
720
+ catch {
721
+ // 在轮询期间忽略文件系统错误 - 它们是预期的
722
+ // 因为我们在文件存在之前检查完成状态
723
+ }
724
+ }, 10); // 增加这个值会引入延迟
725
+ });
726
+ }
727
+ // 非 Bash Shell 特殊处理 (PowerShell, cmd.exe)
728
+ async execNonBashShell(command, timeout) {
729
+ const commandTimeout = timeout || DEFAULT_TIMEOUT;
730
+ this.commandInterrupted = false;
731
+ return new Promise(resolve => {
732
+ try {
733
+ let shellArgs;
734
+ let actualCommand;
735
+ if (this.shellType === 'powershell') {
736
+ // PowerShell 命令处理
737
+ shellArgs = ['-NoProfile', '-Command', command];
738
+ actualCommand = command;
739
+ }
740
+ else if (this.shellType === 'cmd') {
741
+ // cmd.exe 命令处理
742
+ shellArgs = ['/c', command];
743
+ actualCommand = command;
744
+ }
745
+ else {
746
+ // 回退处理
747
+ shellArgs = [command];
748
+ actualCommand = command;
749
+ }
750
+ (0, log_1.logInfo)(`执行 ${this.shellType} 命令: ${actualCommand}`);
751
+ // 直接使用对应的 Shell 执行命令
752
+ const childProcess = (0, child_process_1.spawn)(this.binShell, shellArgs, {
753
+ cwd: this.cwd,
754
+ env: process.env,
755
+ stdio: ['pipe', 'pipe', 'pipe'],
756
+ windowsHide: true
757
+ });
758
+ let stdout = '';
759
+ let stderr = '';
760
+ let completed = false;
761
+ // 收集输出
762
+ if (childProcess.stdout) {
763
+ childProcess.stdout.on('data', (data) => {
764
+ stdout += data.toString();
765
+ });
766
+ }
767
+ if (childProcess.stderr) {
768
+ childProcess.stderr.on('data', (data) => {
769
+ stderr += data.toString();
770
+ });
771
+ }
772
+ // 设置超时
773
+ const timer = setTimeout(() => {
774
+ if (!completed) {
775
+ completed = true;
776
+ childProcess.kill('SIGTERM');
777
+ resolve({
778
+ stdout,
779
+ stderr: stderr + '\nCommand execution timed out',
780
+ code: SIGTERM_CODE,
781
+ interrupted: true,
782
+ });
783
+ }
784
+ }, commandTimeout);
785
+ // 处理进程退出
786
+ childProcess.on('exit', (code, signal) => {
787
+ if (!completed) {
788
+ completed = true;
789
+ clearTimeout(timer);
790
+ resolve({
791
+ stdout,
792
+ stderr,
793
+ code: code || 0,
794
+ interrupted: this.commandInterrupted,
795
+ });
796
+ }
797
+ });
798
+ childProcess.on('error', (error) => {
799
+ if (!completed) {
800
+ completed = true;
801
+ clearTimeout(timer);
802
+ resolve({
803
+ stdout,
804
+ stderr: stderr + '\n' + error.message,
805
+ code: 1,
806
+ interrupted: false,
807
+ });
808
+ }
809
+ });
810
+ }
811
+ catch (error) {
812
+ resolve({
813
+ stdout: '',
814
+ stderr: String(error),
815
+ code: 1,
816
+ interrupted: false,
817
+ });
818
+ }
819
+ });
820
+ }
821
+ // 向Shell发送命令
822
+ sendToShell(command) {
823
+ try {
824
+ this.shell.stdin.write(command + '\n');
825
+ }
826
+ catch (error) {
827
+ const errorString = error instanceof Error
828
+ ? error.message
829
+ : String(error || 'Unknown error');
830
+ (0, log_1.logError)(`Error in sendToShell: ${errorString}`);
831
+ throw error;
832
+ }
833
+ }
834
+ // 获取当前工作目录
835
+ pwd() {
836
+ // 对于非 bash Shell,直接返回缓存的目录
837
+ if (this.shellType === 'cmd' || this.shellType === 'powershell') {
838
+ return this.cwd;
839
+ }
840
+ try {
841
+ const newCwd = fs.readFileSync(this.cwdFile, 'utf8').trim();
842
+ if (newCwd) {
843
+ this.cwd = newCwd;
844
+ }
845
+ }
846
+ catch (error) {
847
+ (0, log_1.logError)(`Shell pwd error ${error}`);
848
+ }
849
+ // 总是返回缓存的值
850
+ return this.cwd;
851
+ }
852
+ // 设置当前工作目录
853
+ async setCwd(cwd) {
854
+ const resolved = (0, path_1.isAbsolute)(cwd) ? cwd : (0, path_1.resolve)(process.cwd(), cwd);
855
+ if (!(0, fs_1.existsSync)(resolved)) {
856
+ throw new Error(`Path "${resolved}" does not exist`);
857
+ }
858
+ // 对于非 bash Shell,直接更新缓存的目录
859
+ if (this.shellType === 'cmd' || this.shellType === 'powershell') {
860
+ this.cwd = resolved;
861
+ (0, log_1.logInfo)(`${this.shellType} 工作目录更新为: ${resolved}`);
862
+ return;
863
+ }
864
+ const bashPath = toBashPath(resolved, this.shellType);
865
+ await this.exec(`cd ${quoteForBash(bashPath)}`);
866
+ }
867
+ // 关闭Shell
868
+ close() {
869
+ this.shell.stdin.end();
870
+ this.shell.kill();
871
+ }
872
+ }
873
+ exports.PersistentShell = PersistentShell;
874
+ // 单例实例
875
+ PersistentShell.instance = null;
876
+ //# sourceMappingURL=shell.js.map