@soederpop/luca 0.1.2 → 0.2.1

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 (381) hide show
  1. package/.github/workflows/release.yaml +167 -0
  2. package/CLAUDE.md +2 -0
  3. package/README.md +3 -0
  4. package/assistants/codingAssistant/ABOUT.md +3 -0
  5. package/assistants/codingAssistant/CORE.md +22 -17
  6. package/assistants/codingAssistant/hooks.ts +17 -4
  7. package/assistants/codingAssistant/tools.ts +1 -106
  8. package/assistants/inkbot/ABOUT.md +5 -0
  9. package/assistants/inkbot/CORE.md +71 -0
  10. package/assistants/inkbot/hooks.ts +14 -0
  11. package/assistants/inkbot/tools.ts +47 -0
  12. package/bun.lock +20 -4
  13. package/commands/inkbot.ts +353 -0
  14. package/commands/release.ts +75 -181
  15. package/dist/agi/container.server.d.ts +63 -0
  16. package/dist/agi/container.server.d.ts.map +1 -0
  17. package/dist/agi/endpoints/ask.d.ts +20 -0
  18. package/dist/agi/endpoints/ask.d.ts.map +1 -0
  19. package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
  20. package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
  21. package/dist/agi/endpoints/conversations.d.ts +18 -0
  22. package/dist/agi/endpoints/conversations.d.ts.map +1 -0
  23. package/dist/agi/endpoints/experts.d.ts +8 -0
  24. package/dist/agi/endpoints/experts.d.ts.map +1 -0
  25. package/dist/agi/feature.d.ts +9 -0
  26. package/dist/agi/feature.d.ts.map +1 -0
  27. package/dist/agi/features/assistant.d.ts +509 -0
  28. package/dist/agi/features/assistant.d.ts.map +1 -0
  29. package/dist/agi/features/assistants-manager.d.ts +236 -0
  30. package/dist/agi/features/assistants-manager.d.ts.map +1 -0
  31. package/dist/agi/features/autonomous-assistant.d.ts +281 -0
  32. package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
  33. package/dist/agi/features/browser-use.d.ts +479 -0
  34. package/dist/agi/features/browser-use.d.ts.map +1 -0
  35. package/dist/agi/features/claude-code.d.ts +824 -0
  36. package/dist/agi/features/claude-code.d.ts.map +1 -0
  37. package/dist/agi/features/conversation-history.d.ts +245 -0
  38. package/dist/agi/features/conversation-history.d.ts.map +1 -0
  39. package/dist/agi/features/conversation.d.ts +464 -0
  40. package/dist/agi/features/conversation.d.ts.map +1 -0
  41. package/dist/agi/features/docs-reader.d.ts +72 -0
  42. package/dist/agi/features/docs-reader.d.ts.map +1 -0
  43. package/dist/agi/features/file-tools.d.ts +110 -0
  44. package/dist/agi/features/file-tools.d.ts.map +1 -0
  45. package/dist/agi/features/luca-coder.d.ts +323 -0
  46. package/dist/agi/features/luca-coder.d.ts.map +1 -0
  47. package/dist/agi/features/openai-codex.d.ts +381 -0
  48. package/dist/agi/features/openai-codex.d.ts.map +1 -0
  49. package/dist/agi/features/openapi.d.ts +200 -0
  50. package/dist/agi/features/openapi.d.ts.map +1 -0
  51. package/dist/agi/features/skills-library.d.ts +167 -0
  52. package/dist/agi/features/skills-library.d.ts.map +1 -0
  53. package/dist/agi/index.d.ts +5 -0
  54. package/dist/agi/index.d.ts.map +1 -0
  55. package/dist/agi/lib/interceptor-chain.d.ts +44 -0
  56. package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
  57. package/dist/agi/lib/token-counter.d.ts +13 -0
  58. package/dist/agi/lib/token-counter.d.ts.map +1 -0
  59. package/dist/bootstrap/generated.d.ts +5 -0
  60. package/dist/bootstrap/generated.d.ts.map +1 -0
  61. package/dist/browser.d.ts +12 -0
  62. package/dist/browser.d.ts.map +1 -0
  63. package/dist/bus.d.ts +29 -0
  64. package/dist/bus.d.ts.map +1 -0
  65. package/dist/cli/build-info.d.ts +4 -0
  66. package/dist/cli/build-info.d.ts.map +1 -0
  67. package/dist/cli/cli.d.ts +3 -0
  68. package/dist/cli/cli.d.ts.map +1 -0
  69. package/dist/client.d.ts +60 -0
  70. package/dist/client.d.ts.map +1 -0
  71. package/dist/clients/civitai/index.d.ts +472 -0
  72. package/dist/clients/civitai/index.d.ts.map +1 -0
  73. package/dist/clients/client-template.d.ts +30 -0
  74. package/dist/clients/client-template.d.ts.map +1 -0
  75. package/dist/clients/comfyui/index.d.ts +281 -0
  76. package/dist/clients/comfyui/index.d.ts.map +1 -0
  77. package/dist/clients/elevenlabs/index.d.ts +197 -0
  78. package/dist/clients/elevenlabs/index.d.ts.map +1 -0
  79. package/dist/clients/graph.d.ts +64 -0
  80. package/dist/clients/graph.d.ts.map +1 -0
  81. package/dist/clients/openai/index.d.ts +247 -0
  82. package/dist/clients/openai/index.d.ts.map +1 -0
  83. package/dist/clients/rest.d.ts +92 -0
  84. package/dist/clients/rest.d.ts.map +1 -0
  85. package/dist/clients/supabase/index.d.ts +176 -0
  86. package/dist/clients/supabase/index.d.ts.map +1 -0
  87. package/dist/clients/websocket.d.ts +127 -0
  88. package/dist/clients/websocket.d.ts.map +1 -0
  89. package/dist/command.d.ts +163 -0
  90. package/dist/command.d.ts.map +1 -0
  91. package/dist/commands/bootstrap.d.ts +20 -0
  92. package/dist/commands/bootstrap.d.ts.map +1 -0
  93. package/dist/commands/chat.d.ts +37 -0
  94. package/dist/commands/chat.d.ts.map +1 -0
  95. package/dist/commands/code.d.ts +28 -0
  96. package/dist/commands/code.d.ts.map +1 -0
  97. package/dist/commands/console.d.ts +22 -0
  98. package/dist/commands/console.d.ts.map +1 -0
  99. package/dist/commands/describe.d.ts +50 -0
  100. package/dist/commands/describe.d.ts.map +1 -0
  101. package/dist/commands/eval.d.ts +23 -0
  102. package/dist/commands/eval.d.ts.map +1 -0
  103. package/dist/commands/help.d.ts +25 -0
  104. package/dist/commands/help.d.ts.map +1 -0
  105. package/dist/commands/index.d.ts +18 -0
  106. package/dist/commands/index.d.ts.map +1 -0
  107. package/dist/commands/introspect.d.ts +24 -0
  108. package/dist/commands/introspect.d.ts.map +1 -0
  109. package/dist/commands/mcp.d.ts +35 -0
  110. package/dist/commands/mcp.d.ts.map +1 -0
  111. package/dist/commands/prompt.d.ts +38 -0
  112. package/dist/commands/prompt.d.ts.map +1 -0
  113. package/dist/commands/run.d.ts +24 -0
  114. package/dist/commands/run.d.ts.map +1 -0
  115. package/dist/commands/sandbox-mcp.d.ts +34 -0
  116. package/dist/commands/sandbox-mcp.d.ts.map +1 -0
  117. package/dist/commands/save-api-docs.d.ts +21 -0
  118. package/dist/commands/save-api-docs.d.ts.map +1 -0
  119. package/dist/commands/scaffold.d.ts +24 -0
  120. package/dist/commands/scaffold.d.ts.map +1 -0
  121. package/dist/commands/select.d.ts +22 -0
  122. package/dist/commands/select.d.ts.map +1 -0
  123. package/dist/commands/serve.d.ts +29 -0
  124. package/dist/commands/serve.d.ts.map +1 -0
  125. package/dist/container-describer.d.ts +144 -0
  126. package/dist/container-describer.d.ts.map +1 -0
  127. package/dist/container.d.ts +451 -0
  128. package/dist/container.d.ts.map +1 -0
  129. package/dist/endpoint.d.ts +113 -0
  130. package/dist/endpoint.d.ts.map +1 -0
  131. package/dist/feature.d.ts +47 -0
  132. package/dist/feature.d.ts.map +1 -0
  133. package/dist/graft.d.ts +29 -0
  134. package/dist/graft.d.ts.map +1 -0
  135. package/dist/hash-object.d.ts +8 -0
  136. package/dist/hash-object.d.ts.map +1 -0
  137. package/dist/helper.d.ts +209 -0
  138. package/dist/helper.d.ts.map +1 -0
  139. package/dist/introspection/generated.node.d.ts +44623 -0
  140. package/dist/introspection/generated.node.d.ts.map +1 -0
  141. package/dist/introspection/generated.web.d.ts +1412 -0
  142. package/dist/introspection/generated.web.d.ts.map +1 -0
  143. package/dist/introspection/index.d.ts +156 -0
  144. package/dist/introspection/index.d.ts.map +1 -0
  145. package/dist/introspection/scan.d.ts +147 -0
  146. package/dist/introspection/scan.d.ts.map +1 -0
  147. package/dist/node/container.d.ts +256 -0
  148. package/dist/node/container.d.ts.map +1 -0
  149. package/dist/node/feature.d.ts +9 -0
  150. package/dist/node/feature.d.ts.map +1 -0
  151. package/dist/node/features/container-link.d.ts +213 -0
  152. package/dist/node/features/container-link.d.ts.map +1 -0
  153. package/dist/node/features/content-db.d.ts +354 -0
  154. package/dist/node/features/content-db.d.ts.map +1 -0
  155. package/dist/node/features/disk-cache.d.ts +236 -0
  156. package/dist/node/features/disk-cache.d.ts.map +1 -0
  157. package/dist/node/features/dns.d.ts +511 -0
  158. package/dist/node/features/dns.d.ts.map +1 -0
  159. package/dist/node/features/docker.d.ts +485 -0
  160. package/dist/node/features/docker.d.ts.map +1 -0
  161. package/dist/node/features/downloader.d.ts +73 -0
  162. package/dist/node/features/downloader.d.ts.map +1 -0
  163. package/dist/node/features/figlet-fonts.d.ts +4 -0
  164. package/dist/node/features/figlet-fonts.d.ts.map +1 -0
  165. package/dist/node/features/file-manager.d.ts +177 -0
  166. package/dist/node/features/file-manager.d.ts.map +1 -0
  167. package/dist/node/features/fs.d.ts +635 -0
  168. package/dist/node/features/fs.d.ts.map +1 -0
  169. package/dist/node/features/git.d.ts +329 -0
  170. package/dist/node/features/git.d.ts.map +1 -0
  171. package/dist/node/features/google-auth.d.ts +200 -0
  172. package/dist/node/features/google-auth.d.ts.map +1 -0
  173. package/dist/node/features/google-calendar.d.ts +194 -0
  174. package/dist/node/features/google-calendar.d.ts.map +1 -0
  175. package/dist/node/features/google-docs.d.ts +138 -0
  176. package/dist/node/features/google-docs.d.ts.map +1 -0
  177. package/dist/node/features/google-drive.d.ts +202 -0
  178. package/dist/node/features/google-drive.d.ts.map +1 -0
  179. package/dist/node/features/google-mail.d.ts +221 -0
  180. package/dist/node/features/google-mail.d.ts.map +1 -0
  181. package/dist/node/features/google-sheets.d.ts +157 -0
  182. package/dist/node/features/google-sheets.d.ts.map +1 -0
  183. package/dist/node/features/grep.d.ts +207 -0
  184. package/dist/node/features/grep.d.ts.map +1 -0
  185. package/dist/node/features/helpers.d.ts +236 -0
  186. package/dist/node/features/helpers.d.ts.map +1 -0
  187. package/dist/node/features/ink.d.ts +332 -0
  188. package/dist/node/features/ink.d.ts.map +1 -0
  189. package/dist/node/features/ipc-socket.d.ts +298 -0
  190. package/dist/node/features/ipc-socket.d.ts.map +1 -0
  191. package/dist/node/features/json-tree.d.ts +140 -0
  192. package/dist/node/features/json-tree.d.ts.map +1 -0
  193. package/dist/node/features/networking.d.ts +373 -0
  194. package/dist/node/features/networking.d.ts.map +1 -0
  195. package/dist/node/features/nlp.d.ts +125 -0
  196. package/dist/node/features/nlp.d.ts.map +1 -0
  197. package/dist/node/features/opener.d.ts +93 -0
  198. package/dist/node/features/opener.d.ts.map +1 -0
  199. package/dist/node/features/os.d.ts +168 -0
  200. package/dist/node/features/os.d.ts.map +1 -0
  201. package/dist/node/features/package-finder.d.ts +419 -0
  202. package/dist/node/features/package-finder.d.ts.map +1 -0
  203. package/dist/node/features/postgres.d.ts +173 -0
  204. package/dist/node/features/postgres.d.ts.map +1 -0
  205. package/dist/node/features/proc.d.ts +285 -0
  206. package/dist/node/features/proc.d.ts.map +1 -0
  207. package/dist/node/features/process-manager.d.ts +427 -0
  208. package/dist/node/features/process-manager.d.ts.map +1 -0
  209. package/dist/node/features/python.d.ts +477 -0
  210. package/dist/node/features/python.d.ts.map +1 -0
  211. package/dist/node/features/redis.d.ts +247 -0
  212. package/dist/node/features/redis.d.ts.map +1 -0
  213. package/dist/node/features/repl.d.ts +84 -0
  214. package/dist/node/features/repl.d.ts.map +1 -0
  215. package/dist/node/features/runpod.d.ts +527 -0
  216. package/dist/node/features/runpod.d.ts.map +1 -0
  217. package/dist/node/features/secure-shell.d.ts +145 -0
  218. package/dist/node/features/secure-shell.d.ts.map +1 -0
  219. package/dist/node/features/semantic-search.d.ts +207 -0
  220. package/dist/node/features/semantic-search.d.ts.map +1 -0
  221. package/dist/node/features/sqlite.d.ts +180 -0
  222. package/dist/node/features/sqlite.d.ts.map +1 -0
  223. package/dist/node/features/telegram.d.ts +173 -0
  224. package/dist/node/features/telegram.d.ts.map +1 -0
  225. package/dist/node/features/transpiler.d.ts +51 -0
  226. package/dist/node/features/transpiler.d.ts.map +1 -0
  227. package/dist/node/features/tts.d.ts +108 -0
  228. package/dist/node/features/tts.d.ts.map +1 -0
  229. package/dist/node/features/ui.d.ts +562 -0
  230. package/dist/node/features/ui.d.ts.map +1 -0
  231. package/dist/node/features/vault.d.ts +90 -0
  232. package/dist/node/features/vault.d.ts.map +1 -0
  233. package/dist/node/features/vm.d.ts +285 -0
  234. package/dist/node/features/vm.d.ts.map +1 -0
  235. package/dist/node/features/yaml-tree.d.ts +118 -0
  236. package/dist/node/features/yaml-tree.d.ts.map +1 -0
  237. package/dist/node/features/yaml.d.ts +127 -0
  238. package/dist/node/features/yaml.d.ts.map +1 -0
  239. package/dist/node.d.ts +67 -0
  240. package/dist/node.d.ts.map +1 -0
  241. package/dist/python/generated.d.ts +2 -0
  242. package/dist/python/generated.d.ts.map +1 -0
  243. package/dist/react/index.d.ts +36 -0
  244. package/dist/react/index.d.ts.map +1 -0
  245. package/dist/registry.d.ts +97 -0
  246. package/dist/registry.d.ts.map +1 -0
  247. package/dist/scaffolds/generated.d.ts +13 -0
  248. package/dist/scaffolds/generated.d.ts.map +1 -0
  249. package/dist/scaffolds/template.d.ts +11 -0
  250. package/dist/scaffolds/template.d.ts.map +1 -0
  251. package/dist/schemas/base.d.ts +254 -0
  252. package/dist/schemas/base.d.ts.map +1 -0
  253. package/dist/selector.d.ts +130 -0
  254. package/dist/selector.d.ts.map +1 -0
  255. package/dist/server.d.ts +89 -0
  256. package/dist/server.d.ts.map +1 -0
  257. package/dist/servers/express.d.ts +104 -0
  258. package/dist/servers/express.d.ts.map +1 -0
  259. package/dist/servers/mcp.d.ts +201 -0
  260. package/dist/servers/mcp.d.ts.map +1 -0
  261. package/dist/servers/socket.d.ts +121 -0
  262. package/dist/servers/socket.d.ts.map +1 -0
  263. package/dist/state.d.ts +24 -0
  264. package/dist/state.d.ts.map +1 -0
  265. package/dist/web/clients/socket.d.ts +37 -0
  266. package/dist/web/clients/socket.d.ts.map +1 -0
  267. package/dist/web/container.d.ts +55 -0
  268. package/dist/web/container.d.ts.map +1 -0
  269. package/dist/web/extension.d.ts +4 -0
  270. package/dist/web/extension.d.ts.map +1 -0
  271. package/dist/web/feature.d.ts +8 -0
  272. package/dist/web/feature.d.ts.map +1 -0
  273. package/dist/web/features/asset-loader.d.ts +35 -0
  274. package/dist/web/features/asset-loader.d.ts.map +1 -0
  275. package/dist/web/features/container-link.d.ts +167 -0
  276. package/dist/web/features/container-link.d.ts.map +1 -0
  277. package/dist/web/features/esbuild.d.ts +51 -0
  278. package/dist/web/features/esbuild.d.ts.map +1 -0
  279. package/dist/web/features/helpers.d.ts +140 -0
  280. package/dist/web/features/helpers.d.ts.map +1 -0
  281. package/dist/web/features/network.d.ts +69 -0
  282. package/dist/web/features/network.d.ts.map +1 -0
  283. package/dist/web/features/speech.d.ts +71 -0
  284. package/dist/web/features/speech.d.ts.map +1 -0
  285. package/dist/web/features/vault.d.ts +62 -0
  286. package/dist/web/features/vault.d.ts.map +1 -0
  287. package/dist/web/features/vm.d.ts +48 -0
  288. package/dist/web/features/vm.d.ts.map +1 -0
  289. package/dist/web/features/voice-recognition.d.ts +96 -0
  290. package/dist/web/features/voice-recognition.d.ts.map +1 -0
  291. package/dist/web/shims/isomorphic-vm.d.ts +22 -0
  292. package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
  293. package/docs/apis/features/agi/assistant.md +1 -0
  294. package/docs/apis/features/agi/assistants-manager.md +62 -2
  295. package/docs/apis/features/agi/auto-assistant.md +11 -109
  296. package/docs/apis/features/agi/claude-code.md +138 -0
  297. package/docs/apis/features/agi/conversation.md +60 -31
  298. package/docs/apis/features/agi/luca-coder.md +407 -0
  299. package/docs/apis/features/agi/openapi.md +2 -2
  300. package/docs/apis/features/agi/skills-library.md +12 -0
  301. package/docs/apis/features/node/python.md +81 -11
  302. package/docs/apis/features/node/transpiler.md +74 -0
  303. package/docs/apis/features/web/esbuild.md +0 -6
  304. package/docs/apis/servers/mcp.md +2 -2
  305. package/docs/examples/entity.md +124 -0
  306. package/docs/ideas/assistant-factory-pattern.md +142 -0
  307. package/package.json +74 -21
  308. package/src/agi/container.server.ts +10 -0
  309. package/src/agi/feature.ts +13 -0
  310. package/src/agi/features/agent-memory.ts +694 -0
  311. package/src/agi/features/assistant.ts +37 -26
  312. package/src/agi/features/assistants-manager.ts +95 -5
  313. package/src/agi/features/autonomous-assistant.ts +1 -5
  314. package/src/agi/features/browser-use.ts +32 -2
  315. package/src/agi/features/claude-code.ts +165 -1
  316. package/src/agi/features/coding-tools.ts +175 -0
  317. package/src/agi/features/conversation-history.ts +2 -6
  318. package/src/agi/features/conversation.ts +95 -3
  319. package/src/agi/features/docs-reader.ts +2 -1
  320. package/src/agi/features/file-tools.ts +35 -28
  321. package/src/agi/features/luca-coder.ts +1 -5
  322. package/src/agi/features/openai-codex.ts +1 -1
  323. package/src/agi/features/openapi.ts +3 -3
  324. package/src/agi/features/skills-library.ts +111 -13
  325. package/src/agi/lib/interceptor-chain.ts +10 -0
  326. package/src/agi/lib/token-counter.ts +1 -1
  327. package/src/bootstrap/generated.ts +126 -1
  328. package/src/bus.ts +27 -5
  329. package/src/cli/build-info.ts +2 -2
  330. package/src/client.ts +2 -2
  331. package/src/clients/elevenlabs/index.ts +5 -0
  332. package/src/clients/voicebox/index.ts +300 -0
  333. package/src/commands/bootstrap.ts +2 -1
  334. package/src/commands/chat.ts +1 -0
  335. package/src/commands/code.ts +4 -2
  336. package/src/commands/prompt.ts +34 -34
  337. package/src/commands/sandbox-mcp.ts +69 -163
  338. package/src/commands/save-api-docs.ts +10 -8
  339. package/src/commands/select.ts +8 -3
  340. package/src/container-describer.ts +70 -84
  341. package/src/container.ts +93 -3
  342. package/src/endpoint.ts +1 -1
  343. package/src/entity.ts +173 -0
  344. package/src/feature.ts +3 -3
  345. package/src/helper.ts +8 -4
  346. package/src/introspection/generated.agi.ts +3012 -1356
  347. package/src/introspection/generated.node.ts +179 -33
  348. package/src/introspection/generated.web.ts +95 -3
  349. package/src/introspection/scan.ts +1 -1
  350. package/src/node/container.ts +1 -1
  351. package/src/node/features/content-db.ts +57 -30
  352. package/src/node/features/file-manager.ts +10 -9
  353. package/src/node/features/git.ts +5 -5
  354. package/src/node/features/helpers.ts +1 -1
  355. package/src/node/features/json-tree.ts +1 -1
  356. package/src/node/features/os.ts +3 -3
  357. package/src/node/features/package-finder.ts +1 -1
  358. package/src/node/features/process-manager.ts +51 -18
  359. package/src/node/features/python.ts +3 -3
  360. package/src/node/features/redis.ts +1 -1
  361. package/src/node/features/repl.ts +2 -2
  362. package/src/node/features/transpiler.ts +2 -2
  363. package/src/node/features/ui.ts +1 -1
  364. package/src/node/features/vm.ts +3 -3
  365. package/src/node/features/yaml-tree.ts +1 -1
  366. package/src/node.ts +1 -0
  367. package/src/python/generated.ts +1 -1
  368. package/src/scaffolds/generated.ts +1 -1
  369. package/src/selector.ts +74 -4
  370. package/src/server.ts +2 -2
  371. package/src/servers/mcp.ts +6 -6
  372. package/src/web/features/helpers.ts +1 -1
  373. package/src/web/features/network.ts +1 -0
  374. package/test/assistant.test.ts +14 -5
  375. package/test/conversation.test.ts +220 -0
  376. package/test-integration/memory.test.ts +204 -0
  377. package/tsconfig.build.json +12 -0
  378. package/tsconfig.json +1 -1
  379. package/scripts/examples/telegram-ink-ui.ts +0 -302
  380. package/scripts/examples/using-openai-codex.ts +0 -23
  381. package/scripts/examples/vm-loading-esm-modules.ts +0 -16
@@ -0,0 +1,353 @@
1
+ import { z } from 'zod'
2
+ import { commands, CommandOptionsSchema } from '@soederpop/luca'
3
+ import type { ContainerContext } from '@soederpop/luca'
4
+ import { AGIContainer } from '../src/agi/container.server.js'
5
+ import { tmpdir } from 'os'
6
+
7
+ export const argsSchema = CommandOptionsSchema.extend({
8
+ model: z.string().optional().describe('OpenAI model to use'),
9
+ })
10
+
11
+ export async function inkbot(options: z.infer<typeof argsSchema>, context: ContainerContext) {
12
+ const container = new AGIContainer()
13
+
14
+ // ─── Load Ink ────────────────────────────────────────────────────────
15
+ const ink = container.feature('ink', { enable: true, patchConsole: true })
16
+ await ink.loadModules()
17
+ const React = ink.React
18
+ const h = React.createElement
19
+ const { Box, Text } = ink.components
20
+ const { useInput, useApp, useStdout } = ink.hooks
21
+ const { useState, useEffect } = React
22
+
23
+ // ─── Scene Runner ────────────────────────────────────────────────────
24
+ // Scenes are code strings run as bun subprocesses.
25
+ // The stage entity tracks which scenes exist and which is active.
26
+ // Scene entities track individual code, output, error, status.
27
+
28
+ const stage = container.entity('inkbot:stage')
29
+ stage.setState({ activeSceneId: null, sceneIds: [] as string[], tick: 0 })
30
+
31
+ const sceneMap: Record<string, ReturnType<typeof container.entity>> = {}
32
+
33
+ function bumpStage() {
34
+ stage.setState({ tick: ((stage.state.get('tick') as number) || 0) + 1 })
35
+ }
36
+
37
+ function getOrCreateScene(id: string, code: string) {
38
+ if (sceneMap[id]) {
39
+ sceneMap[id].setState({ code })
40
+ return sceneMap[id]
41
+ }
42
+ const scene = container.entity(`inkbot:scene:${id}`)
43
+ scene.setState({ code, output: '', error: '', status: 'idle', exitCode: null })
44
+ sceneMap[id] = scene
45
+ const ids = [...((stage.state.get('sceneIds') || []) as string[])]
46
+ if (!ids.includes(id)) ids.push(id)
47
+ stage.setState({ sceneIds: ids })
48
+ if (!stage.state.get('activeSceneId')) stage.setState({ activeSceneId: id })
49
+ return scene
50
+ }
51
+
52
+ const proc = container.feature('proc')
53
+ const fs = container.feature('fs')
54
+ const sceneTmpDir = `${tmpdir()}/inkbot-scenes`
55
+ fs.ensureFolder(sceneTmpDir)
56
+
57
+ async function runScene(id: string): Promise<{ output: string; error: string; exitCode: number }> {
58
+ const scene = sceneMap[id]
59
+ if (!scene) throw new Error(`Scene "${id}" not found`)
60
+
61
+ const code = scene.state.get('code') as string
62
+ scene.setState({ status: 'running', output: '', error: '' })
63
+ bumpStage()
64
+
65
+ // Write to tmpdir, shell out to `luca run` — gets full container context + process isolation
66
+ const file = `${sceneTmpDir}/${id.replace(/[^a-zA-Z0-9-]/g, '_')}_${Date.now()}.ts`
67
+ fs.writeFile(file, code)
68
+
69
+ try {
70
+ const result = await proc.spawnAndCapture('luca', ['run', file], {
71
+ cwd: container.cwd,
72
+ onOutput(data: string) {
73
+ scene.setState({ output: ((scene.state.get('output') || '') as string) + data })
74
+ bumpStage()
75
+ },
76
+ onError(data: string) {
77
+ scene.setState({ error: ((scene.state.get('error') || '') as string) + data })
78
+ bumpStage()
79
+ },
80
+ })
81
+
82
+ const status = result.exitCode === 0 ? 'complete' : 'failed'
83
+ scene.setState({ status, exitCode: result.exitCode })
84
+ bumpStage()
85
+ try { fs.unlink(file) } catch {}
86
+
87
+ return {
88
+ output: (scene.state.get('output') || '') as string,
89
+ error: (scene.state.get('error') || '') as string,
90
+ exitCode: result.exitCode ?? 1,
91
+ }
92
+ } catch (err: any) {
93
+ scene.setState({ status: 'failed', error: err.message, exitCode: 1 })
94
+ bumpStage()
95
+ try { fs.unlink(file) } catch {}
96
+ return { output: '', error: err.message, exitCode: 1 }
97
+ }
98
+ }
99
+
100
+ // ─── Assistant ───────────────────────────────────────────────────────
101
+ const mgr = container.feature('assistantsManager')
102
+ await mgr.discover()
103
+ const assistant = mgr.create('inkbot', { model: options.model })
104
+
105
+ // Scene completion → inject result into conversation so the assistant sees it
106
+ stage.on('sceneComplete' as any, (id: string, output: string) => {
107
+ const msg = output.trim()
108
+ ? `[Scene "${id}" completed]\n${output.trim()}`
109
+ : `[Scene "${id}" completed with no output]`
110
+ assistant.conversation?.pushMessage({ role: 'developer', content: msg })
111
+ })
112
+
113
+ stage.on('sceneFailed' as any, (id: string, error: string) => {
114
+ const msg = `[Scene "${id}" failed]\n${error.trim()}`
115
+ assistant.conversation?.pushMessage({ role: 'developer', content: msg })
116
+ // Auto-ask the assistant to fix it
117
+ assistant.ask(msg).catch(() => {})
118
+ })
119
+
120
+ // Canvas tools — registered directly so they close over stage/sceneMap
121
+ assistant.addTool(
122
+ 'draw',
123
+ async (args: { code: string; sceneId?: string }) => {
124
+ const id = args.sceneId || 'default'
125
+ getOrCreateScene(id, args.code)
126
+ stage.setState({ activeSceneId: id })
127
+ bumpStage()
128
+ // Fire and forget — result feeds back via stage events
129
+ runScene(id).then(result => {
130
+ if (result.exitCode === 0) {
131
+ stage.emit('sceneComplete' as any, id, result.output)
132
+ } else {
133
+ stage.emit('sceneFailed' as any, id, result.error)
134
+ }
135
+ })
136
+ return { status: 'running', sceneId: id }
137
+ },
138
+ z.object({
139
+ code: z.string().describe('TypeScript code to execute. Use console.log() for visible output.'),
140
+ sceneId: z.string().optional().describe('Scene id (defaults to "default").'),
141
+ }).describe('Draw or redraw the canvas. Returns immediately — output streams to the canvas. If the scene fails, you will be notified automatically.'),
142
+ )
143
+
144
+ assistant.addTool(
145
+ 'create_scene',
146
+ async (args: { id: string; code: string }) => {
147
+ getOrCreateScene(args.id, args.code)
148
+ return { created: args.id, allScenes: stage.state.get('sceneIds') }
149
+ },
150
+ z.object({
151
+ id: z.string().describe('Unique scene identifier'),
152
+ code: z.string().describe('TypeScript code for this scene'),
153
+ }).describe('Create a named scene without running it yet.'),
154
+ )
155
+
156
+ assistant.addTool(
157
+ 'run_scene',
158
+ async (args: { id: string }) => runScene(args.id),
159
+ z.object({
160
+ id: z.string().describe('Scene id to run'),
161
+ }).describe('Run a specific scene by its id.'),
162
+ )
163
+
164
+ assistant.addTool(
165
+ 'run_all',
166
+ async () => {
167
+ const ids = (stage.state.get('sceneIds') || []) as string[]
168
+ const results: any[] = []
169
+ for (const id of ids) results.push({ id, ...(await runScene(id)) })
170
+ return results
171
+ },
172
+ z.object({}).describe('Run every scene in order and return all results.'),
173
+ )
174
+
175
+ assistant.addTool(
176
+ 'get_canvas',
177
+ async () => {
178
+ const activeId = stage.state.get('activeSceneId') as string | null
179
+ if (!activeId || !sceneMap[activeId]) return { status: 'empty', allScenes: [] }
180
+ const s = sceneMap[activeId]
181
+ return {
182
+ sceneId: activeId,
183
+ status: s.state.get('status'),
184
+ output: s.state.get('output'),
185
+ error: s.state.get('error'),
186
+ code: s.state.get('code'),
187
+ allScenes: stage.state.get('sceneIds'),
188
+ }
189
+ },
190
+ z.object({}).describe('Inspect the current canvas: active scene output, error, code, status.'),
191
+ )
192
+
193
+ assistant.addTool(
194
+ 'activate_scene',
195
+ async (args: { id: string }) => {
196
+ if (!sceneMap[args.id]) return { error: `Scene "${args.id}" not found` }
197
+ stage.setState({ activeSceneId: args.id })
198
+ bumpStage()
199
+ return { activeSceneId: args.id }
200
+ },
201
+ z.object({
202
+ id: z.string().describe('Scene id to make active in the canvas'),
203
+ }).describe('Switch the canvas to display a different scene.'),
204
+ )
205
+
206
+ // ─── Ink App ─────────────────────────────────────────────────────────
207
+
208
+ type Msg = { role: 'user' | 'assistant' | 'system'; content: string }
209
+
210
+ function App() {
211
+ const [messages, setMessages] = useState<Msg[]>([])
212
+ const [input, setInput] = useState('')
213
+ const [streaming, setStreaming] = useState('')
214
+ const [thinking, setThinking] = useState(false)
215
+ const [activity, setActivity] = useState('')
216
+ const [canvas, setCanvas] = useState({ output: '', error: '', status: 'empty' })
217
+ const { exit } = useApp()
218
+ const { stdout } = useStdout()
219
+ const rows = stdout?.rows ?? 24
220
+
221
+ // --- assistant events ---
222
+ useEffect(() => {
223
+ const onPreview = (text: string) => setStreaming(text)
224
+ const onResponse = (text: string) => {
225
+ setStreaming('')
226
+ setThinking(false)
227
+ setActivity('')
228
+ setMessages(prev => [...prev, { role: 'assistant', content: text }])
229
+ }
230
+ const onToolCall = (name: string) => setActivity(`${name}`)
231
+ const onToolResult = () => setActivity('')
232
+
233
+ assistant.on('preview', onPreview)
234
+ assistant.on('response', onResponse)
235
+ assistant.on('toolCall', onToolCall)
236
+ assistant.on('toolResult', onToolResult)
237
+ return () => {
238
+ assistant.off('preview', onPreview)
239
+ assistant.off('response', onResponse)
240
+ assistant.off('toolCall', onToolCall)
241
+ assistant.off('toolResult', onToolResult)
242
+ }
243
+ }, [])
244
+
245
+ // --- stage entity ticks → canvas state ---
246
+ useEffect(() => {
247
+ const unsub = stage.state.observe((_changeType: any, key: any) => {
248
+ if (key !== 'tick') return
249
+ const activeId = stage.state.get('activeSceneId') as string | null
250
+ if (!activeId || !sceneMap[activeId]) {
251
+ setCanvas({ output: '', error: '', status: 'empty' })
252
+ return
253
+ }
254
+ const s = sceneMap[activeId]
255
+ setCanvas({
256
+ output: (s.state.get('output') || '') as string,
257
+ error: (s.state.get('error') || '') as string,
258
+ status: (s.state.get('status') || 'idle') as string,
259
+ })
260
+ })
261
+ return unsub
262
+ }, [])
263
+
264
+ // --- keyboard ---
265
+ useInput((ch, key) => {
266
+ if (key.escape) { exit(); return }
267
+
268
+ if (key.return) {
269
+ if (thinking) return
270
+ const msg = input.trim()
271
+ if (!msg) return
272
+ setInput('')
273
+ setMessages(prev => [...prev, { role: 'user', content: msg }])
274
+ setThinking(true)
275
+ assistant.ask(msg).catch((err: any) => {
276
+ setMessages(prev => [...prev, { role: 'system', content: `error: ${err.message}` }])
277
+ setThinking(false)
278
+ })
279
+ return
280
+ }
281
+
282
+ if (key.backspace || key.delete) {
283
+ setInput(prev => prev.slice(0, -1))
284
+ return
285
+ }
286
+
287
+ if (ch && !key.ctrl && !key.meta) {
288
+ setInput(prev => prev + ch)
289
+ }
290
+ })
291
+
292
+ // --- render ---
293
+ const visible = messages.slice(-30)
294
+ const sceneIds = (stage.state.get('sceneIds') || []) as string[]
295
+ const activeId = (stage.state.get('activeSceneId') || '') as string
296
+
297
+ const chatChildren: any[] = []
298
+
299
+ visible.forEach((m, i) => {
300
+ const color = m.role === 'user' ? 'green' : m.role === 'system' ? 'red' : 'white'
301
+ const prefix = m.role === 'user' ? '> ' : ' '
302
+ chatChildren.push(h(Text, { key: `msg-${i}`, wrap: 'wrap', color }, `${prefix}${m.content}`))
303
+ })
304
+
305
+ if (streaming) chatChildren.push(h(Text, { key: 'chat-stream', wrap: 'wrap', dimColor: true }, ` ${streaming}`))
306
+ if (thinking && !streaming) chatChildren.push(h(Text, { key: 'chat-think', color: 'yellow' }, ' thinking...'))
307
+ if (activity) chatChildren.push(h(Text, { key: 'chat-act', color: 'blue' }, ` [${activity}]`))
308
+
309
+ const canvasBody = canvas.output
310
+ ? h(Text, { key: 'cvs-out', wrap: 'wrap' }, canvas.output)
311
+ : canvas.status === 'empty'
312
+ ? h(Text, { key: 'cvs-empty', dimColor: true }, ' ask inkbot to draw something')
313
+ : null
314
+
315
+ // border + header + status = 4 rows overhead per panel
316
+ const panelHeight = rows - 2
317
+
318
+ return h(Box, { flexDirection: 'row', width: '100%', height: rows },
319
+ // ── Chat ──
320
+ h(Box, { key: 'chat', flexDirection: 'column', width: '50%', height: rows, borderStyle: 'round', borderColor: 'cyan', paddingX: 1 },
321
+ h(Text, { bold: true, color: 'cyan' }, ' inkbot '),
322
+ h(Box, { flexDirection: 'column', flexGrow: 1, overflow: 'hidden' }, ...chatChildren),
323
+ h(Box, { borderStyle: 'single', borderColor: 'gray', paddingX: 1 },
324
+ h(Text, { color: 'green' }, '> '),
325
+ h(Text, null, input),
326
+ h(Text, { dimColor: true }, '\u2588'),
327
+ ),
328
+ ),
329
+ // ── Canvas ──
330
+ h(Box, { key: 'canvas', flexDirection: 'column', width: '50%', height: rows, borderStyle: 'round', borderColor: 'magenta', paddingX: 1 },
331
+ h(Text, { bold: true, color: 'magenta' }, ' canvas '),
332
+ h(Box, { flexDirection: 'column', height: panelHeight - 4, overflow: 'hidden' },
333
+ canvasBody,
334
+ canvas.error ? h(Text, { key: 'cvs-err', color: 'red', wrap: 'wrap' }, canvas.error) : null,
335
+ ),
336
+ h(Box, null,
337
+ h(Text, { dimColor: true }, ` ${canvas.status}`),
338
+ sceneIds.length > 1 ? h(Text, { dimColor: true }, ` scenes: ${sceneIds.join(', ')} active: ${activeId}`) : null,
339
+ ),
340
+ ),
341
+ )
342
+ }
343
+
344
+ // Mount and hold
345
+ await ink.render(h(App))
346
+ await ink.waitUntilExit()
347
+ }
348
+
349
+ export default {
350
+ description: 'Launch the Inkbot split-pane assistant with a live canvas.',
351
+ argsSchema,
352
+ handler: inkbot,
353
+ }
@@ -1,186 +1,80 @@
1
- import { z } from 'zod'
2
- import type { ContainerContext } from '@soederpop/luca'
3
- import { CommandOptionsSchema } from '@soederpop/luca/schemas'
4
-
5
- const TARGETS = [
6
- { name: 'linux-x64', bunTarget: 'bun-linux-x64', suffix: 'linux-x64' },
7
- { name: 'linux-arm64', bunTarget: 'bun-linux-arm64', suffix: 'linux-arm64' },
8
- { name: 'darwin-x64', bunTarget: 'bun-darwin-x64', suffix: 'darwin-x64' },
9
- { name: 'darwin-arm64', bunTarget: 'bun-darwin-arm64', suffix: 'darwin-arm64' },
10
- { name: 'windows-x64', bunTarget: 'bun-windows-x64', suffix: 'windows-x64', ext: '.exe' },
11
- ]
1
+ import { z } from "zod";
2
+ import type { ContainerContext } from "@soederpop/luca";
3
+ import { CommandOptionsSchema } from "@soederpop/luca/schemas";
12
4
 
13
5
  export const argsSchema = CommandOptionsSchema.extend({
14
- dryRun: z.boolean().optional().describe('Build binaries but skip tagging and uploading'),
15
- skipBuild: z.boolean().optional().describe('Skip pre-build steps (introspection, scaffolds, bootstrap)'),
16
- skipTests: z.boolean().optional().describe('Skip running tests before release'),
17
- draft: z.boolean().optional().describe('Create the GitHub release as a draft'),
18
- targets: z.string().optional().describe('Comma-separated list of targets to build (e.g. linux-x64,darwin-arm64). Defaults to all'),
19
- })
20
-
21
- async function release(options: z.infer<typeof argsSchema>, context: ContainerContext) {
22
- const container = context.container as any
23
- const proc = container.feature('proc')
24
- const fileSystem = container.feature('fs')
25
- const ui = container.feature('ui')
26
-
27
- const pkg = JSON.parse(await fileSystem.readFileAsync('package.json'))
28
- const version = pkg.version
29
- const tag = `v${version}`
30
- const distDir = 'dist/release'
31
-
32
- ui.banner(`Luca Release ${tag}`)
33
-
34
- // Filter targets if specified
35
- let selectedTargets = TARGETS
36
- if (options.targets) {
37
- const requested = options.targets.split(',').map((t: string) => t.trim())
38
- selectedTargets = TARGETS.filter(t => requested.includes(t.suffix) || requested.includes(t.name))
39
- if (selectedTargets.length === 0) {
40
- console.error(`No valid targets found. Available: ${TARGETS.map(t => t.suffix).join(', ')}`)
41
- return
42
- }
43
- }
44
-
45
- // 1. Run tests
46
- if (!options.skipTests) {
47
- console.log('\n→ Running tests...')
48
- const testResult = await proc.execAndCapture('bun test test/*.test.ts', { silent: false })
49
- if (testResult.exitCode !== 0) {
50
- console.error('Tests failed. Fix them before releasing.')
51
- return
52
- }
53
- }
54
-
55
- // 2. Pre-build steps
56
- if (!options.skipBuild) {
57
- console.log('\n→ Running pre-build steps...')
58
- const steps = [
59
- ['build:introspection', 'bun run build:introspection'],
60
- ['build:scaffolds', 'bun run build:scaffolds'],
61
- ['build:bootstrap', 'bun run build:bootstrap'],
62
- ]
63
- for (const [label, cmd] of steps) {
64
- console.log(` ${label}...`)
65
- const r = await proc.execAndCapture(cmd, { silent: true })
66
- if (r.exitCode !== 0) {
67
- console.error(`${label} failed:\n${r.stderr}`)
68
- return
69
- }
70
- }
71
- }
72
-
73
- // 3. Cross-compile for all targets
74
- fileSystem.ensureFolder(distDir)
75
-
76
- console.log(`\n→ Compiling for ${selectedTargets.length} targets...`)
77
- for (const target of selectedTargets) {
78
- const ext = target.ext || ''
79
- const outfile = `${distDir}/luca-${target.suffix}${ext}`
80
- const cmd = `bun build ./src/cli/cli.ts --compile --target=${target.bunTarget} --outfile ${outfile} --external node-llama-cpp`
81
-
82
- console.log(` ${target.name}...`)
83
- const result = await proc.execAndCapture(cmd, { silent: true })
84
- if (result.exitCode !== 0) {
85
- console.error(` Failed to compile for ${target.name}:\n${result.stderr}`)
86
- return
87
- }
88
-
89
- const sizeBytes = proc.exec(`stat -f%z ${container.paths.resolve(outfile)}`)
90
- const sizeMB = (parseInt(sizeBytes, 10) / 1024 / 1024).toFixed(1)
91
- console.log(` ✓ ${outfile} (${sizeMB} MB)`)
92
- }
93
-
94
- if (options.dryRun) {
95
- console.log(`\n→ Dry run complete. Binaries are in ${distDir}/`)
96
- console.log(' Skipping git tag and GitHub release.')
97
- return
98
- }
99
-
100
- // 4. Check if tag already exists
101
- const tagCheck = await proc.execAndCapture(`git tag -l "${tag}"`, { silent: true })
102
- if (tagCheck.stdout.trim() === tag) {
103
- console.error(`\nTag ${tag} already exists. Bump the version in package.json first.`)
104
- return
105
- }
106
-
107
- // 5. Check for clean working tree (allow untracked)
108
- const statusCheck = await proc.execAndCapture('git status --porcelain', { silent: true })
109
- const dirtyFiles = statusCheck.stdout.trim().split('\n').filter((l: string) => l && !l.startsWith('??'))
110
- if (dirtyFiles.length > 0) {
111
- console.error('\nWorking tree has uncommitted changes. Commit or stash them first.')
112
- console.error(dirtyFiles.join('\n'))
113
- return
114
- }
115
-
116
- // 6. Create git tag
117
- console.log(`\n→ Creating tag ${tag}...`)
118
- const tagResult = await proc.execAndCapture(`git tag -a "${tag}" -m "Release ${tag}"`, { silent: true })
119
- if (tagResult.exitCode !== 0) {
120
- console.error(`Failed to create tag:\n${tagResult.stderr}`)
121
- return
122
- }
123
-
124
- // 7. Push tag
125
- console.log(`→ Pushing tag ${tag}...`)
126
- const pushResult = await proc.execAndCapture(`git push origin "${tag}"`, { silent: true })
127
- if (pushResult.exitCode !== 0) {
128
- console.error(`Failed to push tag:\n${pushResult.stderr}`)
129
- return
130
- }
131
-
132
- // 8. Create GitHub release and upload binaries
133
- const assetPaths = selectedTargets
134
- .map(t => container.paths.resolve(`${distDir}/luca-${t.suffix}${t.ext || ''}`))
135
-
136
- const releaseTitle = `Luca ${tag}`
137
- const releaseNotes = await generateReleaseNotes(proc, tag)
138
-
139
- // Write notes to a temp file so gh doesn't need shell quoting
140
- const notesFile = container.paths.resolve(distDir, 'release-notes.md')
141
- await fileSystem.writeFileAsync(notesFile, releaseNotes)
142
-
143
- console.log(`\n→ Creating GitHub release ${tag}...`)
144
- const ghArgs = [
145
- 'release', 'create', tag,
146
- ...assetPaths,
147
- '--title', releaseTitle,
148
- '--notes-file', notesFile,
149
- ...(options.draft ? ['--draft'] : []),
150
- ]
151
- const ghResult = await proc.spawnAndCapture('gh', ghArgs)
152
-
153
- if (ghResult.exitCode !== 0) {
154
- console.error(`Failed to create GitHub release:\n${ghResult.stderr}`)
155
- console.log('The tag was pushed. You can manually create the release with:')
156
- console.log(` gh release create ${tag} ${assetPaths.join(' ')}`)
157
- return
158
- }
159
-
160
- console.log(`\n✓ Released ${tag} successfully!`)
161
- console.log(` https://github.com/soederpop/luca/releases/tag/${tag}`)
162
- }
163
-
164
- async function generateReleaseNotes(proc: any, tag: string): Promise<string> {
165
- // Get commits since last tag
166
- const lastTag = await proc.execAndCapture('git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo ""', { silent: true })
167
- const since = lastTag.stdout.trim()
168
-
169
- let logCmd: string
170
- if (since) {
171
- logCmd = `git log ${since}..HEAD --oneline --no-decorate`
172
- } else {
173
- logCmd = 'git log --oneline --no-decorate -20'
174
- }
175
-
176
- const log = await proc.execAndCapture(logCmd, { silent: true })
177
- const commits = log.stdout.trim()
178
-
179
- return `## What's Changed\n\n${commits ? commits.split('\n').map((c: string) => `- ${c}`).join('\n') : 'Initial release'}\n\n## Platforms\n\n- Linux x64\n- Linux ARM64\n- macOS x64 (Intel)\n- macOS ARM64 (Apple Silicon)\n- Windows x64`
6
+ skipTests: z
7
+ .boolean()
8
+ .optional()
9
+ .describe("Skip running tests before release"),
10
+ });
11
+
12
+ async function release(
13
+ options: z.infer<typeof argsSchema>,
14
+ context: ContainerContext,
15
+ ) {
16
+ const container = context.container as any;
17
+ const proc = container.feature("proc");
18
+ const fileSystem = container.feature("fs");
19
+ const ui = container.feature("ui");
20
+
21
+ const pkg = JSON.parse(await fileSystem.readFileAsync("package.json"));
22
+ const version = pkg.version;
23
+ const tag = `v${version}`;
24
+
25
+ ui.banner(`Luca Release ${tag}`);
26
+
27
+ // Check if tag already exists
28
+ const tagCheck = await proc.execAndCapture(`git tag -l "${tag}"`, {
29
+ silent: true,
30
+ });
31
+ if (tagCheck.stdout.trim() === tag) {
32
+ console.error(
33
+ `\nTag ${tag} already exists. Bump the version in package.json first.`,
34
+ );
35
+ return;
36
+ }
37
+
38
+ // Run tests
39
+ if (!options.skipTests) {
40
+ console.log("\n→ Running tests...");
41
+ const testResult = await proc.execAndCapture("bun test test/*.test.ts", {
42
+ silent: false,
43
+ });
44
+ if (testResult.exitCode !== 0) {
45
+ console.error("Tests failed. Fix them before releasing.");
46
+ return;
47
+ }
48
+ }
49
+
50
+ // Create and push git tag — triggers the GitHub Actions release workflow
51
+ console.log(`\n→ Creating tag ${tag}...`);
52
+ const tagResult = await proc.execAndCapture(
53
+ `git tag -a "${tag}" -m "Release ${tag}"`,
54
+ { silent: true },
55
+ );
56
+ if (tagResult.exitCode !== 0) {
57
+ console.error(`Failed to create tag:\n${tagResult.stderr}`);
58
+ return;
59
+ }
60
+
61
+ console.log(`→ Pushing tag ${tag}...`);
62
+ const pushResult = await proc.execAndCapture(`git push origin "${tag}"`, {
63
+ silent: true,
64
+ });
65
+ if (pushResult.exitCode !== 0) {
66
+ console.error(`Failed to push tag:\n${pushResult.stderr}`);
67
+ return;
68
+ }
69
+
70
+ console.log(
71
+ `\n✓ Tag ${tag} pushed. GitHub Actions will build, sign, and create the draft release.`,
72
+ );
73
+ console.log(` https://github.com/soederpop/luca/actions`);
180
74
  }
181
75
 
182
76
  export default {
183
- description: 'Build cross-platform binaries and publish a GitHub release tagged by version',
184
- argsSchema,
185
- handler: release,
186
- }
77
+ description: "Run tests and trigger a GitHub Actions release via git tag",
78
+ argsSchema,
79
+ handler: release,
80
+ };
@@ -0,0 +1,63 @@
1
+ import type { ContainerState } from '../container';
2
+ import { type NodeFeatures, NodeContainer } from '../node/container';
3
+ import '@/introspection/generated.agi.js';
4
+ import { OpenAIClient } from '../clients/openai';
5
+ import { ElevenLabsClient } from '../clients/elevenlabs';
6
+ import { ClaudeCode } from './features/claude-code';
7
+ import { OpenAICodex } from './features/openai-codex';
8
+ import { Conversation } from './features/conversation';
9
+ import { ConversationHistory } from './features/conversation-history';
10
+ import { Assistant } from './features/assistant';
11
+ import { AssistantsManager } from './features/assistants-manager';
12
+ import { DocsReader } from './features/docs-reader';
13
+ import { SkillsLibrary } from './features/skills-library';
14
+ import { BrowserUse } from './features/browser-use';
15
+ import { SemanticSearch } from '@soederpop/luca/node/features/semantic-search';
16
+ import { ContentDb } from '@soederpop/luca/node/features/content-db';
17
+ import { FileTools } from './features/file-tools';
18
+ import { LucaCoder } from './features/luca-coder';
19
+ import type { ConversationTool } from './features/conversation';
20
+ import type { ZodType } from 'zod';
21
+ export { ClaudeCode, OpenAICodex, Conversation, ConversationHistory, Assistant, AssistantsManager, DocsReader, SkillsLibrary, BrowserUse, FileTools, LucaCoder, SemanticSearch, ContentDb, NodeContainer, OpenAIClient, ElevenLabsClient, };
22
+ export type { ConversationTool, ZodType, ContainerState, NodeFeatures, };
23
+ export interface AGIFeatures extends NodeFeatures {
24
+ conversation: typeof Conversation;
25
+ claudeCode: typeof ClaudeCode;
26
+ openaiCodex: typeof OpenAICodex;
27
+ conversationHistory: typeof ConversationHistory;
28
+ assistant: typeof Assistant;
29
+ assistantsManager: typeof AssistantsManager;
30
+ docsReader: typeof DocsReader;
31
+ skillsLibrary: typeof SkillsLibrary;
32
+ browserUse: typeof BrowserUse;
33
+ fileTools: typeof FileTools;
34
+ lucaCoder: typeof LucaCoder;
35
+ }
36
+ export interface ConversationFactoryOptions {
37
+ tools?: {
38
+ handlers: Record<string, ConversationTool['handler']>;
39
+ schemas: Record<string, ZodType>;
40
+ };
41
+ systemPrompt?: string;
42
+ model?: string;
43
+ id?: string;
44
+ title?: string;
45
+ thread?: string;
46
+ tags?: string[];
47
+ metadata?: Record<string, any>;
48
+ }
49
+ /**
50
+ * AGI-specific container that extends NodeContainer with AI capabilities including
51
+ * OpenAI conversations, code generation, and self-modifying agent features.
52
+ */
53
+ export declare class AGIContainer<Features extends AGIFeatures = AGIFeatures, K extends ContainerState = ContainerState> extends NodeContainer<Features, K> {
54
+ openai: OpenAIClient;
55
+ claudeCode?: ClaudeCode;
56
+ openaiCodex?: OpenAICodex;
57
+ conversationHistory?: ConversationHistory;
58
+ docs: ContentDb;
59
+ conversation(options?: ConversationFactoryOptions): Promise<InstanceType<Features["conversation"]>>;
60
+ }
61
+ declare const container: any;
62
+ export default container;
63
+ //# sourceMappingURL=container.server.d.ts.map