@adverant-nexus/cli 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 (541) hide show
  1. package/ARCHITECTURE.md +1366 -0
  2. package/LICENSE +21 -0
  3. package/README.md +593 -0
  4. package/completions/_nexus +452 -0
  5. package/completions/nexus.bash +329 -0
  6. package/completions/nexus.fish +187 -0
  7. package/dist/cli.d.ts +35 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +135 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/agent/index.d.ts +9 -0
  12. package/dist/commands/agent/index.d.ts.map +1 -0
  13. package/dist/commands/agent/index.js +20 -0
  14. package/dist/commands/agent/index.js.map +1 -0
  15. package/dist/commands/agent/list.d.ts +9 -0
  16. package/dist/commands/agent/list.d.ts.map +1 -0
  17. package/dist/commands/agent/list.js +122 -0
  18. package/dist/commands/agent/list.js.map +1 -0
  19. package/dist/commands/agent/run.d.ts +10 -0
  20. package/dist/commands/agent/run.d.ts.map +1 -0
  21. package/dist/commands/agent/run.js +167 -0
  22. package/dist/commands/agent/run.js.map +1 -0
  23. package/dist/commands/agent/status.d.ts +9 -0
  24. package/dist/commands/agent/status.d.ts.map +1 -0
  25. package/dist/commands/agent/status.js +157 -0
  26. package/dist/commands/agent/status.js.map +1 -0
  27. package/dist/commands/compute/agent.d.ts +21 -0
  28. package/dist/commands/compute/agent.d.ts.map +1 -0
  29. package/dist/commands/compute/agent.js +158 -0
  30. package/dist/commands/compute/agent.js.map +1 -0
  31. package/dist/commands/compute/index.d.ts +10 -0
  32. package/dist/commands/compute/index.d.ts.map +1 -0
  33. package/dist/commands/compute/index.js +27 -0
  34. package/dist/commands/compute/index.js.map +1 -0
  35. package/dist/commands/compute/lib/hardware-detection.d.ts +52 -0
  36. package/dist/commands/compute/lib/hardware-detection.d.ts.map +1 -0
  37. package/dist/commands/compute/lib/hardware-detection.js +432 -0
  38. package/dist/commands/compute/lib/hardware-detection.js.map +1 -0
  39. package/dist/commands/compute/lib/local-compute-agent.d.ts +143 -0
  40. package/dist/commands/compute/lib/local-compute-agent.d.ts.map +1 -0
  41. package/dist/commands/compute/lib/local-compute-agent.js +1162 -0
  42. package/dist/commands/compute/lib/local-compute-agent.js.map +1 -0
  43. package/dist/commands/compute/lib/local-compute-client.d.ts +89 -0
  44. package/dist/commands/compute/lib/local-compute-client.d.ts.map +1 -0
  45. package/dist/commands/compute/lib/local-compute-client.js +388 -0
  46. package/dist/commands/compute/lib/local-compute-client.js.map +1 -0
  47. package/dist/commands/compute/list.d.ts +14 -0
  48. package/dist/commands/compute/list.d.ts.map +1 -0
  49. package/dist/commands/compute/list.js +164 -0
  50. package/dist/commands/compute/list.js.map +1 -0
  51. package/dist/commands/compute/logs.d.ts +14 -0
  52. package/dist/commands/compute/logs.d.ts.map +1 -0
  53. package/dist/commands/compute/logs.js +105 -0
  54. package/dist/commands/compute/logs.js.map +1 -0
  55. package/dist/commands/compute/resources.d.ts +14 -0
  56. package/dist/commands/compute/resources.d.ts.map +1 -0
  57. package/dist/commands/compute/resources.js +163 -0
  58. package/dist/commands/compute/resources.js.map +1 -0
  59. package/dist/commands/compute/status.d.ts +13 -0
  60. package/dist/commands/compute/status.d.ts.map +1 -0
  61. package/dist/commands/compute/status.js +223 -0
  62. package/dist/commands/compute/status.js.map +1 -0
  63. package/dist/commands/compute/submit.d.ts +19 -0
  64. package/dist/commands/compute/submit.d.ts.map +1 -0
  65. package/dist/commands/compute/submit.js +99 -0
  66. package/dist/commands/compute/submit.js.map +1 -0
  67. package/dist/commands/deploy.d.ts +11 -0
  68. package/dist/commands/deploy.d.ts.map +1 -0
  69. package/dist/commands/deploy.js +117 -0
  70. package/dist/commands/deploy.js.map +1 -0
  71. package/dist/commands/dynamic/graphrag-commands.d.ts +16 -0
  72. package/dist/commands/dynamic/graphrag-commands.d.ts.map +1 -0
  73. package/dist/commands/dynamic/graphrag-commands.js +562 -0
  74. package/dist/commands/dynamic/graphrag-commands.js.map +1 -0
  75. package/dist/commands/dynamic/index.d.ts +10 -0
  76. package/dist/commands/dynamic/index.d.ts.map +1 -0
  77. package/dist/commands/dynamic/index.js +17 -0
  78. package/dist/commands/dynamic/index.js.map +1 -0
  79. package/dist/commands/dynamic/mageagent-commands.d.ts +8 -0
  80. package/dist/commands/dynamic/mageagent-commands.d.ts.map +1 -0
  81. package/dist/commands/dynamic/mageagent-commands.js +86 -0
  82. package/dist/commands/dynamic/mageagent-commands.js.map +1 -0
  83. package/dist/commands/dynamic/mcp-tool-mapper.d.ts +97 -0
  84. package/dist/commands/dynamic/mcp-tool-mapper.d.ts.map +1 -0
  85. package/dist/commands/dynamic/mcp-tool-mapper.js +328 -0
  86. package/dist/commands/dynamic/mcp-tool-mapper.js.map +1 -0
  87. package/dist/commands/dynamic/nexus-commands.d.ts +78 -0
  88. package/dist/commands/dynamic/nexus-commands.d.ts.map +1 -0
  89. package/dist/commands/dynamic/nexus-commands.js +426 -0
  90. package/dist/commands/dynamic/nexus-commands.js.map +1 -0
  91. package/dist/commands/dynamic/sandbox-commands.d.ts +8 -0
  92. package/dist/commands/dynamic/sandbox-commands.d.ts.map +1 -0
  93. package/dist/commands/dynamic/sandbox-commands.js +80 -0
  94. package/dist/commands/dynamic/sandbox-commands.js.map +1 -0
  95. package/dist/commands/init.d.ts +11 -0
  96. package/dist/commands/init.d.ts.map +1 -0
  97. package/dist/commands/init.js +128 -0
  98. package/dist/commands/init.js.map +1 -0
  99. package/dist/commands/list.d.ts +10 -0
  100. package/dist/commands/list.d.ts.map +1 -0
  101. package/dist/commands/list.js +81 -0
  102. package/dist/commands/list.js.map +1 -0
  103. package/dist/commands/login.d.ts +10 -0
  104. package/dist/commands/login.d.ts.map +1 -0
  105. package/dist/commands/login.js +83 -0
  106. package/dist/commands/login.js.map +1 -0
  107. package/dist/commands/logs.d.ts +11 -0
  108. package/dist/commands/logs.d.ts.map +1 -0
  109. package/dist/commands/logs.js +79 -0
  110. package/dist/commands/logs.js.map +1 -0
  111. package/dist/commands/nexus/index.d.ts +69 -0
  112. package/dist/commands/nexus/index.d.ts.map +1 -0
  113. package/dist/commands/nexus/index.js +336 -0
  114. package/dist/commands/nexus/index.js.map +1 -0
  115. package/dist/commands/plugin/disable.d.ts +8 -0
  116. package/dist/commands/plugin/disable.d.ts.map +1 -0
  117. package/dist/commands/plugin/disable.js +31 -0
  118. package/dist/commands/plugin/disable.js.map +1 -0
  119. package/dist/commands/plugin/enable.d.ts +8 -0
  120. package/dist/commands/plugin/enable.d.ts.map +1 -0
  121. package/dist/commands/plugin/enable.js +37 -0
  122. package/dist/commands/plugin/enable.js.map +1 -0
  123. package/dist/commands/plugin/index.d.ts +8 -0
  124. package/dist/commands/plugin/index.d.ts.map +1 -0
  125. package/dist/commands/plugin/index.js +23 -0
  126. package/dist/commands/plugin/index.js.map +1 -0
  127. package/dist/commands/plugin/info.d.ts +8 -0
  128. package/dist/commands/plugin/info.d.ts.map +1 -0
  129. package/dist/commands/plugin/info.js +129 -0
  130. package/dist/commands/plugin/info.js.map +1 -0
  131. package/dist/commands/plugin/init.d.ts +8 -0
  132. package/dist/commands/plugin/init.d.ts.map +1 -0
  133. package/dist/commands/plugin/init.js +83 -0
  134. package/dist/commands/plugin/init.js.map +1 -0
  135. package/dist/commands/plugin/install.d.ts +8 -0
  136. package/dist/commands/plugin/install.d.ts.map +1 -0
  137. package/dist/commands/plugin/install.js +56 -0
  138. package/dist/commands/plugin/install.js.map +1 -0
  139. package/dist/commands/plugin/list.d.ts +8 -0
  140. package/dist/commands/plugin/list.d.ts.map +1 -0
  141. package/dist/commands/plugin/list.js +72 -0
  142. package/dist/commands/plugin/list.js.map +1 -0
  143. package/dist/commands/plugin/uninstall.d.ts +8 -0
  144. package/dist/commands/plugin/uninstall.d.ts.map +1 -0
  145. package/dist/commands/plugin/uninstall.js +49 -0
  146. package/dist/commands/plugin/uninstall.js.map +1 -0
  147. package/dist/commands/register.d.ts +10 -0
  148. package/dist/commands/register.d.ts.map +1 -0
  149. package/dist/commands/register.js +85 -0
  150. package/dist/commands/register.js.map +1 -0
  151. package/dist/commands/services/health.d.ts +7 -0
  152. package/dist/commands/services/health.d.ts.map +1 -0
  153. package/dist/commands/services/health.js +73 -0
  154. package/dist/commands/services/health.js.map +1 -0
  155. package/dist/commands/services/index.d.ts +16 -0
  156. package/dist/commands/services/index.d.ts.map +1 -0
  157. package/dist/commands/services/index.js +26 -0
  158. package/dist/commands/services/index.js.map +1 -0
  159. package/dist/commands/services/info.d.ts +7 -0
  160. package/dist/commands/services/info.d.ts.map +1 -0
  161. package/dist/commands/services/info.js +68 -0
  162. package/dist/commands/services/info.js.map +1 -0
  163. package/dist/commands/services/list.d.ts +9 -0
  164. package/dist/commands/services/list.d.ts.map +1 -0
  165. package/dist/commands/services/list.js +43 -0
  166. package/dist/commands/services/list.js.map +1 -0
  167. package/dist/commands/services/logs.d.ts +7 -0
  168. package/dist/commands/services/logs.d.ts.map +1 -0
  169. package/dist/commands/services/logs.js +107 -0
  170. package/dist/commands/services/logs.js.map +1 -0
  171. package/dist/commands/services/ports.d.ts +7 -0
  172. package/dist/commands/services/ports.d.ts.map +1 -0
  173. package/dist/commands/services/ports.js +65 -0
  174. package/dist/commands/services/ports.js.map +1 -0
  175. package/dist/commands/services/restart.d.ts +7 -0
  176. package/dist/commands/services/restart.d.ts.map +1 -0
  177. package/dist/commands/services/restart.js +67 -0
  178. package/dist/commands/services/restart.js.map +1 -0
  179. package/dist/commands/services/start.d.ts +7 -0
  180. package/dist/commands/services/start.d.ts.map +1 -0
  181. package/dist/commands/services/start.js +67 -0
  182. package/dist/commands/services/start.js.map +1 -0
  183. package/dist/commands/services/status.d.ts +9 -0
  184. package/dist/commands/services/status.d.ts.map +1 -0
  185. package/dist/commands/services/status.js +119 -0
  186. package/dist/commands/services/status.js.map +1 -0
  187. package/dist/commands/services/stop.d.ts +7 -0
  188. package/dist/commands/services/stop.d.ts.map +1 -0
  189. package/dist/commands/services/stop.js +67 -0
  190. package/dist/commands/services/stop.js.map +1 -0
  191. package/dist/commands/session/delete.d.ts +9 -0
  192. package/dist/commands/session/delete.d.ts.map +1 -0
  193. package/dist/commands/session/delete.js +51 -0
  194. package/dist/commands/session/delete.js.map +1 -0
  195. package/dist/commands/session/export.d.ts +9 -0
  196. package/dist/commands/session/export.d.ts.map +1 -0
  197. package/dist/commands/session/export.js +36 -0
  198. package/dist/commands/session/export.js.map +1 -0
  199. package/dist/commands/session/import.d.ts +9 -0
  200. package/dist/commands/session/import.d.ts.map +1 -0
  201. package/dist/commands/session/import.js +54 -0
  202. package/dist/commands/session/import.js.map +1 -0
  203. package/dist/commands/session/index.d.ts +9 -0
  204. package/dist/commands/session/index.d.ts.map +1 -0
  205. package/dist/commands/session/index.js +28 -0
  206. package/dist/commands/session/index.js.map +1 -0
  207. package/dist/commands/session/list.d.ts +9 -0
  208. package/dist/commands/session/list.d.ts.map +1 -0
  209. package/dist/commands/session/list.js +88 -0
  210. package/dist/commands/session/list.js.map +1 -0
  211. package/dist/commands/session/load.d.ts +9 -0
  212. package/dist/commands/session/load.d.ts.map +1 -0
  213. package/dist/commands/session/load.js +71 -0
  214. package/dist/commands/session/load.js.map +1 -0
  215. package/dist/commands/session/resume.d.ts +9 -0
  216. package/dist/commands/session/resume.d.ts.map +1 -0
  217. package/dist/commands/session/resume.js +49 -0
  218. package/dist/commands/session/resume.js.map +1 -0
  219. package/dist/commands/session/save.d.ts +9 -0
  220. package/dist/commands/session/save.d.ts.map +1 -0
  221. package/dist/commands/session/save.js +69 -0
  222. package/dist/commands/session/save.js.map +1 -0
  223. package/dist/commands/workspace/git-commit.d.ts +9 -0
  224. package/dist/commands/workspace/git-commit.d.ts.map +1 -0
  225. package/dist/commands/workspace/git-commit.js +156 -0
  226. package/dist/commands/workspace/git-commit.js.map +1 -0
  227. package/dist/commands/workspace/git-status.d.ts +9 -0
  228. package/dist/commands/workspace/git-status.d.ts.map +1 -0
  229. package/dist/commands/workspace/git-status.js +192 -0
  230. package/dist/commands/workspace/git-status.js.map +1 -0
  231. package/dist/commands/workspace/index.d.ts +9 -0
  232. package/dist/commands/workspace/index.d.ts.map +1 -0
  233. package/dist/commands/workspace/index.js +24 -0
  234. package/dist/commands/workspace/index.js.map +1 -0
  235. package/dist/commands/workspace/info.d.ts +10 -0
  236. package/dist/commands/workspace/info.d.ts.map +1 -0
  237. package/dist/commands/workspace/info.js +191 -0
  238. package/dist/commands/workspace/info.js.map +1 -0
  239. package/dist/commands/workspace/init.d.ts +9 -0
  240. package/dist/commands/workspace/init.d.ts.map +1 -0
  241. package/dist/commands/workspace/init.js +193 -0
  242. package/dist/commands/workspace/init.js.map +1 -0
  243. package/dist/commands/workspace/validate.d.ts +9 -0
  244. package/dist/commands/workspace/validate.d.ts.map +1 -0
  245. package/dist/commands/workspace/validate.js +140 -0
  246. package/dist/commands/workspace/validate.js.map +1 -0
  247. package/dist/core/agent-client.d.ts +49 -0
  248. package/dist/core/agent-client.d.ts.map +1 -0
  249. package/dist/core/agent-client.js +289 -0
  250. package/dist/core/agent-client.js.map +1 -0
  251. package/dist/core/config/config-manager.d.ts +75 -0
  252. package/dist/core/config/config-manager.d.ts.map +1 -0
  253. package/dist/core/config/config-manager.js +379 -0
  254. package/dist/core/config/config-manager.js.map +1 -0
  255. package/dist/core/config/profile-manager.d.ts +76 -0
  256. package/dist/core/config/profile-manager.d.ts.map +1 -0
  257. package/dist/core/config/profile-manager.js +250 -0
  258. package/dist/core/config/profile-manager.js.map +1 -0
  259. package/dist/core/config/workspace-detector.d.ts +66 -0
  260. package/dist/core/config/workspace-detector.d.ts.map +1 -0
  261. package/dist/core/config/workspace-detector.js +291 -0
  262. package/dist/core/config/workspace-detector.js.map +1 -0
  263. package/dist/core/discovery/docker-parser.d.ts +27 -0
  264. package/dist/core/discovery/docker-parser.d.ts.map +1 -0
  265. package/dist/core/discovery/docker-parser.js +361 -0
  266. package/dist/core/discovery/docker-parser.js.map +1 -0
  267. package/dist/core/discovery/index.d.ts +11 -0
  268. package/dist/core/discovery/index.d.ts.map +1 -0
  269. package/dist/core/discovery/index.js +16 -0
  270. package/dist/core/discovery/index.js.map +1 -0
  271. package/dist/core/discovery/mcp-discovery.d.ts +41 -0
  272. package/dist/core/discovery/mcp-discovery.d.ts.map +1 -0
  273. package/dist/core/discovery/mcp-discovery.js +439 -0
  274. package/dist/core/discovery/mcp-discovery.js.map +1 -0
  275. package/dist/core/discovery/openapi-parser.d.ts +95 -0
  276. package/dist/core/discovery/openapi-parser.d.ts.map +1 -0
  277. package/dist/core/discovery/openapi-parser.js +353 -0
  278. package/dist/core/discovery/openapi-parser.js.map +1 -0
  279. package/dist/core/discovery/plugin-discovery.d.ts +63 -0
  280. package/dist/core/discovery/plugin-discovery.d.ts.map +1 -0
  281. package/dist/core/discovery/plugin-discovery.js +333 -0
  282. package/dist/core/discovery/plugin-discovery.js.map +1 -0
  283. package/dist/core/discovery/service-discovery.d.ts +107 -0
  284. package/dist/core/discovery/service-discovery.d.ts.map +1 -0
  285. package/dist/core/discovery/service-discovery.js +349 -0
  286. package/dist/core/discovery/service-discovery.js.map +1 -0
  287. package/dist/core/nexus-client.d.ts +119 -0
  288. package/dist/core/nexus-client.d.ts.map +1 -0
  289. package/dist/core/nexus-client.js +292 -0
  290. package/dist/core/nexus-client.js.map +1 -0
  291. package/dist/core/nexus-tool-executor.d.ts +102 -0
  292. package/dist/core/nexus-tool-executor.d.ts.map +1 -0
  293. package/dist/core/nexus-tool-executor.js +386 -0
  294. package/dist/core/nexus-tool-executor.js.map +1 -0
  295. package/dist/core/react-handler.d.ts +17 -0
  296. package/dist/core/react-handler.d.ts.map +1 -0
  297. package/dist/core/react-handler.js +296 -0
  298. package/dist/core/react-handler.js.map +1 -0
  299. package/dist/core/router/command-registry.d.ts +61 -0
  300. package/dist/core/router/command-registry.d.ts.map +1 -0
  301. package/dist/core/router/command-registry.js +138 -0
  302. package/dist/core/router/command-registry.js.map +1 -0
  303. package/dist/core/router/command-router.d.ts +33 -0
  304. package/dist/core/router/command-router.d.ts.map +1 -0
  305. package/dist/core/router/command-router.js +111 -0
  306. package/dist/core/router/command-router.js.map +1 -0
  307. package/dist/core/router/index.d.ts +9 -0
  308. package/dist/core/router/index.d.ts.map +1 -0
  309. package/dist/core/router/index.js +8 -0
  310. package/dist/core/router/index.js.map +1 -0
  311. package/dist/core/session/context-manager.d.ts +69 -0
  312. package/dist/core/session/context-manager.d.ts.map +1 -0
  313. package/dist/core/session/context-manager.js +109 -0
  314. package/dist/core/session/context-manager.js.map +1 -0
  315. package/dist/core/session/history-manager.d.ts +72 -0
  316. package/dist/core/session/history-manager.d.ts.map +1 -0
  317. package/dist/core/session/history-manager.js +175 -0
  318. package/dist/core/session/history-manager.js.map +1 -0
  319. package/dist/core/session/index.d.ts +9 -0
  320. package/dist/core/session/index.d.ts.map +1 -0
  321. package/dist/core/session/index.js +9 -0
  322. package/dist/core/session/index.js.map +1 -0
  323. package/dist/core/session/session-manager.d.ts +50 -0
  324. package/dist/core/session/session-manager.d.ts.map +1 -0
  325. package/dist/core/session/session-manager.js +200 -0
  326. package/dist/core/session/session-manager.js.map +1 -0
  327. package/dist/core/session/session-storage.d.ts +59 -0
  328. package/dist/core/session/session-storage.d.ts.map +1 -0
  329. package/dist/core/session/session-storage.js +226 -0
  330. package/dist/core/session/session-storage.js.map +1 -0
  331. package/dist/core/transport/http-client.d.ts +27 -0
  332. package/dist/core/transport/http-client.d.ts.map +1 -0
  333. package/dist/core/transport/http-client.js +182 -0
  334. package/dist/core/transport/http-client.js.map +1 -0
  335. package/dist/core/transport/index.d.ts +11 -0
  336. package/dist/core/transport/index.d.ts.map +1 -0
  337. package/dist/core/transport/index.js +10 -0
  338. package/dist/core/transport/index.js.map +1 -0
  339. package/dist/core/transport/mcp-client.d.ts +69 -0
  340. package/dist/core/transport/mcp-client.d.ts.map +1 -0
  341. package/dist/core/transport/mcp-client.js +252 -0
  342. package/dist/core/transport/mcp-client.js.map +1 -0
  343. package/dist/core/transport/stream-handler.d.ts +51 -0
  344. package/dist/core/transport/stream-handler.d.ts.map +1 -0
  345. package/dist/core/transport/stream-handler.js +264 -0
  346. package/dist/core/transport/stream-handler.js.map +1 -0
  347. package/dist/core/transport/websocket-client.d.ts +66 -0
  348. package/dist/core/transport/websocket-client.d.ts.map +1 -0
  349. package/dist/core/transport/websocket-client.js +232 -0
  350. package/dist/core/transport/websocket-client.js.map +1 -0
  351. package/dist/index.d.ts +9 -0
  352. package/dist/index.d.ts.map +1 -0
  353. package/dist/index.js +106 -0
  354. package/dist/index.js.map +1 -0
  355. package/dist/output/formatters/index.d.ts +9 -0
  356. package/dist/output/formatters/index.d.ts.map +1 -0
  357. package/dist/output/formatters/index.js +9 -0
  358. package/dist/output/formatters/index.js.map +1 -0
  359. package/dist/output/formatters/json-formatter.d.ts +71 -0
  360. package/dist/output/formatters/json-formatter.d.ts.map +1 -0
  361. package/dist/output/formatters/json-formatter.js +236 -0
  362. package/dist/output/formatters/json-formatter.js.map +1 -0
  363. package/dist/output/formatters/stream-formatter.d.ts +107 -0
  364. package/dist/output/formatters/stream-formatter.d.ts.map +1 -0
  365. package/dist/output/formatters/stream-formatter.js +247 -0
  366. package/dist/output/formatters/stream-formatter.js.map +1 -0
  367. package/dist/output/formatters/table-formatter.d.ts +63 -0
  368. package/dist/output/formatters/table-formatter.d.ts.map +1 -0
  369. package/dist/output/formatters/table-formatter.js +294 -0
  370. package/dist/output/formatters/table-formatter.js.map +1 -0
  371. package/dist/output/formatters/text-formatter.d.ts +63 -0
  372. package/dist/output/formatters/text-formatter.d.ts.map +1 -0
  373. package/dist/output/formatters/text-formatter.js +202 -0
  374. package/dist/output/formatters/text-formatter.js.map +1 -0
  375. package/dist/output/formatters/yaml-formatter.d.ts +71 -0
  376. package/dist/output/formatters/yaml-formatter.d.ts.map +1 -0
  377. package/dist/output/formatters/yaml-formatter.js +239 -0
  378. package/dist/output/formatters/yaml-formatter.js.map +1 -0
  379. package/dist/output/index.d.ts +7 -0
  380. package/dist/output/index.d.ts.map +1 -0
  381. package/dist/output/index.js +7 -0
  382. package/dist/output/index.js.map +1 -0
  383. package/dist/output/output-manager.d.ts +156 -0
  384. package/dist/output/output-manager.d.ts.map +1 -0
  385. package/dist/output/output-manager.js +339 -0
  386. package/dist/output/output-manager.js.map +1 -0
  387. package/dist/output/renderers/index.d.ts +6 -0
  388. package/dist/output/renderers/index.d.ts.map +1 -0
  389. package/dist/output/renderers/index.js +6 -0
  390. package/dist/output/renderers/index.js.map +1 -0
  391. package/dist/output/renderers/progress-renderer.d.ts +56 -0
  392. package/dist/output/renderers/progress-renderer.d.ts.map +1 -0
  393. package/dist/output/renderers/progress-renderer.js +306 -0
  394. package/dist/output/renderers/progress-renderer.js.map +1 -0
  395. package/dist/output/renderers/terminal-renderer.d.ts +117 -0
  396. package/dist/output/renderers/terminal-renderer.d.ts.map +1 -0
  397. package/dist/output/renderers/terminal-renderer.js +294 -0
  398. package/dist/output/renderers/terminal-renderer.js.map +1 -0
  399. package/dist/plugins/index.d.ts +12 -0
  400. package/dist/plugins/index.d.ts.map +1 -0
  401. package/dist/plugins/index.js +18 -0
  402. package/dist/plugins/index.js.map +1 -0
  403. package/dist/plugins/plugin-loader.d.ts +37 -0
  404. package/dist/plugins/plugin-loader.d.ts.map +1 -0
  405. package/dist/plugins/plugin-loader.js +155 -0
  406. package/dist/plugins/plugin-loader.js.map +1 -0
  407. package/dist/plugins/plugin-manager.d.ts +78 -0
  408. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  409. package/dist/plugins/plugin-manager.js +310 -0
  410. package/dist/plugins/plugin-manager.js.map +1 -0
  411. package/dist/plugins/plugin-sdk.d.ts +136 -0
  412. package/dist/plugins/plugin-sdk.d.ts.map +1 -0
  413. package/dist/plugins/plugin-sdk.js +260 -0
  414. package/dist/plugins/plugin-sdk.js.map +1 -0
  415. package/dist/plugins/plugin-storage.d.ts +109 -0
  416. package/dist/plugins/plugin-storage.d.ts.map +1 -0
  417. package/dist/plugins/plugin-storage.js +207 -0
  418. package/dist/plugins/plugin-storage.js.map +1 -0
  419. package/dist/plugins/plugin-validator.d.ts +44 -0
  420. package/dist/plugins/plugin-validator.d.ts.map +1 -0
  421. package/dist/plugins/plugin-validator.js +272 -0
  422. package/dist/plugins/plugin-validator.js.map +1 -0
  423. package/dist/plugins/template-generator.d.ts +35 -0
  424. package/dist/plugins/template-generator.d.ts.map +1 -0
  425. package/dist/plugins/template-generator.js +438 -0
  426. package/dist/plugins/template-generator.js.map +1 -0
  427. package/dist/repl/completer.d.ts +58 -0
  428. package/dist/repl/completer.d.ts.map +1 -0
  429. package/dist/repl/completer.js +198 -0
  430. package/dist/repl/completer.js.map +1 -0
  431. package/dist/repl/evaluator.d.ts +55 -0
  432. package/dist/repl/evaluator.d.ts.map +1 -0
  433. package/dist/repl/evaluator.js +299 -0
  434. package/dist/repl/evaluator.js.map +1 -0
  435. package/dist/repl/index.d.ts +10 -0
  436. package/dist/repl/index.d.ts.map +1 -0
  437. package/dist/repl/index.js +10 -0
  438. package/dist/repl/index.js.map +1 -0
  439. package/dist/repl/renderer.d.ts +77 -0
  440. package/dist/repl/renderer.d.ts.map +1 -0
  441. package/dist/repl/renderer.js +291 -0
  442. package/dist/repl/renderer.js.map +1 -0
  443. package/dist/repl/repl.d.ts +89 -0
  444. package/dist/repl/repl.d.ts.map +1 -0
  445. package/dist/repl/repl.js +339 -0
  446. package/dist/repl/repl.js.map +1 -0
  447. package/dist/templates/python.d.ts +15 -0
  448. package/dist/templates/python.d.ts.map +1 -0
  449. package/dist/templates/python.js +375 -0
  450. package/dist/templates/python.js.map +1 -0
  451. package/dist/templates/typescript.d.ts +15 -0
  452. package/dist/templates/typescript.d.ts.map +1 -0
  453. package/dist/templates/typescript.js +274 -0
  454. package/dist/templates/typescript.js.map +1 -0
  455. package/dist/types/agent.d.ts +109 -0
  456. package/dist/types/agent.d.ts.map +1 -0
  457. package/dist/types/agent.js +7 -0
  458. package/dist/types/agent.js.map +1 -0
  459. package/dist/types/api.d.ts +125 -0
  460. package/dist/types/api.d.ts.map +1 -0
  461. package/dist/types/api.js +53 -0
  462. package/dist/types/api.js.map +1 -0
  463. package/dist/types/command.d.ts +101 -0
  464. package/dist/types/command.d.ts.map +1 -0
  465. package/dist/types/command.js +7 -0
  466. package/dist/types/command.js.map +1 -0
  467. package/dist/types/compute.d.ts +317 -0
  468. package/dist/types/compute.d.ts.map +1 -0
  469. package/dist/types/compute.js +19 -0
  470. package/dist/types/compute.js.map +1 -0
  471. package/dist/types/config.d.ts +71 -0
  472. package/dist/types/config.d.ts.map +1 -0
  473. package/dist/types/config.js +7 -0
  474. package/dist/types/config.js.map +1 -0
  475. package/dist/types/errors.d.ts +56 -0
  476. package/dist/types/errors.d.ts.map +1 -0
  477. package/dist/types/errors.js +64 -0
  478. package/dist/types/errors.js.map +1 -0
  479. package/dist/types/index.d.ts +16 -0
  480. package/dist/types/index.d.ts.map +1 -0
  481. package/dist/types/index.js +16 -0
  482. package/dist/types/index.js.map +1 -0
  483. package/dist/types/nexus.d.ts +254 -0
  484. package/dist/types/nexus.d.ts.map +1 -0
  485. package/dist/types/nexus.js +7 -0
  486. package/dist/types/nexus.js.map +1 -0
  487. package/dist/types/output.d.ts +107 -0
  488. package/dist/types/output.d.ts.map +1 -0
  489. package/dist/types/output.js +7 -0
  490. package/dist/types/output.js.map +1 -0
  491. package/dist/types/plugin.d.ts +118 -0
  492. package/dist/types/plugin.d.ts.map +1 -0
  493. package/dist/types/plugin.js +7 -0
  494. package/dist/types/plugin.js.map +1 -0
  495. package/dist/types/service.d.ts +94 -0
  496. package/dist/types/service.d.ts.map +1 -0
  497. package/dist/types/service.js +15 -0
  498. package/dist/types/service.js.map +1 -0
  499. package/dist/types/session.d.ts +80 -0
  500. package/dist/types/session.d.ts.map +1 -0
  501. package/dist/types/session.js +7 -0
  502. package/dist/types/session.js.map +1 -0
  503. package/dist/types/transport.d.ts +96 -0
  504. package/dist/types/transport.d.ts.map +1 -0
  505. package/dist/types/transport.js +7 -0
  506. package/dist/types/transport.js.map +1 -0
  507. package/dist/utils/config.d.ts +47 -0
  508. package/dist/utils/config.d.ts.map +1 -0
  509. package/dist/utils/config.js +166 -0
  510. package/dist/utils/config.js.map +1 -0
  511. package/dist/utils/error-handler.d.ts +82 -0
  512. package/dist/utils/error-handler.d.ts.map +1 -0
  513. package/dist/utils/error-handler.js +238 -0
  514. package/dist/utils/error-handler.js.map +1 -0
  515. package/dist/utils/index.d.ts +9 -0
  516. package/dist/utils/index.d.ts.map +1 -0
  517. package/dist/utils/index.js +9 -0
  518. package/dist/utils/index.js.map +1 -0
  519. package/dist/utils/logger.d.ts +61 -0
  520. package/dist/utils/logger.d.ts.map +1 -0
  521. package/dist/utils/logger.js +200 -0
  522. package/dist/utils/logger.js.map +1 -0
  523. package/dist/utils/prompt.d.ts +57 -0
  524. package/dist/utils/prompt.d.ts.map +1 -0
  525. package/dist/utils/prompt.js +141 -0
  526. package/dist/utils/prompt.js.map +1 -0
  527. package/dist/utils/spinner.d.ts +47 -0
  528. package/dist/utils/spinner.d.ts.map +1 -0
  529. package/dist/utils/spinner.js +123 -0
  530. package/dist/utils/spinner.js.map +1 -0
  531. package/dist/utils/validation.d.ts +97 -0
  532. package/dist/utils/validation.d.ts.map +1 -0
  533. package/dist/utils/validation.js +289 -0
  534. package/dist/utils/validation.js.map +1 -0
  535. package/docs/COMPLETIONS.md +528 -0
  536. package/docs/REPL.md +466 -0
  537. package/docs/graphrag-commands.md +387 -0
  538. package/package.json +154 -0
  539. package/scripts/install-completions.sh +356 -0
  540. package/scripts/prepublish.js +522 -0
  541. package/scripts/verify-package.js +505 -0
@@ -0,0 +1,1162 @@
1
+ /**
2
+ * Local Compute Agent
3
+ *
4
+ * Daemon process that registers with HPC Gateway and executes ML jobs locally.
5
+ * Supports Apple Silicon (MPS), NVIDIA CUDA, and CPU-only execution.
6
+ */
7
+ import { spawn } from 'child_process';
8
+ import { io } from 'socket.io-client';
9
+ import express from 'express';
10
+ import { Server as SocketIOServer } from 'socket.io';
11
+ import EventEmitter from 'eventemitter3';
12
+ import os from 'os';
13
+ import fs from 'fs/promises';
14
+ import path from 'path';
15
+ import { v4 as uuidv4 } from 'uuid';
16
+ import { detectHardware } from './hardware-detection.js';
17
+ /**
18
+ * Path to agent PID file
19
+ */
20
+ const NEXUS_DIR = path.join(os.homedir(), '.nexus');
21
+ const AGENT_PID_FILE = path.join(NEXUS_DIR, 'compute-agent.pid');
22
+ const AGENT_LOG_FILE = path.join(NEXUS_DIR, 'compute-agent.log');
23
+ export class LocalComputeAgent extends EventEmitter {
24
+ config;
25
+ hardware = null;
26
+ agentId = null;
27
+ gatewaySocket = null;
28
+ localServer = null;
29
+ localApp = null;
30
+ localIO = null;
31
+ jobQueue = [];
32
+ currentJob = null;
33
+ completedJobs = new Map();
34
+ jobLogs = new Map();
35
+ // Kernel session management
36
+ kernelSessions = new Map();
37
+ kernelProcesses = new Map();
38
+ kernelOutputBuffers = new Map();
39
+ reconnectAttempts = 0;
40
+ reconnectTimer = null;
41
+ heartbeatTimer = null;
42
+ idleTimer = null;
43
+ running = false;
44
+ jobsCompleted = 0;
45
+ jobsFailed = 0;
46
+ totalComputeTime = 0;
47
+ startTime = null;
48
+ constructor(config = {}) {
49
+ super();
50
+ this.config = {
51
+ name: config.name || os.hostname(),
52
+ gatewayUrl: config.gatewayUrl || 'https://api.adverant.ai/hpc',
53
+ maxMemoryPercent: config.maxMemoryPercent ?? 75,
54
+ allowRemoteJobs: config.allowRemoteJobs ?? false,
55
+ idleTimeoutMinutes: config.idleTimeoutMinutes ?? 30,
56
+ apiPort: config.apiPort ?? 9200,
57
+ reconnectInterval: config.reconnectInterval ?? 5000,
58
+ maxReconnectAttempts: config.maxReconnectAttempts ?? 10,
59
+ };
60
+ }
61
+ /**
62
+ * Start the local compute agent
63
+ */
64
+ async start() {
65
+ if (this.running) {
66
+ throw new Error('Agent is already running');
67
+ }
68
+ // Ensure .nexus directory exists
69
+ await fs.mkdir(NEXUS_DIR, { recursive: true });
70
+ // Check if another agent is already running
71
+ if (await this.isAnotherAgentRunning()) {
72
+ throw new Error('Another compute agent is already running. Stop it first with: nexus compute agent stop');
73
+ }
74
+ // Detect hardware
75
+ this.hardware = await detectHardware();
76
+ this.agentId = uuidv4();
77
+ this.running = true;
78
+ this.startTime = new Date();
79
+ // Write PID file
80
+ await fs.writeFile(AGENT_PID_FILE, process.pid.toString());
81
+ // Start local API server
82
+ await this.startLocalServer();
83
+ // Connect to HPC Gateway
84
+ await this.connectToGateway();
85
+ // Start heartbeat
86
+ this.startHeartbeat();
87
+ // Reset idle timer
88
+ this.resetIdleTimer();
89
+ this.emit('connected', { agentId: this.agentId });
90
+ // Setup graceful shutdown
91
+ this.setupShutdownHandlers();
92
+ }
93
+ /**
94
+ * Stop the agent gracefully
95
+ */
96
+ async stop() {
97
+ if (!this.running) {
98
+ return;
99
+ }
100
+ this.running = false;
101
+ // Shutdown all kernels
102
+ await this.shutdownAllKernels();
103
+ // Cancel current job if running
104
+ if (this.currentJob) {
105
+ await this.cancelJob(this.currentJob.job.id);
106
+ }
107
+ // Clear timers
108
+ if (this.heartbeatTimer) {
109
+ clearInterval(this.heartbeatTimer);
110
+ this.heartbeatTimer = null;
111
+ }
112
+ if (this.idleTimer) {
113
+ clearTimeout(this.idleTimer);
114
+ this.idleTimer = null;
115
+ }
116
+ if (this.reconnectTimer) {
117
+ clearTimeout(this.reconnectTimer);
118
+ this.reconnectTimer = null;
119
+ }
120
+ // Disconnect from gateway
121
+ if (this.gatewaySocket) {
122
+ this.gatewaySocket.emit('agent:disconnect', { agentId: this.agentId });
123
+ this.gatewaySocket.disconnect();
124
+ this.gatewaySocket = null;
125
+ }
126
+ // Stop local server
127
+ if (this.localIO) {
128
+ this.localIO.close();
129
+ this.localIO = null;
130
+ }
131
+ if (this.localServer) {
132
+ await new Promise((resolve) => {
133
+ this.localServer.close(() => resolve());
134
+ });
135
+ this.localServer = null;
136
+ }
137
+ // Remove PID file
138
+ await fs.unlink(AGENT_PID_FILE).catch(() => { });
139
+ this.emit('disconnected', { reason: 'shutdown' });
140
+ }
141
+ /**
142
+ * Submit a job for execution
143
+ */
144
+ async submitJob(job) {
145
+ const fullJob = {
146
+ ...job,
147
+ id: uuidv4(),
148
+ status: 'queued',
149
+ submittedAt: new Date(),
150
+ logs: [],
151
+ };
152
+ this.jobQueue.push({
153
+ job: fullJob,
154
+ priority: 1,
155
+ submittedAt: new Date(),
156
+ });
157
+ this.jobLogs.set(fullJob.id, []);
158
+ // Process queue if not busy
159
+ if (!this.currentJob) {
160
+ this.processQueue();
161
+ }
162
+ this.resetIdleTimer();
163
+ return fullJob;
164
+ }
165
+ /**
166
+ * Get job by ID
167
+ */
168
+ getJob(jobId) {
169
+ // Check current job
170
+ if (this.currentJob?.job.id === jobId) {
171
+ return { ...this.currentJob.job, logs: this.jobLogs.get(jobId) || [] };
172
+ }
173
+ // Check queue
174
+ const queued = this.jobQueue.find((q) => q.job.id === jobId);
175
+ if (queued) {
176
+ return queued.job;
177
+ }
178
+ // Check completed
179
+ return this.completedJobs.get(jobId) || null;
180
+ }
181
+ /**
182
+ * List all jobs
183
+ */
184
+ listJobs(options) {
185
+ const jobs = [];
186
+ // Add current job
187
+ if (this.currentJob) {
188
+ jobs.push({ ...this.currentJob.job, logs: this.jobLogs.get(this.currentJob.job.id) || [] });
189
+ }
190
+ // Add queued jobs
191
+ jobs.push(...this.jobQueue.map((q) => q.job));
192
+ // Add completed jobs
193
+ jobs.push(...Array.from(this.completedJobs.values()));
194
+ // Filter by status
195
+ let filtered = options?.status
196
+ ? jobs.filter((j) => j.status === options.status)
197
+ : jobs;
198
+ // Sort by submission time (newest first)
199
+ filtered.sort((a, b) => b.submittedAt.getTime() - a.submittedAt.getTime());
200
+ // Limit results
201
+ if (options?.limit) {
202
+ filtered = filtered.slice(0, options.limit);
203
+ }
204
+ return filtered;
205
+ }
206
+ /**
207
+ * Cancel a job
208
+ */
209
+ async cancelJob(jobId) {
210
+ // Check if it's the current job
211
+ if (this.currentJob?.job.id === jobId) {
212
+ try {
213
+ process.kill(this.currentJob.pid, 'SIGTERM');
214
+ // Wait for process to exit
215
+ await new Promise((resolve) => {
216
+ const check = setInterval(() => {
217
+ try {
218
+ process.kill(this.currentJob.pid, 0);
219
+ }
220
+ catch {
221
+ clearInterval(check);
222
+ resolve();
223
+ }
224
+ }, 100);
225
+ // Force kill after 5 seconds
226
+ setTimeout(() => {
227
+ try {
228
+ process.kill(this.currentJob.pid, 'SIGKILL');
229
+ }
230
+ catch {
231
+ // Already dead
232
+ }
233
+ }, 5000);
234
+ });
235
+ this.currentJob.job.status = 'cancelled';
236
+ this.completedJobs.set(jobId, this.currentJob.job);
237
+ this.currentJob = null;
238
+ this.emit('job:cancelled', { jobId });
239
+ return true;
240
+ }
241
+ catch {
242
+ return false;
243
+ }
244
+ }
245
+ // Check queue
246
+ const queueIndex = this.jobQueue.findIndex((q) => q.job.id === jobId);
247
+ if (queueIndex >= 0) {
248
+ const [removed] = this.jobQueue.splice(queueIndex, 1);
249
+ removed.job.status = 'cancelled';
250
+ this.completedJobs.set(jobId, removed.job);
251
+ this.emit('job:cancelled', { jobId });
252
+ return true;
253
+ }
254
+ return false;
255
+ }
256
+ /**
257
+ * Get job logs
258
+ */
259
+ getJobLogs(jobId, tail) {
260
+ const logs = this.jobLogs.get(jobId) || [];
261
+ if (tail && tail > 0) {
262
+ return logs.slice(-tail);
263
+ }
264
+ return logs;
265
+ }
266
+ /**
267
+ * Get agent status for local CLI display
268
+ */
269
+ async getStatus() {
270
+ // Check if agent is running by reading PID file
271
+ let pid;
272
+ let uptime;
273
+ let isRunning = false;
274
+ try {
275
+ const pidStr = await fs.readFile(AGENT_PID_FILE, 'utf-8');
276
+ pid = parseInt(pidStr.trim(), 10);
277
+ // Check if process is still running
278
+ process.kill(pid, 0);
279
+ isRunning = true;
280
+ if (this.startTime) {
281
+ const uptimeMs = Date.now() - this.startTime.getTime();
282
+ const hours = Math.floor(uptimeMs / (1000 * 60 * 60));
283
+ const minutes = Math.floor((uptimeMs % (1000 * 60 * 60)) / (1000 * 60));
284
+ uptime = `${hours}h ${minutes}m`;
285
+ }
286
+ }
287
+ catch {
288
+ isRunning = false;
289
+ }
290
+ return {
291
+ running: isRunning || this.running,
292
+ pid,
293
+ uptime,
294
+ jobsCompleted: this.jobsCompleted,
295
+ jobsRunning: this.currentJob ? 1 : 0,
296
+ };
297
+ }
298
+ /**
299
+ * Get full agent status for HPC Gateway
300
+ */
301
+ getFullStatus() {
302
+ return {
303
+ id: this.agentId || '',
304
+ name: this.config.name,
305
+ status: this.currentJob ? 'busy' : 'idle',
306
+ registeredAt: this.startTime || new Date(),
307
+ lastHeartbeat: new Date(),
308
+ currentJob: this.currentJob?.job || null,
309
+ jobsCompleted: this.jobsCompleted,
310
+ jobsFailed: this.jobsFailed,
311
+ totalComputeTime: this.totalComputeTime,
312
+ hardware: this.hardware,
313
+ };
314
+ }
315
+ /**
316
+ * Start agent as a background daemon
317
+ */
318
+ async startDaemon() {
319
+ // Fork the process to run in background
320
+ const { fork } = await import('child_process');
321
+ const scriptPath = new URL(import.meta.url).pathname;
322
+ const child = fork(scriptPath, ['--daemon-mode'], {
323
+ detached: true,
324
+ stdio: 'ignore',
325
+ });
326
+ child.unref();
327
+ // Write PID file
328
+ await fs.mkdir(NEXUS_DIR, { recursive: true });
329
+ await fs.writeFile(AGENT_PID_FILE, child.pid?.toString() || '');
330
+ }
331
+ /**
332
+ * Check if another agent is already running
333
+ */
334
+ async isAnotherAgentRunning() {
335
+ try {
336
+ const pidStr = await fs.readFile(AGENT_PID_FILE, 'utf-8');
337
+ const pid = parseInt(pidStr.trim(), 10);
338
+ if (pid === process.pid) {
339
+ return false;
340
+ }
341
+ // Check if process is running
342
+ try {
343
+ process.kill(pid, 0);
344
+ return true;
345
+ }
346
+ catch {
347
+ // Process not running, stale PID file
348
+ await fs.unlink(AGENT_PID_FILE).catch(() => { });
349
+ return false;
350
+ }
351
+ }
352
+ catch {
353
+ return false;
354
+ }
355
+ }
356
+ /**
357
+ * Start local API server
358
+ */
359
+ async startLocalServer() {
360
+ this.localApp = express();
361
+ this.localApp.use(express.json());
362
+ // Health check
363
+ this.localApp.get('/health', (_req, res) => {
364
+ res.json({ status: 'ok', agentId: this.agentId });
365
+ });
366
+ // Status
367
+ this.localApp.get('/status', (_req, res) => {
368
+ res.json(this.getFullStatus());
369
+ });
370
+ // Submit job
371
+ this.localApp.post('/jobs', async (req, res) => {
372
+ try {
373
+ const job = await this.submitJob(req.body);
374
+ res.json(job);
375
+ }
376
+ catch (error) {
377
+ res.status(400).json({
378
+ error: error instanceof Error ? error.message : String(error),
379
+ });
380
+ }
381
+ });
382
+ // List jobs
383
+ this.localApp.get('/jobs', (req, res) => {
384
+ const jobs = this.listJobs({
385
+ status: req.query.status,
386
+ limit: req.query.limit ? parseInt(req.query.limit, 10) : undefined,
387
+ });
388
+ res.json({ jobs });
389
+ });
390
+ // Get job
391
+ this.localApp.get('/jobs/:jobId', (req, res) => {
392
+ const job = this.getJob(req.params.jobId);
393
+ if (job) {
394
+ res.json(job);
395
+ }
396
+ else {
397
+ res.status(404).json({ error: 'Job not found' });
398
+ }
399
+ });
400
+ // Get job logs
401
+ this.localApp.get('/jobs/:jobId/logs', (req, res) => {
402
+ const logs = this.getJobLogs(req.params.jobId, req.query.tail ? parseInt(req.query.tail, 10) : undefined);
403
+ res.json({ logs });
404
+ });
405
+ // Cancel job
406
+ this.localApp.post('/jobs/:jobId/cancel', async (req, res) => {
407
+ const success = await this.cancelJob(req.params.jobId);
408
+ if (success) {
409
+ res.json({ success: true });
410
+ }
411
+ else {
412
+ res.status(404).json({ error: 'Job not found or already completed' });
413
+ }
414
+ });
415
+ // Shutdown
416
+ this.localApp.post('/shutdown', async (_req, res) => {
417
+ res.json({ success: true });
418
+ setTimeout(() => this.stop(), 100);
419
+ });
420
+ // ========================================
421
+ // Jupyter Kernel Endpoints
422
+ // ========================================
423
+ // Create kernel
424
+ this.localApp.post('/kernels', async (req, res) => {
425
+ try {
426
+ const { language = 'python' } = req.body;
427
+ const kernel = await this.createKernel(language);
428
+ res.json(kernel);
429
+ }
430
+ catch (error) {
431
+ res.status(500).json({
432
+ error: error instanceof Error ? error.message : String(error),
433
+ });
434
+ }
435
+ });
436
+ // List kernels
437
+ this.localApp.get('/kernels', (_req, res) => {
438
+ const kernels = this.listKernels();
439
+ res.json({ kernels });
440
+ });
441
+ // Get kernel
442
+ this.localApp.get('/kernels/:kernelId', (req, res) => {
443
+ const kernel = this.getKernelSession(req.params.kernelId);
444
+ if (kernel) {
445
+ res.json(kernel);
446
+ }
447
+ else {
448
+ res.status(404).json({ error: 'Kernel not found' });
449
+ }
450
+ });
451
+ // Execute code
452
+ this.localApp.post('/kernels/:kernelId/execute', async (req, res) => {
453
+ try {
454
+ const result = await this.executeCode({
455
+ ...req.body,
456
+ kernelId: req.params.kernelId,
457
+ });
458
+ res.json(result);
459
+ }
460
+ catch (error) {
461
+ res.status(500).json({
462
+ error: error instanceof Error ? error.message : String(error),
463
+ });
464
+ }
465
+ });
466
+ // Execute code (auto-create kernel if needed)
467
+ this.localApp.post('/execute', async (req, res) => {
468
+ try {
469
+ const result = await this.executeCode(req.body);
470
+ res.json(result);
471
+ }
472
+ catch (error) {
473
+ res.status(500).json({
474
+ error: error instanceof Error ? error.message : String(error),
475
+ });
476
+ }
477
+ });
478
+ // Shutdown kernel
479
+ this.localApp.delete('/kernels/:kernelId', async (req, res) => {
480
+ try {
481
+ await this.shutdownKernel(req.params.kernelId);
482
+ res.json({ success: true });
483
+ }
484
+ catch (error) {
485
+ res.status(404).json({
486
+ error: error instanceof Error ? error.message : String(error),
487
+ });
488
+ }
489
+ });
490
+ // Interrupt kernel execution
491
+ this.localApp.post('/kernels/:kernelId/interrupt', async (req, res) => {
492
+ try {
493
+ const success = this.interruptKernel(req.params.kernelId);
494
+ if (success) {
495
+ res.json({ success: true });
496
+ }
497
+ else {
498
+ res.status(404).json({ error: 'Kernel not found or not running' });
499
+ }
500
+ }
501
+ catch (error) {
502
+ res.status(500).json({
503
+ error: error instanceof Error ? error.message : String(error),
504
+ });
505
+ }
506
+ });
507
+ // Start server
508
+ return new Promise((resolve, reject) => {
509
+ this.localServer = this.localApp.listen(this.config.apiPort, () => {
510
+ // Setup Socket.IO for log streaming
511
+ this.localIO = new SocketIOServer(this.localServer);
512
+ this.localIO.on('connection', (socket) => {
513
+ // Job log subscriptions
514
+ socket.on('subscribe:logs', ({ jobId }) => {
515
+ socket.join(`logs:${jobId}`);
516
+ });
517
+ // Kernel output subscriptions
518
+ socket.on('subscribe:kernel', ({ kernelId }) => {
519
+ socket.join(`kernel:${kernelId}`);
520
+ });
521
+ socket.on('unsubscribe:kernel', ({ kernelId }) => {
522
+ socket.leave(`kernel:${kernelId}`);
523
+ });
524
+ });
525
+ resolve();
526
+ });
527
+ this.localServer.on('error', (error) => {
528
+ if (error.code === 'EADDRINUSE') {
529
+ reject(new Error(`Port ${this.config.apiPort} is already in use`));
530
+ }
531
+ else {
532
+ reject(error);
533
+ }
534
+ });
535
+ });
536
+ }
537
+ /**
538
+ * Connect to HPC Gateway
539
+ */
540
+ async connectToGateway() {
541
+ if (!this.hardware) {
542
+ throw new Error('Hardware not detected');
543
+ }
544
+ const wsUrl = this.config.gatewayUrl
545
+ .replace('http://', 'ws://')
546
+ .replace('https://', 'wss://');
547
+ return new Promise((resolve, reject) => {
548
+ this.gatewaySocket = io(wsUrl, {
549
+ transports: ['websocket'],
550
+ reconnection: false,
551
+ timeout: 10000,
552
+ });
553
+ const timeout = setTimeout(() => {
554
+ reject(new Error('Gateway connection timeout'));
555
+ }, 10000);
556
+ this.gatewaySocket.on('connect', () => {
557
+ clearTimeout(timeout);
558
+ this.reconnectAttempts = 0;
559
+ // Register with gateway
560
+ const registration = {
561
+ type: 'local-compute',
562
+ name: this.config.name,
563
+ hostname: os.hostname(),
564
+ capabilities: {
565
+ gpuType: this.hardware.gpu?.type || 'none',
566
+ gpuMemory: this.hardware.gpu?.memory || 0,
567
+ cpuCores: this.hardware.cpu.cores,
568
+ ramTotal: this.hardware.memory.total,
569
+ frameworks: this.hardware.frameworks
570
+ .filter((f) => f.available)
571
+ .map((f) => f.name.toLowerCase()),
572
+ metalVersion: this.hardware.gpu?.api === 'Metal 3' ? 3 : undefined,
573
+ computeCapability: this.hardware.gpu?.computeCapability,
574
+ neuralEngine: this.hardware.gpu?.neuralEngine,
575
+ neuralEngineTops: this.hardware.gpu?.neuralEngineTops,
576
+ },
577
+ config: {
578
+ maxMemoryPercent: this.config.maxMemoryPercent,
579
+ allowRemoteJobs: this.config.allowRemoteJobs,
580
+ idleTimeoutMinutes: this.config.idleTimeoutMinutes,
581
+ },
582
+ };
583
+ this.gatewaySocket.emit('agent:register', registration);
584
+ resolve();
585
+ });
586
+ this.gatewaySocket.on('connect_error', (error) => {
587
+ clearTimeout(timeout);
588
+ this.emit('error', {
589
+ code: 'CONNECTION_ERROR',
590
+ message: error.message,
591
+ });
592
+ this.scheduleReconnect();
593
+ });
594
+ this.gatewaySocket.on('disconnect', (reason) => {
595
+ this.emit('disconnected', { reason });
596
+ if (this.running && reason !== 'io client disconnect') {
597
+ this.scheduleReconnect();
598
+ }
599
+ });
600
+ // Handle remote job assignment (if allowRemoteJobs is true)
601
+ this.gatewaySocket.on('job:assign', async (data) => {
602
+ if (this.config.allowRemoteJobs) {
603
+ try {
604
+ const job = await this.submitJob(data);
605
+ this.gatewaySocket.emit('job:accepted', { jobId: job.id });
606
+ }
607
+ catch (error) {
608
+ this.gatewaySocket.emit('job:rejected', {
609
+ error: error instanceof Error ? error.message : String(error),
610
+ });
611
+ }
612
+ }
613
+ else {
614
+ this.gatewaySocket.emit('job:rejected', {
615
+ error: 'Remote jobs not allowed',
616
+ });
617
+ }
618
+ });
619
+ });
620
+ }
621
+ /**
622
+ * Schedule reconnection attempt
623
+ */
624
+ scheduleReconnect() {
625
+ if (!this.running)
626
+ return;
627
+ if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
628
+ this.emit('error', {
629
+ code: 'MAX_RECONNECT_ATTEMPTS',
630
+ message: 'Maximum reconnection attempts reached',
631
+ });
632
+ return;
633
+ }
634
+ const delay = Math.min(this.config.reconnectInterval * Math.pow(2, this.reconnectAttempts), 60000);
635
+ this.reconnectAttempts++;
636
+ this.emit('reconnecting', { attempt: this.reconnectAttempts, delay });
637
+ this.reconnectTimer = setTimeout(() => {
638
+ this.connectToGateway().catch(() => {
639
+ // Error handled in connect
640
+ });
641
+ }, delay);
642
+ }
643
+ /**
644
+ * Start heartbeat to gateway
645
+ */
646
+ startHeartbeat() {
647
+ this.heartbeatTimer = setInterval(() => {
648
+ if (this.gatewaySocket?.connected) {
649
+ this.gatewaySocket.emit('agent:heartbeat', {
650
+ agentId: this.agentId,
651
+ status: this.currentJob ? 'busy' : 'idle',
652
+ currentJobId: this.currentJob?.job.id,
653
+ jobsCompleted: this.jobsCompleted,
654
+ jobsFailed: this.jobsFailed,
655
+ });
656
+ this.emit('heartbeat', { timestamp: new Date() });
657
+ }
658
+ }, 30000);
659
+ }
660
+ /**
661
+ * Reset idle timer
662
+ */
663
+ resetIdleTimer() {
664
+ if (this.idleTimer) {
665
+ clearTimeout(this.idleTimer);
666
+ }
667
+ if (this.config.idleTimeoutMinutes > 0 && !this.currentJob && this.jobQueue.length === 0) {
668
+ this.idleTimer = setTimeout(() => {
669
+ console.log('Idle timeout reached, shutting down...');
670
+ this.stop();
671
+ }, this.config.idleTimeoutMinutes * 60 * 1000);
672
+ }
673
+ }
674
+ /**
675
+ * Process job queue
676
+ */
677
+ async processQueue() {
678
+ if (this.currentJob || this.jobQueue.length === 0) {
679
+ this.resetIdleTimer();
680
+ return;
681
+ }
682
+ // Get highest priority job
683
+ this.jobQueue.sort((a, b) => b.priority - a.priority);
684
+ const queuedJob = this.jobQueue.shift();
685
+ if (!queuedJob) {
686
+ this.resetIdleTimer();
687
+ return;
688
+ }
689
+ await this.executeJob(queuedJob.job);
690
+ }
691
+ /**
692
+ * Execute a job
693
+ */
694
+ async executeJob(job) {
695
+ job.status = 'running';
696
+ job.startedAt = new Date();
697
+ this.emit('job:started', { jobId: job.id });
698
+ // Build environment (filter out undefined values)
699
+ const env = Object.fromEntries(Object.entries({ ...process.env, ...job.environment })
700
+ .filter((entry) => entry[1] !== undefined));
701
+ // Set framework-specific environment
702
+ if (this.hardware?.gpu?.type.includes('Apple M')) {
703
+ env.PYTORCH_ENABLE_MPS_FALLBACK = '1';
704
+ }
705
+ // Determine command
706
+ let command;
707
+ let args;
708
+ if (job.scriptPath) {
709
+ if (job.scriptPath.endsWith('.py')) {
710
+ command = 'python3';
711
+ args = [job.scriptPath];
712
+ }
713
+ else {
714
+ command = 'bash';
715
+ args = [job.scriptPath];
716
+ }
717
+ }
718
+ else {
719
+ command = 'python3';
720
+ args = ['-c', job.script];
721
+ }
722
+ // Spawn process
723
+ const childProcess = spawn(command, args, {
724
+ cwd: job.workingDir,
725
+ env: env,
726
+ stdio: ['pipe', 'pipe', 'pipe'],
727
+ });
728
+ this.currentJob = {
729
+ pid: childProcess.pid,
730
+ job,
731
+ startTime: new Date(),
732
+ logBuffer: [],
733
+ };
734
+ const logs = this.jobLogs.get(job.id) || [];
735
+ // Capture stdout
736
+ childProcess.stdout?.on('data', (data) => {
737
+ const line = data.toString();
738
+ logs.push(line);
739
+ this.currentJob.logBuffer.push(line);
740
+ this.emit('job:log', { jobId: job.id, line, timestamp: new Date() });
741
+ // Broadcast to WebSocket clients
742
+ if (this.localIO) {
743
+ this.localIO.to(`logs:${job.id}`).emit('log', { line });
744
+ }
745
+ });
746
+ // Capture stderr
747
+ childProcess.stderr?.on('data', (data) => {
748
+ const line = `[stderr] ${data.toString()}`;
749
+ logs.push(line);
750
+ this.currentJob.logBuffer.push(line);
751
+ this.emit('job:log', { jobId: job.id, line, timestamp: new Date() });
752
+ if (this.localIO) {
753
+ this.localIO.to(`logs:${job.id}`).emit('log', { line });
754
+ }
755
+ });
756
+ // Handle completion
757
+ return new Promise((resolve) => {
758
+ childProcess.on('exit', (code, signal) => {
759
+ const endTime = new Date();
760
+ const durationSeconds = (endTime.getTime() - this.currentJob.startTime.getTime()) / 1000;
761
+ job.completedAt = endTime;
762
+ job.exitCode = code ?? (signal ? 128 : 1);
763
+ job.logs = [...logs];
764
+ const metrics = {
765
+ peakMemoryGb: 0, // Would need to track during execution
766
+ cpuUtilization: 0,
767
+ durationSeconds,
768
+ };
769
+ job.metrics = metrics;
770
+ if (code === 0) {
771
+ job.status = 'completed';
772
+ this.jobsCompleted++;
773
+ this.emit('job:completed', { jobId: job.id, exitCode: code, metrics });
774
+ if (this.localIO) {
775
+ this.localIO.to(`logs:${job.id}`).emit('job:completed', { exitCode: code });
776
+ }
777
+ }
778
+ else {
779
+ job.status = 'failed';
780
+ job.error = signal
781
+ ? `Process killed by signal: ${signal}`
782
+ : `Process exited with code: ${code}`;
783
+ this.jobsFailed++;
784
+ this.emit('job:failed', { jobId: job.id, error: job.error });
785
+ if (this.localIO) {
786
+ this.localIO.to(`logs:${job.id}`).emit('job:failed', { error: job.error });
787
+ }
788
+ }
789
+ this.totalComputeTime += durationSeconds;
790
+ this.completedJobs.set(job.id, job);
791
+ this.currentJob = null;
792
+ // Report to gateway
793
+ if (this.gatewaySocket?.connected) {
794
+ this.gatewaySocket.emit('job:complete', {
795
+ agentId: this.agentId,
796
+ jobId: job.id,
797
+ status: job.status,
798
+ exitCode: job.exitCode,
799
+ metrics,
800
+ });
801
+ }
802
+ // Process next job
803
+ this.processQueue();
804
+ resolve();
805
+ });
806
+ childProcess.on('error', (error) => {
807
+ job.status = 'failed';
808
+ job.error = error.message;
809
+ job.completedAt = new Date();
810
+ this.jobsFailed++;
811
+ this.emit('job:failed', { jobId: job.id, error: error.message });
812
+ this.completedJobs.set(job.id, job);
813
+ this.currentJob = null;
814
+ this.processQueue();
815
+ resolve();
816
+ });
817
+ });
818
+ }
819
+ // ========================================
820
+ // Kernel Management Methods
821
+ // ========================================
822
+ /**
823
+ * Create a new kernel session
824
+ */
825
+ async createKernel(language = 'python') {
826
+ const kernelId = uuidv4();
827
+ const session = {
828
+ id: kernelId,
829
+ language,
830
+ createdAt: new Date(),
831
+ lastActivity: new Date(),
832
+ status: 'starting',
833
+ executionCount: 0,
834
+ };
835
+ this.kernelSessions.set(kernelId, session);
836
+ this.kernelOutputBuffers.set(kernelId, []);
837
+ // For Python, we use a persistent Python subprocess
838
+ // that can execute multiple code blocks
839
+ const pythonProcess = spawn('python3', ['-u', '-i', '-q'], {
840
+ stdio: ['pipe', 'pipe', 'pipe'],
841
+ env: {
842
+ ...process.env,
843
+ PYTHONUNBUFFERED: '1',
844
+ // Enable Apple MPS if available
845
+ PYTORCH_ENABLE_MPS_FALLBACK: '1',
846
+ },
847
+ });
848
+ this.kernelProcesses.set(kernelId, pythonProcess);
849
+ // Initialize the Python environment
850
+ const initCode = `
851
+ import sys
852
+ import json
853
+ import traceback
854
+
855
+ # Set up output capture
856
+ class OutputCapture:
857
+ def __init__(self, stream_type):
858
+ self.stream_type = stream_type
859
+ self.original = getattr(sys, stream_type)
860
+
861
+ def write(self, text):
862
+ self.original.write(text)
863
+ self.original.flush()
864
+
865
+ def flush(self):
866
+ self.original.flush()
867
+
868
+ sys.stdout = OutputCapture('stdout')
869
+ sys.stderr = OutputCapture('stderr')
870
+
871
+ # Import common ML libraries if available
872
+ try:
873
+ import numpy as np
874
+ except ImportError:
875
+ pass
876
+ try:
877
+ import torch
878
+ if torch.backends.mps.is_available():
879
+ print("MPS (Apple Silicon GPU) is available")
880
+ except ImportError:
881
+ pass
882
+ try:
883
+ import mlx
884
+ print("MLX (Apple ML framework) is available")
885
+ except ImportError:
886
+ pass
887
+
888
+ print("__KERNEL_READY__")
889
+ `;
890
+ pythonProcess.stdin?.write(initCode);
891
+ pythonProcess.stdin?.write('\n');
892
+ // Wait for kernel to be ready
893
+ await new Promise((resolve, reject) => {
894
+ const timeout = setTimeout(() => {
895
+ reject(new Error('Kernel startup timeout'));
896
+ }, 30000);
897
+ const checkReady = (data) => {
898
+ if (data.toString().includes('__KERNEL_READY__')) {
899
+ clearTimeout(timeout);
900
+ pythonProcess.stdout?.off('data', checkReady);
901
+ session.status = 'idle';
902
+ this.kernelSessions.set(kernelId, session);
903
+ resolve();
904
+ }
905
+ };
906
+ pythonProcess.stdout?.on('data', checkReady);
907
+ pythonProcess.on('error', (err) => {
908
+ clearTimeout(timeout);
909
+ reject(err);
910
+ });
911
+ });
912
+ // Broadcast via WebSocket
913
+ if (this.localIO) {
914
+ this.localIO.emit('kernel:created', { kernelId, session });
915
+ }
916
+ return session;
917
+ }
918
+ /**
919
+ * Execute code in a kernel
920
+ */
921
+ async executeCode(request) {
922
+ const startTime = Date.now();
923
+ let kernelId = request.kernelId;
924
+ // Auto-create kernel if not specified
925
+ if (!kernelId || !this.kernelSessions.has(kernelId)) {
926
+ const session = await this.createKernel('python');
927
+ kernelId = session.id;
928
+ }
929
+ const session = this.kernelSessions.get(kernelId);
930
+ const process = this.kernelProcesses.get(kernelId);
931
+ if (!session || !process) {
932
+ throw new Error('Kernel not found');
933
+ }
934
+ // Update session status
935
+ session.status = 'busy';
936
+ session.lastActivity = new Date();
937
+ this.kernelSessions.set(kernelId, session);
938
+ if (this.localIO) {
939
+ this.localIO.emit('kernel:status', { kernelId, status: 'busy' });
940
+ }
941
+ const outputs = [];
942
+ let errorResult;
943
+ // Generate execution marker
944
+ const execId = uuidv4().slice(0, 8);
945
+ const startMarker = `__EXEC_START_${execId}__`;
946
+ const endMarker = `__EXEC_END_${execId}__`;
947
+ const errorMarker = `__EXEC_ERROR_${execId}__`;
948
+ // Wrap code to capture output and detect completion
949
+ const wrappedCode = `
950
+ print("${startMarker}")
951
+ try:
952
+ exec(${JSON.stringify(request.code)})
953
+ print("${endMarker}")
954
+ except Exception as e:
955
+ import traceback
956
+ print("${errorMarker}")
957
+ print(json.dumps({
958
+ "name": type(e).__name__,
959
+ "value": str(e),
960
+ "traceback": traceback.format_exc().split("\\n")
961
+ }))
962
+ print("${endMarker}")
963
+ `;
964
+ return new Promise((resolve) => {
965
+ let outputBuffer = '';
966
+ let inExecution = false;
967
+ let gotError = false;
968
+ const handleOutput = (data, isStderr) => {
969
+ const text = data.toString();
970
+ outputBuffer += text;
971
+ // Check for start marker
972
+ if (outputBuffer.includes(startMarker)) {
973
+ inExecution = true;
974
+ outputBuffer = outputBuffer.split(startMarker)[1] || '';
975
+ }
976
+ // Check for error marker
977
+ if (outputBuffer.includes(errorMarker)) {
978
+ gotError = true;
979
+ const parts = outputBuffer.split(errorMarker);
980
+ outputBuffer = parts[1] || '';
981
+ }
982
+ // Check for end marker
983
+ if (inExecution && outputBuffer.includes(endMarker)) {
984
+ const outputText = outputBuffer.split(endMarker)[0];
985
+ // Parse error if present
986
+ if (gotError) {
987
+ try {
988
+ const errorData = JSON.parse(outputText.trim());
989
+ errorResult = {
990
+ name: errorData.name,
991
+ value: errorData.value,
992
+ traceback: errorData.traceback,
993
+ };
994
+ }
995
+ catch {
996
+ errorResult = {
997
+ name: 'ExecutionError',
998
+ value: outputText,
999
+ traceback: [],
1000
+ };
1001
+ }
1002
+ }
1003
+ else if (outputText.trim()) {
1004
+ outputs.push({
1005
+ type: 'stream',
1006
+ name: isStderr ? 'stderr' : 'stdout',
1007
+ text: outputText,
1008
+ });
1009
+ // Broadcast output
1010
+ if (this.localIO) {
1011
+ this.localIO.emit('kernel:output', {
1012
+ kernelId,
1013
+ output: outputs[outputs.length - 1],
1014
+ });
1015
+ }
1016
+ }
1017
+ // Cleanup listeners
1018
+ process.stdout?.off('data', stdoutHandler);
1019
+ process.stderr?.off('data', stderrHandler);
1020
+ // Update session
1021
+ session.status = 'idle';
1022
+ session.executionCount++;
1023
+ session.lastActivity = new Date();
1024
+ this.kernelSessions.set(kernelId, session);
1025
+ const result = {
1026
+ executionCount: session.executionCount,
1027
+ status: errorResult ? 'error' : 'ok',
1028
+ outputs,
1029
+ error: errorResult,
1030
+ duration: Date.now() - startTime,
1031
+ };
1032
+ if (this.localIO) {
1033
+ this.localIO.emit('kernel:status', { kernelId, status: 'idle' });
1034
+ this.localIO.emit('kernel:result', { kernelId, result });
1035
+ }
1036
+ resolve(result);
1037
+ }
1038
+ else if (inExecution && !gotError) {
1039
+ // Stream intermediate output
1040
+ const output = {
1041
+ type: 'stream',
1042
+ name: isStderr ? 'stderr' : 'stdout',
1043
+ text,
1044
+ };
1045
+ outputs.push(output);
1046
+ if (this.localIO) {
1047
+ this.localIO.emit('kernel:output', { kernelId, output });
1048
+ }
1049
+ }
1050
+ };
1051
+ const stdoutHandler = (data) => handleOutput(data, false);
1052
+ const stderrHandler = (data) => handleOutput(data, true);
1053
+ process.stdout?.on('data', stdoutHandler);
1054
+ process.stderr?.on('data', stderrHandler);
1055
+ // Send code to kernel
1056
+ process.stdin?.write(wrappedCode);
1057
+ process.stdin?.write('\n');
1058
+ // Timeout after 5 minutes
1059
+ setTimeout(() => {
1060
+ process.stdout?.off('data', stdoutHandler);
1061
+ process.stderr?.off('data', stderrHandler);
1062
+ session.status = 'idle';
1063
+ this.kernelSessions.set(kernelId, session);
1064
+ resolve({
1065
+ executionCount: session.executionCount,
1066
+ status: 'error',
1067
+ outputs,
1068
+ error: {
1069
+ name: 'TimeoutError',
1070
+ value: 'Execution timed out after 5 minutes',
1071
+ traceback: [],
1072
+ },
1073
+ duration: Date.now() - startTime,
1074
+ });
1075
+ }, 300000);
1076
+ });
1077
+ }
1078
+ /**
1079
+ * Shutdown a kernel
1080
+ */
1081
+ async shutdownKernel(kernelId) {
1082
+ const session = this.kernelSessions.get(kernelId);
1083
+ const process = this.kernelProcesses.get(kernelId);
1084
+ if (!session || !process) {
1085
+ throw new Error('Kernel not found');
1086
+ }
1087
+ // Send quit command
1088
+ process.stdin?.write('quit()\n');
1089
+ // Wait for process to exit or force kill
1090
+ await new Promise((resolve) => {
1091
+ const timeout = setTimeout(() => {
1092
+ process.kill('SIGKILL');
1093
+ resolve();
1094
+ }, 5000);
1095
+ process.on('exit', () => {
1096
+ clearTimeout(timeout);
1097
+ resolve();
1098
+ });
1099
+ });
1100
+ // Cleanup
1101
+ this.kernelSessions.delete(kernelId);
1102
+ this.kernelProcesses.delete(kernelId);
1103
+ this.kernelOutputBuffers.delete(kernelId);
1104
+ if (this.localIO) {
1105
+ this.localIO.emit('kernel:shutdown', { kernelId });
1106
+ }
1107
+ }
1108
+ /**
1109
+ * Get kernel session info
1110
+ */
1111
+ getKernelSession(kernelId) {
1112
+ return this.kernelSessions.get(kernelId) || null;
1113
+ }
1114
+ /**
1115
+ * List all active kernels
1116
+ */
1117
+ listKernels() {
1118
+ return Array.from(this.kernelSessions.values());
1119
+ }
1120
+ /**
1121
+ * Interrupt kernel execution
1122
+ */
1123
+ interruptKernel(kernelId) {
1124
+ const process = this.kernelProcesses.get(kernelId);
1125
+ if (!process) {
1126
+ return false;
1127
+ }
1128
+ try {
1129
+ process.kill('SIGINT');
1130
+ const session = this.kernelSessions.get(kernelId);
1131
+ if (session) {
1132
+ session.status = 'idle';
1133
+ this.kernelSessions.set(kernelId, session);
1134
+ }
1135
+ return true;
1136
+ }
1137
+ catch {
1138
+ return false;
1139
+ }
1140
+ }
1141
+ /**
1142
+ * Shutdown all kernels (called on agent stop)
1143
+ */
1144
+ async shutdownAllKernels() {
1145
+ const kernelIds = Array.from(this.kernelSessions.keys());
1146
+ await Promise.all(kernelIds.map((id) => this.shutdownKernel(id).catch(() => { })));
1147
+ }
1148
+ /**
1149
+ * Setup graceful shutdown handlers
1150
+ */
1151
+ setupShutdownHandlers() {
1152
+ const shutdown = async () => {
1153
+ console.log('\nShutting down compute agent...');
1154
+ await this.stop();
1155
+ process.exit(0);
1156
+ };
1157
+ process.on('SIGINT', shutdown);
1158
+ process.on('SIGTERM', shutdown);
1159
+ }
1160
+ }
1161
+ export default LocalComputeAgent;
1162
+ //# sourceMappingURL=local-compute-agent.js.map