@soederpop/luca 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/CLAUDE.md +71 -0
  2. package/README.md +78 -0
  3. package/bun.lock +2928 -0
  4. package/bunfig.toml +3 -0
  5. package/commands/audit-docs.ts +740 -0
  6. package/commands/build-scaffolds.ts +154 -0
  7. package/commands/generate-api-docs.ts +114 -0
  8. package/commands/update-introspection.ts +67 -0
  9. package/docs/CLI.md +335 -0
  10. package/docs/README.md +88 -0
  11. package/docs/TABLE-OF-CONTENTS.md +157 -0
  12. package/docs/apis/clients/elevenlabs.md +84 -0
  13. package/docs/apis/clients/graph.md +56 -0
  14. package/docs/apis/clients/openai.md +69 -0
  15. package/docs/apis/clients/rest.md +41 -0
  16. package/docs/apis/clients/websocket.md +107 -0
  17. package/docs/apis/features/agi/assistant.md +471 -0
  18. package/docs/apis/features/agi/assistants-manager.md +154 -0
  19. package/docs/apis/features/agi/claude-code.md +602 -0
  20. package/docs/apis/features/agi/conversation-history.md +352 -0
  21. package/docs/apis/features/agi/conversation.md +333 -0
  22. package/docs/apis/features/agi/docs-reader.md +121 -0
  23. package/docs/apis/features/agi/openai-codex.md +318 -0
  24. package/docs/apis/features/agi/openapi.md +138 -0
  25. package/docs/apis/features/agi/semantic-search.md +387 -0
  26. package/docs/apis/features/agi/skills-library.md +216 -0
  27. package/docs/apis/features/node/container-link.md +133 -0
  28. package/docs/apis/features/node/content-db.md +313 -0
  29. package/docs/apis/features/node/disk-cache.md +379 -0
  30. package/docs/apis/features/node/dns.md +651 -0
  31. package/docs/apis/features/node/docker.md +705 -0
  32. package/docs/apis/features/node/downloader.md +81 -0
  33. package/docs/apis/features/node/esbuild.md +59 -0
  34. package/docs/apis/features/node/file-manager.md +182 -0
  35. package/docs/apis/features/node/fs.md +581 -0
  36. package/docs/apis/features/node/git.md +330 -0
  37. package/docs/apis/features/node/google-auth.md +174 -0
  38. package/docs/apis/features/node/google-calendar.md +187 -0
  39. package/docs/apis/features/node/google-docs.md +151 -0
  40. package/docs/apis/features/node/google-drive.md +225 -0
  41. package/docs/apis/features/node/google-sheets.md +179 -0
  42. package/docs/apis/features/node/grep.md +290 -0
  43. package/docs/apis/features/node/helpers.md +135 -0
  44. package/docs/apis/features/node/ink.md +334 -0
  45. package/docs/apis/features/node/ipc-socket.md +260 -0
  46. package/docs/apis/features/node/json-tree.md +86 -0
  47. package/docs/apis/features/node/launcher-app-command-listener.md +145 -0
  48. package/docs/apis/features/node/networking.md +281 -0
  49. package/docs/apis/features/node/nlp.md +133 -0
  50. package/docs/apis/features/node/opener.md +97 -0
  51. package/docs/apis/features/node/os.md +118 -0
  52. package/docs/apis/features/node/package-finder.md +402 -0
  53. package/docs/apis/features/node/postgres.md +212 -0
  54. package/docs/apis/features/node/proc.md +430 -0
  55. package/docs/apis/features/node/process-manager.md +210 -0
  56. package/docs/apis/features/node/python.md +278 -0
  57. package/docs/apis/features/node/repl.md +88 -0
  58. package/docs/apis/features/node/runpod.md +673 -0
  59. package/docs/apis/features/node/secure-shell.md +169 -0
  60. package/docs/apis/features/node/semantic-search.md +401 -0
  61. package/docs/apis/features/node/sqlite.md +211 -0
  62. package/docs/apis/features/node/telegram.md +254 -0
  63. package/docs/apis/features/node/tts.md +118 -0
  64. package/docs/apis/features/node/ui.md +703 -0
  65. package/docs/apis/features/node/vault.md +64 -0
  66. package/docs/apis/features/node/vm.md +84 -0
  67. package/docs/apis/features/node/window-manager.md +337 -0
  68. package/docs/apis/features/node/yaml-tree.md +85 -0
  69. package/docs/apis/features/node/yaml.md +176 -0
  70. package/docs/apis/features/web/asset-loader.md +47 -0
  71. package/docs/apis/features/web/container-link.md +133 -0
  72. package/docs/apis/features/web/esbuild.md +59 -0
  73. package/docs/apis/features/web/helpers.md +135 -0
  74. package/docs/apis/features/web/network.md +30 -0
  75. package/docs/apis/features/web/speech.md +55 -0
  76. package/docs/apis/features/web/vault.md +64 -0
  77. package/docs/apis/features/web/vm.md +84 -0
  78. package/docs/apis/features/web/voice.md +67 -0
  79. package/docs/apis/servers/express.md +127 -0
  80. package/docs/apis/servers/mcp.md +213 -0
  81. package/docs/apis/servers/websocket.md +99 -0
  82. package/docs/documentation-audit.md +134 -0
  83. package/docs/examples/content-db.md +77 -0
  84. package/docs/examples/disk-cache.md +83 -0
  85. package/docs/examples/docker.md +101 -0
  86. package/docs/examples/downloader.md +70 -0
  87. package/docs/examples/esbuild.md +80 -0
  88. package/docs/examples/file-manager.md +82 -0
  89. package/docs/examples/fs.md +83 -0
  90. package/docs/examples/git.md +85 -0
  91. package/docs/examples/google-auth.md +88 -0
  92. package/docs/examples/google-calendar.md +94 -0
  93. package/docs/examples/google-docs.md +82 -0
  94. package/docs/examples/google-drive.md +96 -0
  95. package/docs/examples/google-sheets.md +95 -0
  96. package/docs/examples/grep.md +85 -0
  97. package/docs/examples/ink-blocks.md +75 -0
  98. package/docs/examples/ink-renderer.md +41 -0
  99. package/docs/examples/ink.md +103 -0
  100. package/docs/examples/ipc-socket.md +103 -0
  101. package/docs/examples/json-tree.md +91 -0
  102. package/docs/examples/launcher-app-command-listener.md +120 -0
  103. package/docs/examples/networking.md +58 -0
  104. package/docs/examples/nlp.md +91 -0
  105. package/docs/examples/opener.md +78 -0
  106. package/docs/examples/os.md +72 -0
  107. package/docs/examples/package-finder.md +89 -0
  108. package/docs/examples/port-exposer.md +89 -0
  109. package/docs/examples/postgres.md +91 -0
  110. package/docs/examples/proc.md +81 -0
  111. package/docs/examples/process-manager.md +79 -0
  112. package/docs/examples/python.md +91 -0
  113. package/docs/examples/repl.md +93 -0
  114. package/docs/examples/runpod.md +119 -0
  115. package/docs/examples/secure-shell.md +92 -0
  116. package/docs/examples/sqlite.md +86 -0
  117. package/docs/examples/telegram.md +77 -0
  118. package/docs/examples/tts.md +86 -0
  119. package/docs/examples/ui.md +80 -0
  120. package/docs/examples/vault.md +70 -0
  121. package/docs/examples/vm.md +86 -0
  122. package/docs/examples/window-manager.md +125 -0
  123. package/docs/examples/yaml-tree.md +93 -0
  124. package/docs/examples/yaml.md +104 -0
  125. package/docs/ideas/class-registration-refactor-possibilities.md +197 -0
  126. package/docs/ideas/container-use-api.md +9 -0
  127. package/docs/ideas/easy-auth-for-express-servers-and-luca-serve.md +0 -0
  128. package/docs/ideas/feature-stacks.md +22 -0
  129. package/docs/ideas/luca-cli-self-sufficiency-demo.md +23 -0
  130. package/docs/ideas/mcp-design.md +9 -0
  131. package/docs/ideas/web-container-debugging-feature.md +13 -0
  132. package/docs/introspection-audit.md +49 -0
  133. package/docs/introspection.md +154 -0
  134. package/docs/mcp/readme.md +162 -0
  135. package/docs/models.ts +38 -0
  136. package/docs/philosophy.md +85 -0
  137. package/docs/principles.md +7 -0
  138. package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
  139. package/docs/prompts/mcp-test-easy-command.md +27 -0
  140. package/docs/reports/assistant-bugs.md +38 -0
  141. package/docs/reports/attach-pattern-usage.md +18 -0
  142. package/docs/reports/code-audit-results.md +391 -0
  143. package/docs/reports/introspection-audit-tasks.md +378 -0
  144. package/docs/reports/luca-mcp-improvements.md +128 -0
  145. package/docs/scaffolds/client.md +140 -0
  146. package/docs/scaffolds/command.md +106 -0
  147. package/docs/scaffolds/endpoint.md +176 -0
  148. package/docs/scaffolds/feature.md +148 -0
  149. package/docs/scaffolds/server.md +187 -0
  150. package/docs/tasks/web-container-helper-discovery.md +71 -0
  151. package/docs/todos.md +1 -0
  152. package/docs/tutorials/01-getting-started.md +106 -0
  153. package/docs/tutorials/02-container.md +210 -0
  154. package/docs/tutorials/03-scripts.md +194 -0
  155. package/docs/tutorials/04-features-overview.md +196 -0
  156. package/docs/tutorials/05-state-and-events.md +171 -0
  157. package/docs/tutorials/06-servers.md +157 -0
  158. package/docs/tutorials/07-endpoints.md +198 -0
  159. package/docs/tutorials/08-commands.md +171 -0
  160. package/docs/tutorials/09-clients.md +162 -0
  161. package/docs/tutorials/10-creating-features.md +198 -0
  162. package/docs/tutorials/11-contentbase.md +191 -0
  163. package/docs/tutorials/12-assistants.md +215 -0
  164. package/docs/tutorials/13-introspection.md +147 -0
  165. package/docs/tutorials/14-type-system.md +174 -0
  166. package/docs/tutorials/15-project-patterns.md +222 -0
  167. package/docs/tutorials/16-google-features.md +534 -0
  168. package/docs/tutorials/17-tui-blocks.md +530 -0
  169. package/docs/tutorials/18-semantic-search.md +334 -0
  170. package/index.ts +1 -0
  171. package/luca.console.ts +9 -0
  172. package/main.py +6 -0
  173. package/package.json +154 -0
  174. package/pyproject.toml +7 -0
  175. package/scripts/animations/chrome-glitch.ts +55 -0
  176. package/scripts/animations/index.ts +16 -0
  177. package/scripts/animations/neon-pulse.ts +64 -0
  178. package/scripts/animations/types.ts +6 -0
  179. package/scripts/build-web.ts +28 -0
  180. package/scripts/examples/ask-luca-expert.ts +42 -0
  181. package/scripts/examples/assistant-questions.ts +12 -0
  182. package/scripts/examples/excalidraw-expert.ts +75 -0
  183. package/scripts/examples/expert-chat.ts +0 -0
  184. package/scripts/examples/file-manager.ts +14 -0
  185. package/scripts/examples/ideas.ts +12 -0
  186. package/scripts/examples/interactive-chat.ts +20 -0
  187. package/scripts/examples/openai-tool-calls.ts +113 -0
  188. package/scripts/examples/opening-a-web-browser.ts +5 -0
  189. package/scripts/examples/telegram-bot.ts +79 -0
  190. package/scripts/examples/telegram-ink-ui.ts +302 -0
  191. package/scripts/examples/using-assistant-with-mcp.ts +560 -0
  192. package/scripts/examples/using-claude-code.ts +10 -0
  193. package/scripts/examples/using-contentdb.ts +35 -0
  194. package/scripts/examples/using-conversations.ts +35 -0
  195. package/scripts/examples/using-disk-cache.ts +10 -0
  196. package/scripts/examples/using-docker-shell.ts +75 -0
  197. package/scripts/examples/using-elevenlabs.ts +25 -0
  198. package/scripts/examples/using-google-calendar.ts +57 -0
  199. package/scripts/examples/using-google-docs.ts +74 -0
  200. package/scripts/examples/using-google-drive.ts +74 -0
  201. package/scripts/examples/using-google-sheets.ts +89 -0
  202. package/scripts/examples/using-nlp.ts +55 -0
  203. package/scripts/examples/using-ollama.ts +10 -0
  204. package/scripts/examples/using-openai-codex.ts +23 -0
  205. package/scripts/examples/using-postgres.ts +55 -0
  206. package/scripts/examples/using-runpod.ts +32 -0
  207. package/scripts/examples/using-tts.ts +40 -0
  208. package/scripts/examples/vm-loading-esm-modules.ts +16 -0
  209. package/scripts/scaffold.ts +391 -0
  210. package/scripts/scratch.ts +15 -0
  211. package/scripts/test-command-listener.ts +123 -0
  212. package/scripts/test-window-manager-lifecycle.ts +86 -0
  213. package/scripts/test-window-manager.ts +43 -0
  214. package/scripts/update-introspection-data.ts +58 -0
  215. package/src/agi/README.md +14 -0
  216. package/src/agi/container.server.ts +114 -0
  217. package/src/agi/endpoints/ask.ts +60 -0
  218. package/src/agi/endpoints/conversations/[id].ts +45 -0
  219. package/src/agi/endpoints/conversations.ts +31 -0
  220. package/src/agi/endpoints/experts.ts +37 -0
  221. package/src/agi/features/assistant.ts +767 -0
  222. package/src/agi/features/assistants-manager.ts +260 -0
  223. package/src/agi/features/claude-code.ts +1111 -0
  224. package/src/agi/features/conversation-history.ts +497 -0
  225. package/src/agi/features/conversation.ts +799 -0
  226. package/src/agi/features/openai-codex.ts +631 -0
  227. package/src/agi/features/openapi.ts +438 -0
  228. package/src/agi/features/skills-library.ts +425 -0
  229. package/src/agi/index.ts +6 -0
  230. package/src/agi/lib/token-counter.ts +122 -0
  231. package/src/browser.ts +25 -0
  232. package/src/bus.ts +100 -0
  233. package/src/cli/cli.ts +70 -0
  234. package/src/client.ts +461 -0
  235. package/src/clients/civitai/index.ts +541 -0
  236. package/src/clients/client-template.ts +41 -0
  237. package/src/clients/comfyui/index.ts +597 -0
  238. package/src/clients/elevenlabs/index.ts +291 -0
  239. package/src/clients/openai/index.ts +451 -0
  240. package/src/clients/supabase/index.ts +366 -0
  241. package/src/command.ts +164 -0
  242. package/src/commands/chat.ts +182 -0
  243. package/src/commands/console.ts +192 -0
  244. package/src/commands/describe.ts +433 -0
  245. package/src/commands/eval.ts +116 -0
  246. package/src/commands/help.ts +214 -0
  247. package/src/commands/index.ts +14 -0
  248. package/src/commands/mcp.ts +64 -0
  249. package/src/commands/prompt.ts +807 -0
  250. package/src/commands/run.ts +257 -0
  251. package/src/commands/sandbox-mcp.ts +439 -0
  252. package/src/commands/scaffold.ts +79 -0
  253. package/src/commands/serve.ts +172 -0
  254. package/src/container.ts +781 -0
  255. package/src/endpoint.ts +340 -0
  256. package/src/feature.ts +75 -0
  257. package/src/hash-object.ts +97 -0
  258. package/src/helper.ts +543 -0
  259. package/src/introspection/generated.agi.ts +23388 -0
  260. package/src/introspection/generated.node.ts +18899 -0
  261. package/src/introspection/generated.web.ts +2021 -0
  262. package/src/introspection/index.ts +256 -0
  263. package/src/introspection/scan.ts +912 -0
  264. package/src/node/container.ts +354 -0
  265. package/src/node/feature.ts +13 -0
  266. package/src/node/features/container-link.ts +558 -0
  267. package/src/node/features/content-db.ts +475 -0
  268. package/src/node/features/disk-cache.ts +382 -0
  269. package/src/node/features/dns.ts +655 -0
  270. package/src/node/features/docker.ts +912 -0
  271. package/src/node/features/downloader.ts +92 -0
  272. package/src/node/features/esbuild.ts +68 -0
  273. package/src/node/features/file-manager.ts +357 -0
  274. package/src/node/features/fs.ts +534 -0
  275. package/src/node/features/git.ts +492 -0
  276. package/src/node/features/google-auth.ts +502 -0
  277. package/src/node/features/google-calendar.ts +300 -0
  278. package/src/node/features/google-docs.ts +404 -0
  279. package/src/node/features/google-drive.ts +339 -0
  280. package/src/node/features/google-sheets.ts +279 -0
  281. package/src/node/features/grep.ts +406 -0
  282. package/src/node/features/helpers.ts +374 -0
  283. package/src/node/features/ink.ts +490 -0
  284. package/src/node/features/ipc-socket.ts +459 -0
  285. package/src/node/features/json-tree.ts +188 -0
  286. package/src/node/features/launcher-app-command-listener.ts +388 -0
  287. package/src/node/features/networking.ts +925 -0
  288. package/src/node/features/nlp.ts +211 -0
  289. package/src/node/features/opener.ts +166 -0
  290. package/src/node/features/os.ts +157 -0
  291. package/src/node/features/package-finder.ts +539 -0
  292. package/src/node/features/port-exposer.ts +342 -0
  293. package/src/node/features/postgres.ts +273 -0
  294. package/src/node/features/proc.ts +502 -0
  295. package/src/node/features/process-manager.ts +542 -0
  296. package/src/node/features/python.ts +444 -0
  297. package/src/node/features/repl.ts +194 -0
  298. package/src/node/features/runpod.ts +802 -0
  299. package/src/node/features/secure-shell.ts +248 -0
  300. package/src/node/features/semantic-search.ts +924 -0
  301. package/src/node/features/sqlite.ts +289 -0
  302. package/src/node/features/telegram.ts +342 -0
  303. package/src/node/features/tts.ts +184 -0
  304. package/src/node/features/ui.ts +857 -0
  305. package/src/node/features/vault.ts +164 -0
  306. package/src/node/features/vm.ts +312 -0
  307. package/src/node/features/window-manager.ts +804 -0
  308. package/src/node/features/yaml-tree.ts +149 -0
  309. package/src/node/features/yaml.ts +132 -0
  310. package/src/node.ts +70 -0
  311. package/src/react/index.ts +175 -0
  312. package/src/registry.ts +199 -0
  313. package/src/scaffolds/generated.ts +1613 -0
  314. package/src/scaffolds/template.ts +37 -0
  315. package/src/schemas/base.ts +255 -0
  316. package/src/server.ts +135 -0
  317. package/src/servers/express.ts +209 -0
  318. package/src/servers/mcp.ts +805 -0
  319. package/src/servers/socket.ts +120 -0
  320. package/src/state.ts +101 -0
  321. package/src/web/clients/socket.ts +82 -0
  322. package/src/web/container.ts +74 -0
  323. package/src/web/extension.ts +30 -0
  324. package/src/web/feature.ts +12 -0
  325. package/src/web/features/asset-loader.ts +64 -0
  326. package/src/web/features/container-link.ts +385 -0
  327. package/src/web/features/esbuild.ts +79 -0
  328. package/src/web/features/helpers.ts +267 -0
  329. package/src/web/features/network.ts +61 -0
  330. package/src/web/features/speech.ts +87 -0
  331. package/src/web/features/vault.ts +189 -0
  332. package/src/web/features/vm.ts +78 -0
  333. package/src/web/features/voice-recognition.ts +129 -0
  334. package/src/web/shims/isomorphic-vm.ts +149 -0
  335. package/test/bus.test.ts +134 -0
  336. package/test/clients-servers.test.ts +216 -0
  337. package/test/container-link.test.ts +274 -0
  338. package/test/features.test.ts +160 -0
  339. package/test/integration.test.ts +787 -0
  340. package/test/node-container.test.ts +121 -0
  341. package/test/rate-limit.test.ts +272 -0
  342. package/test/semantic-search.test.ts +550 -0
  343. package/test/state.test.ts +121 -0
  344. package/test-integration/assistant.test.ts +138 -0
  345. package/test-integration/assistants-manager.test.ts +123 -0
  346. package/test-integration/claude-code.test.ts +98 -0
  347. package/test-integration/conversation-history.test.ts +205 -0
  348. package/test-integration/conversation.test.ts +137 -0
  349. package/test-integration/elevenlabs.test.ts +55 -0
  350. package/test-integration/google-services.test.ts +80 -0
  351. package/test-integration/helpers.ts +89 -0
  352. package/test-integration/openai-codex.test.ts +93 -0
  353. package/test-integration/runpod.test.ts +58 -0
  354. package/test-integration/server-endpoints.test.ts +97 -0
  355. package/test-integration/skills-library.test.ts +157 -0
  356. package/test-integration/telegram.test.ts +46 -0
  357. package/tsconfig.json +58 -0
  358. package/uv.lock +8 -0
@@ -0,0 +1,75 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ async function main() {
4
+ const docker = container.feature('docker', { enable: true, autoRefresh: true })
5
+
6
+ // List running containers so we can pick one
7
+ const containers = await docker.listContainers()
8
+ console.log('Running containers:', containers.map((c) => `${c.name} (${c.image})`).join(', ') || 'none')
9
+
10
+ if (!containers.length) {
11
+ console.log('\nNo running containers. Starting an alpine container for the demo...')
12
+ await docker.runContainer('alpine:latest', {
13
+ name: 'luca-shell-demo',
14
+ detach: true,
15
+ command: ['sleep', 'infinity'],
16
+ })
17
+ console.log('Started luca-shell-demo')
18
+ }
19
+
20
+ const target = containers[0]?.name || 'luca-shell-demo'
21
+
22
+ // --- Basic shell (no volumes) ---
23
+ console.log(`\n--- Basic shell against "${target}" ---`)
24
+ const shell = await docker.createShell(target)
25
+
26
+ await shell.run('echo "Hello from inside the container"')
27
+ console.log('stdout:', shell.last!.stdout.trim())
28
+
29
+ await shell.run('uname -a')
30
+ console.log('uname:', shell.last!.stdout.trim())
31
+
32
+ await shell.run('ls /')
33
+ console.log('root listing:', shell.last!.stdout.trim())
34
+
35
+ // --- Shell with volume mounts ---
36
+ // This creates a new helper container from the same image with the mounts applied
37
+ console.log(`\n--- Shell with volume mount ---`)
38
+ const mounted = await docker.createShell(target, {
39
+ volumes: [`${process.cwd()}:/workspace`],
40
+ workdir: '/workspace',
41
+ })
42
+
43
+ console.log('Helper container:', mounted.containerId)
44
+
45
+ await mounted.run('ls -la')
46
+ console.log('workspace files:\n', mounted.last!.stdout)
47
+
48
+ await mounted.run('wc -l package.json')
49
+ console.log('package.json lines:', mounted.last!.stdout.trim())
50
+
51
+ // Write a file from inside the container, visible on the host
52
+ await mounted.run('echo "written by docker shell" > /workspace/.docker-shell-test')
53
+ console.log('Wrote .docker-shell-test (exit code:', mounted.last!.exitCode, ')')
54
+
55
+ // Clean up the helper container
56
+ await mounted.destroy()
57
+ console.log('Helper container destroyed')
58
+
59
+ // --- Using execCommand directly with volumes (one-shot) ---
60
+ console.log(`\n--- One-shot execCommand with volumes ---`)
61
+ const result = await docker.execCommand(target, ['cat', '/data/package.json'], {
62
+ volumes: [`${process.cwd()}/package.json:/data/package.json:ro`],
63
+ })
64
+ console.log('package.json name:', JSON.parse(result.stdout).name)
65
+
66
+ // Clean up demo container if we created it
67
+ if (!containers.length) {
68
+ await docker.removeContainer('luca-shell-demo', { force: true })
69
+ console.log('\nCleaned up luca-shell-demo')
70
+ }
71
+
72
+ console.log('\nDone!')
73
+ }
74
+
75
+ main().catch(console.error)
@@ -0,0 +1,25 @@
1
+ import container from '@soederpop/luca/node'
2
+ import '../../src/clients/elevenlabs'
3
+
4
+ async function main() {
5
+ const phrase = container.argv.phrase || 'Hello! This is a test of the ElevenLabs text to speech client.'
6
+ const voiceId = container.argv.voice || 'D3LWHMMgiK6AHC5Bl7dE'
7
+ const outputPath = `/tmp/elevenlabs-${Date.now()}.mp3`
8
+
9
+ const el = container.client('elevenlabs')
10
+ await el.connect()
11
+
12
+ console.log('Synthesizing:', phrase)
13
+ const audio = await el.synthesize(phrase, { voiceId })
14
+ console.log(`Audio size: ${(audio.length / 1024).toFixed(1)} KB`)
15
+
16
+ await container.fs.writeFileAsync(outputPath, audio)
17
+ console.log(`Saved to: ${outputPath}`)
18
+
19
+ console.log('Playing...')
20
+ const proc = container.feature('proc')
21
+ await proc.spawnAndCapture('afplay', [outputPath])
22
+ console.log('Done!')
23
+ }
24
+
25
+ main().catch(console.error)
@@ -0,0 +1,57 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ async function main() {
4
+ // GoogleAuth reads GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET from env.
5
+ // On first run it opens your browser for OAuth2 consent.
6
+ // The refresh token is saved in diskCache so subsequent runs skip the browser.
7
+ const auth = container.feature('googleAuth', {
8
+ scopes: ['https://www.googleapis.com/auth/calendar.readonly'],
9
+ })
10
+
11
+ const restored = await auth.tryRestoreTokens()
12
+
13
+ if (restored) {
14
+ console.log(`Restored session for ${auth.state.get('email')}`)
15
+ } else {
16
+ console.log('No cached credentials found — opening browser for authorization...')
17
+ await auth.authorize()
18
+ console.log(`Authorized as ${auth.state.get('email')}`)
19
+ }
20
+
21
+ const calendar = container.feature('googleCalendar', {
22
+ timeZone: 'America/Chicago',
23
+ })
24
+
25
+ // List accessible calendars
26
+ const calendars = await calendar.listCalendars()
27
+ console.log(`\nYou have access to ${calendars.length} calendars:`)
28
+ for (const cal of calendars) {
29
+ const tag = cal.primary ? ' (primary)' : ''
30
+ console.log(` - ${cal.summary}${tag}`)
31
+ }
32
+
33
+ // Today's events
34
+ const today = await calendar.getToday()
35
+ console.log(`\nToday's events (${today.length}):`)
36
+ for (const event of today) {
37
+ const time = event.start.dateTime
38
+ ? new Date(event.start.dateTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
39
+ : 'All day'
40
+ console.log(` ${time} ${event.summary}`)
41
+ }
42
+
43
+ // Upcoming 7 days
44
+ const upcoming = await calendar.getUpcoming(7)
45
+ console.log(`\nNext 7 days (${upcoming.length} events):`)
46
+ for (const event of upcoming) {
47
+ const date = event.start.dateTime
48
+ ? new Date(event.start.dateTime).toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })
49
+ : event.start.date || ''
50
+ const time = event.start.dateTime
51
+ ? new Date(event.start.dateTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
52
+ : 'All day'
53
+ console.log(` ${date} ${time} ${event.summary}`)
54
+ }
55
+ }
56
+
57
+ main().catch(console.error)
@@ -0,0 +1,74 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ // Pass a document ID as the first argument, or omit to list available docs.
4
+ // You can find the ID in a Google Docs URL:
5
+ // https://docs.google.com/document/d/DOCUMENT_ID/edit
6
+ const documentId = process.argv[2]
7
+
8
+ async function main() {
9
+ // GoogleAuth reads GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET from env.
10
+ // On first run it opens your browser for OAuth2 consent.
11
+ // The refresh token is saved in diskCache so subsequent runs skip the browser.
12
+ const auth = container.feature('googleAuth', {
13
+ scopes: [
14
+ 'https://www.googleapis.com/auth/documents.readonly',
15
+ 'https://www.googleapis.com/auth/drive.readonly',
16
+ ],
17
+ })
18
+
19
+ const restored = await auth.tryRestoreTokens()
20
+
21
+ if (restored) {
22
+ console.log(`Restored session for ${auth.state.get('email')}`)
23
+ } else {
24
+ console.log('No cached credentials found — opening browser for authorization...')
25
+ await auth.authorize()
26
+ console.log(`Authorized as ${auth.state.get('email')}`)
27
+ }
28
+
29
+ const docs = container.feature('googleDocs')
30
+
31
+ // List recent Google Docs
32
+ const allDocs = await docs.listDocs()
33
+ console.log(`\n--- Your Google Docs (${allDocs.length}) ---`)
34
+ for (const doc of allDocs.slice(0, 15)) {
35
+ const modified = doc.modifiedTime
36
+ ? new Date(doc.modifiedTime).toLocaleDateString()
37
+ : ''
38
+ console.log(` ${doc.name} ${modified}`)
39
+ console.log(` id: ${doc.id}`)
40
+ }
41
+ if (allDocs.length > 15) {
42
+ console.log(` ... and ${allDocs.length - 15} more`)
43
+ }
44
+
45
+ // If a document ID was provided, read it
46
+ if (documentId) {
47
+ // Plain text
48
+ const text = await docs.getAsText(documentId)
49
+ const lines = text.split('\n')
50
+ console.log(`\n--- Document as Plain Text (first 20 lines) ---`)
51
+ for (const line of lines.slice(0, 20)) {
52
+ console.log(` ${line}`)
53
+ }
54
+ if (lines.length > 20) {
55
+ console.log(` ... and ${lines.length - 20} more lines`)
56
+ }
57
+
58
+ // Markdown
59
+ const markdown = await docs.getAsMarkdown(documentId)
60
+ const mdLines = markdown.split('\n')
61
+ console.log(`\n--- Document as Markdown (first 30 lines) ---`)
62
+ for (const line of mdLines.slice(0, 30)) {
63
+ console.log(` ${line}`)
64
+ }
65
+ if (mdLines.length > 30) {
66
+ console.log(` ... and ${mdLines.length - 30} more lines`)
67
+ }
68
+ } else {
69
+ console.log('\nTip: pass a document ID to read its contents:')
70
+ console.log(' bun run scripts/examples/using-google-docs.ts <document-id>')
71
+ }
72
+ }
73
+
74
+ main().catch(console.error)
@@ -0,0 +1,74 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ async function main() {
4
+ // GoogleAuth reads GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET from env.
5
+ // On first run it opens your browser for OAuth2 consent.
6
+ // The refresh token is saved in diskCache so subsequent runs skip the browser.
7
+ const auth = container.feature('googleAuth', {
8
+ scopes: ['https://www.googleapis.com/auth/drive.readonly'],
9
+ })
10
+
11
+ const restored = await auth.tryRestoreTokens()
12
+
13
+ if (restored) {
14
+ console.log(`Restored session for ${auth.state.get('email')}`)
15
+ } else {
16
+ console.log('No cached credentials found — opening browser for authorization...')
17
+ await auth.authorize()
18
+ console.log(`Authorized as ${auth.state.get('email')}`)
19
+ }
20
+
21
+ const drive = container.feature('googleDrive')
22
+
23
+ // List recent files
24
+ const { files: recent } = await drive.listFiles(undefined, { pageSize: 10 })
25
+ console.log(`\n--- 10 Most Recently Modified Files ---`)
26
+ for (const file of recent) {
27
+ const modified = file.modifiedTime
28
+ ? new Date(file.modifiedTime).toLocaleDateString()
29
+ : ''
30
+ const size = file.size ? `${(parseInt(file.size) / 1024).toFixed(1)} KB` : ''
31
+ console.log(` ${file.name} ${modified} ${size}`)
32
+ console.log(` type: ${file.mimeType}`)
33
+ }
34
+
35
+ // Browse root folder
36
+ const root = await drive.browse('root')
37
+ console.log(`\n--- Root Folder ---`)
38
+ console.log(`Folders (${root.folders.length}):`)
39
+ for (const folder of root.folders.slice(0, 10)) {
40
+ console.log(` 📁 ${folder.name}`)
41
+ }
42
+ console.log(`Files (${root.files.length}):`)
43
+ for (const file of root.files.slice(0, 10)) {
44
+ console.log(` 📄 ${file.name} (${file.mimeType})`)
45
+ }
46
+
47
+ // Search for documents
48
+ const { files: docs } = await drive.search('report', {
49
+ mimeType: 'application/vnd.google-apps.document',
50
+ pageSize: 5,
51
+ })
52
+ console.log(`\n--- Search: "report" (Google Docs only) ---`)
53
+ if (docs.length === 0) {
54
+ console.log(' No matching documents found.')
55
+ } else {
56
+ for (const doc of docs) {
57
+ console.log(` ${doc.name}`)
58
+ if (doc.webViewLink) console.log(` ${doc.webViewLink}`)
59
+ }
60
+ }
61
+
62
+ // List shared drives
63
+ const sharedDrives = await drive.listDrives()
64
+ console.log(`\n--- Shared Drives (${sharedDrives.length}) ---`)
65
+ if (sharedDrives.length === 0) {
66
+ console.log(' No shared drives found.')
67
+ } else {
68
+ for (const sd of sharedDrives) {
69
+ console.log(` ${sd.name} (${sd.id})`)
70
+ }
71
+ }
72
+ }
73
+
74
+ main().catch(console.error)
@@ -0,0 +1,89 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ // Pass a spreadsheet ID as the first argument, or set DEFAULT_SPREADSHEET_ID env var.
4
+ // You can find the ID in a Google Sheets URL:
5
+ // https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit
6
+ const spreadsheetId = process.argv[2] || process.env.DEFAULT_SPREADSHEET_ID
7
+
8
+ async function main() {
9
+ if (!spreadsheetId) {
10
+ console.error('Usage: bun run scripts/examples/using-google-sheets.ts <spreadsheet-id>')
11
+ console.error(' or set DEFAULT_SPREADSHEET_ID env var')
12
+ process.exit(1)
13
+ }
14
+
15
+ // GoogleAuth reads GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET from env.
16
+ // On first run it opens your browser for OAuth2 consent.
17
+ // The refresh token is saved in diskCache so subsequent runs skip the browser.
18
+ const auth = container.feature('googleAuth', {
19
+ scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
20
+ })
21
+
22
+ const restored = await auth.tryRestoreTokens()
23
+
24
+ if (restored) {
25
+ console.log(`Restored session for ${auth.state.get('email')}`)
26
+ } else {
27
+ console.log('No cached credentials found — opening browser for authorization...')
28
+ await auth.authorize()
29
+ console.log(`Authorized as ${auth.state.get('email')}`)
30
+ }
31
+
32
+ const sheets = container.feature('googleSheets', {
33
+ defaultSpreadsheetId: spreadsheetId,
34
+ })
35
+
36
+ // Get spreadsheet metadata
37
+ const meta = await sheets.getSpreadsheet()
38
+ console.log(`\n--- Spreadsheet: "${meta.title}" ---`)
39
+ console.log(`Locale: ${meta.locale}`)
40
+ console.log(`Sheets (${meta.sheets.length}):`)
41
+ for (const sheet of meta.sheets) {
42
+ console.log(` ${sheet.title} (${sheet.rowCount} rows × ${sheet.columnCount} cols)`)
43
+ }
44
+
45
+ // Read first sheet as JSON (first row = headers)
46
+ const firstSheet = meta.sheets[0]
47
+ if (!firstSheet) {
48
+ console.log('\nNo sheets found in this spreadsheet.')
49
+ return
50
+ }
51
+
52
+ const data = await sheets.getAsJson(firstSheet.title)
53
+ console.log(`\n--- "${firstSheet.title}" as JSON (first 5 rows) ---`)
54
+ if (data.length === 0) {
55
+ console.log(' (empty or header-only sheet)')
56
+ } else {
57
+ const headers = Object.keys(data[0]!)
58
+ console.log(` Columns: ${headers.join(', ')}`)
59
+ for (const row of data.slice(0, 5)) {
60
+ console.log(` ${JSON.stringify(row)}`)
61
+ }
62
+ if (data.length > 5) {
63
+ console.log(` ... and ${data.length - 5} more rows`)
64
+ }
65
+ }
66
+
67
+ // Read as CSV
68
+ const csv = await sheets.getAsCsv(firstSheet.title)
69
+ const csvLines = csv.split('\n')
70
+ console.log(`\n--- "${firstSheet.title}" as CSV (first 5 lines) ---`)
71
+ for (const line of csvLines.slice(0, 5)) {
72
+ console.log(` ${line}`)
73
+ }
74
+ if (csvLines.length > 5) {
75
+ console.log(` ... and ${csvLines.length - 5} more lines`)
76
+ }
77
+
78
+ // Read a specific range if there are enough rows
79
+ if (firstSheet.rowCount >= 2 && firstSheet.columnCount >= 2) {
80
+ const range = `${firstSheet.title}!A1:B5`
81
+ const values = await sheets.getRange(range)
82
+ console.log(`\n--- Range: ${range} ---`)
83
+ for (const row of values) {
84
+ console.log(` ${row.join('\t')}`)
85
+ }
86
+ }
87
+ }
88
+
89
+ main().catch(console.error)
@@ -0,0 +1,55 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ const nlp = container.feature('nlp', { enable: true })
4
+
5
+ // --- parse(): compromise-powered verb normalization + structure extraction ---
6
+ console.log('=== parse() ===\n')
7
+
8
+ const commands = [
9
+ 'open the terminal',
10
+ 'draw a diagram of the auth flow',
11
+ 'write something about baseball',
12
+ 'quickly search for recent logs',
13
+ 'deploy the new build to staging',
14
+ ]
15
+
16
+ for (const cmd of commands) {
17
+ const result = nlp.parse(cmd)
18
+ console.log(`"${cmd}"`)
19
+ console.log(` intent: ${result.intent}, target: ${result.target}, subject: ${result.subject}`)
20
+ if (result.modifiers.length) console.log(` modifiers: ${result.modifiers.join(', ')}`)
21
+ console.log()
22
+ }
23
+
24
+ // --- analyze(): wink-nlp POS tagging + named entity recognition ---
25
+ console.log('=== analyze() ===\n')
26
+
27
+ const sentences = [
28
+ 'meet john at 3pm about the deployment',
29
+ 'send the report to sarah by friday',
30
+ 'there are 42 open issues in the repo',
31
+ ]
32
+
33
+ for (const sentence of sentences) {
34
+ const result = nlp.analyze(sentence)
35
+ console.log(`"${sentence}"`)
36
+ console.log(` tokens: ${result.tokens.map(t => `${t.value}/${t.pos}`).join(' ')}`)
37
+ if (result.entities.length) {
38
+ console.log(` entities: ${result.entities.map(e => `${e.value} (${e.type})`).join(', ')}`)
39
+ }
40
+ console.log()
41
+ }
42
+
43
+ // --- understand(): combined parse + analyze ---
44
+ console.log('=== understand() ===\n')
45
+
46
+ const utterance = 'create a new project for the dashboard'
47
+ const full = nlp.understand(utterance)
48
+ console.log(`"${utterance}"`)
49
+ console.log(` intent: ${full.intent}`)
50
+ console.log(` target: ${full.target}`)
51
+ console.log(` subject: ${full.subject}`)
52
+ console.log(` tokens: ${full.tokens.map(t => `${t.value}/${t.pos}`).join(' ')}`)
53
+ if (full.entities.length) {
54
+ console.log(` entities: ${full.entities.map(e => `${e.value} (${e.type})`).join(', ')}`)
55
+ }
@@ -0,0 +1,10 @@
1
+ import container from '@soederpop/luca/agi'
2
+
3
+ const conversation = container.feature('conversation', {
4
+ local: true,
5
+ model: "qwen2.5:7b"
6
+ })
7
+
8
+ const response = await conversation.ask('What model am I using?')
9
+
10
+ console.log(response)
@@ -0,0 +1,23 @@
1
+ import container from '@soederpop/luca/agi'
2
+
3
+ const codex = container.feature('openaiCodex')
4
+
5
+ // Stream deltas as they come in
6
+ codex.on('session:delta', ({ text }: any) => process.stdout.write(text))
7
+ codex.on('session:exec', ({ exec }: any) => console.log(`\n[exec] ${exec.command?.join(' ')}`))
8
+ codex.on('session:patch', ({ patch }: any) => console.log(`\n[patch] ${patch.path}`))
9
+
10
+ async function main() {
11
+ const session = await codex.run('Explain the purpose of this project in a few sentences.', {
12
+ fullAuto: true,
13
+ })
14
+
15
+ console.log('\n---')
16
+ console.log('Status:', session.status)
17
+ console.log('Result:', session.result)
18
+ console.log('Turns:', session.turns)
19
+ console.log('Patches:', session.patches.length)
20
+ console.log('Execs:', session.executions.length)
21
+ }
22
+
23
+ main()
@@ -0,0 +1,55 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ const DEFAULT_DATABASE_URL = 'postgresql://postgres:postgres@127.0.0.1:54322/postgres'
4
+
5
+ type TableRow = {
6
+ table_schema: string
7
+ table_name: string
8
+ }
9
+
10
+ async function main() {
11
+ const url = process.env.DATABASE_URL || DEFAULT_DATABASE_URL
12
+ const postgres = container.feature('postgres', { url })
13
+
14
+ try {
15
+ const tables = await withTimeout(
16
+ postgres.query<TableRow>(
17
+ `
18
+ select table_schema, table_name
19
+ from information_schema.tables
20
+ where table_type = 'BASE TABLE'
21
+ and table_schema not in ('pg_catalog', 'information_schema')
22
+ order by table_schema, table_name
23
+ `
24
+ ),
25
+ 8000,
26
+ `Timed out connecting/querying ${url}`
27
+ )
28
+
29
+ if (tables.length === 0) {
30
+ console.log('No user tables found.')
31
+ return
32
+ }
33
+
34
+ console.log(`Found ${tables.length} table(s):`)
35
+ for (const table of tables) {
36
+ console.log(`- ${table.table_schema}.${table.table_name}`)
37
+ }
38
+ } finally {
39
+ await withTimeout(postgres.close(), 1000, 'Timed out while closing Postgres connection').catch(() => {})
40
+ }
41
+ }
42
+
43
+ main().catch((error) => {
44
+ console.error('Failed to list Postgres tables:', error)
45
+ process.exit(1)
46
+ })
47
+
48
+ function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
49
+ return Promise.race([
50
+ promise,
51
+ new Promise<T>((_, reject) => {
52
+ setTimeout(() => reject(new Error(message)), timeoutMs)
53
+ }),
54
+ ])
55
+ }
@@ -0,0 +1,32 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ async function main() {
4
+ const runpod = container.feature('runpod')
5
+
6
+ // List available GPUs with pricing
7
+ const gpus = await runpod.listSecureGPUs()
8
+ console.log('Available GPUs:')
9
+ console.table(gpus)
10
+
11
+ // List RunPod's official templates
12
+ const templates = await runpod.listTemplates({ includeRunpod: true })
13
+ console.log('\nAvailable Templates:')
14
+ for (const t of templates) {
15
+ console.log(` ${t.id} - ${t.name} (${t.imageName})`)
16
+ }
17
+
18
+ // Launch a pod from a template on an RTX 4090
19
+ // const pod = await runpod.createPod({
20
+ // name: 'my-workspace',
21
+ // templateId: templates[0].id,
22
+ // gpuTypeId: 'NVIDIA GeForce RTX 4090',
23
+ // })
24
+ // console.log('Created pod:', pod.id)
25
+
26
+ // List running pods
27
+ const pods = await runpod.listPods()
28
+ console.log('\nRunning Pods:')
29
+ console.table(pods.map(p => ({ id: p.id, name: p.name, gpu: p.gpu, status: p.status })))
30
+ }
31
+
32
+ main()
@@ -0,0 +1,40 @@
1
+ import container from '@soederpop/luca/node'
2
+
3
+ async function main() {
4
+ const tts = container.feature('tts', { enable: true })
5
+
6
+ console.log('Available voices:', tts.voices.join(', '))
7
+ console.log('Output directory:', tts.outputDir)
8
+ console.log()
9
+
10
+ // Synthesize a simple phrase
11
+ console.log('Synthesizing with default voice (lucy)...')
12
+ const path1 = await tts.synthesize('Hello! This is a test of the Chatterbox text to speech system.')
13
+ console.log(` Saved to: ${path1}`)
14
+
15
+ // Try a different voice
16
+ console.log('\nSynthesizing with voice "ethan"...')
17
+ const path2 = await tts.synthesize('Good morning. How can I help you today?', { voice: 'ethan' })
18
+ console.log(` Saved to: ${path2}`)
19
+
20
+ // Listen for events
21
+ tts.on('synthesized', (text, path, voice, durationMs) => {
22
+ console.log(`\n[event] synthesized "${text.slice(0, 40)}..." voice=${voice} took=${durationMs}ms`)
23
+ })
24
+
25
+ // Synthesize a longer passage
26
+ console.log('\nSynthesizing a longer passage with voice "evelyn"...')
27
+ const path3 = await tts.synthesize(
28
+ 'The quick brown fox jumps over the lazy dog. This sentence contains every letter of the English alphabet, making it a perfect pangram for testing.',
29
+ { voice: 'evelyn' }
30
+ )
31
+ console.log(` Saved to: ${path3}`)
32
+
33
+ // Play the last file with the system player (macOS)
34
+ console.log('\nPlaying last generated audio...')
35
+ const proc = container.feature('proc')
36
+ await proc.spawnAndCapture('afplay', [path3])
37
+ console.log('Done!')
38
+ }
39
+
40
+ main().catch(console.error)
@@ -0,0 +1,16 @@
1
+ import container from '@soederpop/luca/agi'
2
+
3
+ async function main() {
4
+ const vm = container.feature('vm')
5
+ const skillsFile = container.paths.resolve('experts/luca-core-framework/skills.ts')
6
+ const skills = await container.fs.readFile(skillsFile)
7
+ const transformedSkills = await container.feature('esbuild').transform(skills.toString(), { format: 'cjs' })
8
+
9
+ const mod = { exports: {} as Record<string, any> }
10
+ await vm.run(transformedSkills.code, { container, module: mod, exports: mod.exports })
11
+
12
+ console.log('Loaded skills:', Object.keys(mod.exports))
13
+ console.log(mod.exports)
14
+ }
15
+
16
+ main()