@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,212 @@
1
+ # Postgres (features.postgres)
2
+
3
+ Postgres feature for safe SQL execution through Bun's native SQL client. Supports: - parameterized query execution (`query` / `execute`) - tagged-template query execution (`sql`) to avoid manual placeholder wiring
4
+
5
+ ## Usage
6
+
7
+ ```ts
8
+ container.feature('postgres', {
9
+ // Postgres connection URL, e.g. postgres://user:pass@host:5432/db
10
+ url,
11
+ })
12
+ ```
13
+
14
+ ## Options (Zod v4 schema)
15
+
16
+ | Property | Type | Description |
17
+ |----------|------|-------------|
18
+ | `url` | `string` | Postgres connection URL, e.g. postgres://user:pass@host:5432/db |
19
+
20
+ ## Methods
21
+
22
+ ### query
23
+
24
+ Executes a SELECT-like query and returns result rows. Use postgres placeholders (`$1`, `$2`, ...) for `params`.
25
+
26
+ **Parameters:**
27
+
28
+ | Name | Type | Required | Description |
29
+ |------|------|----------|-------------|
30
+ | `queryText` | `string` | ✓ | The SQL query string with optional `$N` placeholders |
31
+ | `params` | `SqlValue[]` | | Ordered array of values to bind to the placeholders |
32
+
33
+ **Returns:** `Promise<T[]>`
34
+
35
+ ```ts
36
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
37
+ const users = await pg.query<{ id: number; email: string }>(
38
+ 'SELECT id, email FROM users WHERE active = $1',
39
+ [true]
40
+ )
41
+ ```
42
+
43
+
44
+
45
+ ### execute
46
+
47
+ Executes a write/update/delete statement and returns metadata. Use postgres placeholders (`$1`, `$2`, ...) for `params`.
48
+
49
+ **Parameters:**
50
+
51
+ | Name | Type | Required | Description |
52
+ |------|------|----------|-------------|
53
+ | `queryText` | `string` | ✓ | The SQL statement string with optional `$N` placeholders |
54
+ | `params` | `SqlValue[]` | | Ordered array of values to bind to the placeholders |
55
+
56
+ **Returns:** `Promise<{ rowCount: number }>`
57
+
58
+ ```ts
59
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
60
+ const { rowCount } = await pg.execute(
61
+ 'UPDATE users SET active = $1 WHERE last_login < $2',
62
+ [false, '2024-01-01']
63
+ )
64
+ console.log(`Deactivated ${rowCount} users`)
65
+ ```
66
+
67
+
68
+
69
+ ### sql
70
+
71
+ Safe tagged-template SQL helper. Values become bound parameters automatically, preventing SQL injection.
72
+
73
+ **Parameters:**
74
+
75
+ | Name | Type | Required | Description |
76
+ |------|------|----------|-------------|
77
+ | `strings` | `TemplateStringsArray` | ✓ | Template literal string segments |
78
+ | `values` | `SqlValue[]` | ✓ | Interpolated values that become bound `$N` parameters |
79
+
80
+ **Returns:** `Promise<T[]>`
81
+
82
+ ```ts
83
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
84
+ const email = 'hello@example.com'
85
+ const rows = await pg.sql<{ id: number }>`
86
+ SELECT id FROM users WHERE email = ${email}
87
+ `
88
+ ```
89
+
90
+
91
+
92
+ ### close
93
+
94
+ Closes the postgres connection and updates feature state. Emits `closed` after the connection is torn down.
95
+
96
+ **Returns:** `void`
97
+
98
+ ```ts
99
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
100
+ // ... run queries ...
101
+ await pg.close()
102
+ ```
103
+
104
+
105
+
106
+ ## Getters
107
+
108
+ | Property | Type | Description |
109
+ |----------|------|-------------|
110
+ | `client` | `any` | Returns the underlying Bun SQL postgres client. |
111
+
112
+ ## Events (Zod v4 schema)
113
+
114
+ ### query
115
+
116
+ Event emitted by Postgres
117
+
118
+
119
+
120
+ ### error
121
+
122
+ Event emitted by Postgres
123
+
124
+
125
+
126
+ ### execute
127
+
128
+ Event emitted by Postgres
129
+
130
+
131
+
132
+ ### closed
133
+
134
+ Event emitted by Postgres
135
+
136
+
137
+
138
+ ## State (Zod v4 schema)
139
+
140
+ | Property | Type | Description |
141
+ |----------|------|-------------|
142
+ | `enabled` | `boolean` | Whether this feature is currently enabled |
143
+ | `connected` | `boolean` | Whether the postgres connection is currently open |
144
+ | `url` | `string` | Connection URL used for this postgres feature instance |
145
+ | `lastQuery` | `string` | Most recent SQL query string that was executed |
146
+ | `lastRowCount` | `number` | Row count returned by the most recent query execution |
147
+ | `lastError` | `string` | Most recent postgres error message, if any |
148
+
149
+ ## Examples
150
+
151
+ **features.postgres**
152
+
153
+ ```ts
154
+ const postgres = container.feature('postgres', { url: process.env.DATABASE_URL! })
155
+
156
+ const users = await postgres.query<{ id: number; email: string }>(
157
+ 'select id, email from users where id = $1',
158
+ [123]
159
+ )
160
+
161
+ const rows = await postgres.sql<{ id: number }>`
162
+ select id from users where email = ${'hello@example.com'}
163
+ `
164
+ ```
165
+
166
+
167
+
168
+ **query**
169
+
170
+ ```ts
171
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
172
+ const users = await pg.query<{ id: number; email: string }>(
173
+ 'SELECT id, email FROM users WHERE active = $1',
174
+ [true]
175
+ )
176
+ ```
177
+
178
+
179
+
180
+ **execute**
181
+
182
+ ```ts
183
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
184
+ const { rowCount } = await pg.execute(
185
+ 'UPDATE users SET active = $1 WHERE last_login < $2',
186
+ [false, '2024-01-01']
187
+ )
188
+ console.log(`Deactivated ${rowCount} users`)
189
+ ```
190
+
191
+
192
+
193
+ **sql**
194
+
195
+ ```ts
196
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
197
+ const email = 'hello@example.com'
198
+ const rows = await pg.sql<{ id: number }>`
199
+ SELECT id FROM users WHERE email = ${email}
200
+ `
201
+ ```
202
+
203
+
204
+
205
+ **close**
206
+
207
+ ```ts
208
+ const pg = container.feature('postgres', { url: process.env.DATABASE_URL! })
209
+ // ... run queries ...
210
+ await pg.close()
211
+ ```
212
+
@@ -0,0 +1,430 @@
1
+ # ChildProcess (features.proc)
2
+
3
+ The ChildProcess feature provides utilities for executing external processes and commands. This feature wraps Node.js child process functionality to provide convenient methods for executing shell commands, spawning processes, and capturing their output. It supports both synchronous and asynchronous execution with various options.
4
+
5
+ ## Usage
6
+
7
+ ```ts
8
+ container.feature('proc')
9
+ ```
10
+
11
+ ## Methods
12
+
13
+ ### execAndCapture
14
+
15
+ Executes a command string and captures its output asynchronously. This method takes a complete command string, splits it into command and arguments, and executes it using the spawnAndCapture method. It's a convenient wrapper for simple command execution.
16
+
17
+ **Parameters:**
18
+
19
+ | Name | Type | Required | Description |
20
+ |------|------|----------|-------------|
21
+ | `cmd` | `string` | ✓ | The complete command string to execute (e.g., "git status --porcelain") |
22
+ | `options` | `any` | | Options to pass to the underlying spawn process |
23
+
24
+ **Returns:** `Promise<{
25
+ stderr: string;
26
+ stdout: string;
27
+ error: null | any;
28
+ exitCode: number;
29
+ pid: number | null;
30
+ }>`
31
+
32
+ ```ts
33
+ // Execute a git command
34
+ const result = await proc.execAndCapture('git status --porcelain')
35
+ if (result.exitCode === 0) {
36
+ console.log('Git status:', result.stdout)
37
+ } else {
38
+ console.error('Git error:', result.stderr)
39
+ }
40
+
41
+ // Execute with options
42
+ const result = await proc.execAndCapture('npm list --depth=0', {
43
+ cwd: '/path/to/project'
44
+ })
45
+ ```
46
+
47
+
48
+
49
+ ### spawnAndCapture
50
+
51
+ Spawns a process and captures its output with real-time monitoring capabilities. This method provides comprehensive process execution with the ability to capture output, monitor real-time data streams, and handle process lifecycle events. It's ideal for long-running processes where you need to capture output as it happens.
52
+
53
+ **Parameters:**
54
+
55
+ | Name | Type | Required | Description |
56
+ |------|------|----------|-------------|
57
+ | `command` | `string` | ✓ | The command to execute (e.g., 'node', 'npm', 'git') |
58
+ | `args` | `string[]` | ✓ | Array of arguments to pass to the command |
59
+ | `options` | `SpawnOptions` | | Options for process execution and monitoring |
60
+
61
+ `SpawnOptions` properties:
62
+
63
+ | Property | Type | Description |
64
+ |----------|------|-------------|
65
+ | `stdio` | `"ignore" | "inherit"` | Standard I/O mode for the child process |
66
+ | `stdout` | `"ignore" | "inherit"` | Stdout mode for the child process |
67
+ | `stderr` | `"ignore" | "inherit"` | Stderr mode for the child process |
68
+ | `cwd` | `string` | Working directory for the child process |
69
+ | `environment` | `Record<string, any>` | Environment variables to pass to the child process |
70
+ | `onError` | `(data: string) => void` | Callback invoked when stderr data is received |
71
+ | `onOutput` | `(data: string) => void` | Callback invoked when stdout data is received |
72
+ | `onExit` | `(code: number) => void` | Callback invoked when the process exits |
73
+
74
+ **Returns:** `Promise<{
75
+ stderr: string;
76
+ stdout: string;
77
+ error: null | any;
78
+ exitCode: number;
79
+ pid: number | null;
80
+ }>`
81
+
82
+ ```ts
83
+ // Basic usage
84
+ const result = await proc.spawnAndCapture('node', ['--version'])
85
+ console.log(`Node version: ${result.stdout}`)
86
+
87
+ // With real-time output monitoring
88
+ const result = await proc.spawnAndCapture('npm', ['install'], {
89
+ onOutput: (data) => console.log('📦 ', data.trim()),
90
+ onError: (data) => console.error('❌ ', data.trim()),
91
+ onExit: (code) => console.log(`Process exited with code ${code}`)
92
+ })
93
+
94
+ // Long-running process with custom working directory
95
+ const buildResult = await proc.spawnAndCapture('npm', ['run', 'build'], {
96
+ cwd: '/path/to/project',
97
+ onOutput: (data) => {
98
+ if (data.includes('error')) {
99
+ console.error('Build error detected:', data)
100
+ }
101
+ }
102
+ })
103
+ ```
104
+
105
+
106
+
107
+ ### spawn
108
+
109
+ Spawn a raw child process and return the handle immediately. Useful when callers need streaming access to stdout/stderr and direct lifecycle control (for example, cancellation via kill()).
110
+
111
+ **Parameters:**
112
+
113
+ | Name | Type | Required | Description |
114
+ |------|------|----------|-------------|
115
+ | `command` | `string` | ✓ | Parameter command |
116
+ | `args` | `string[]` | | Parameter args |
117
+ | `options` | `RawSpawnOptions` | | Parameter options |
118
+
119
+ `RawSpawnOptions` properties:
120
+
121
+ | Property | Type | Description |
122
+ |----------|------|-------------|
123
+ | `cwd` | `string` | Working directory for the child process |
124
+ | `environment` | `Record<string, any>` | Environment variables to pass to the child process |
125
+ | `stdin` | `string | Buffer` | Optional stdin payload written immediately after spawn |
126
+ | `stdout` | `"pipe" | "inherit" | "ignore"` | Stdout mode for the child process |
127
+ | `stderr` | `"pipe" | "inherit" | "ignore"` | Stderr mode for the child process |
128
+
129
+ **Returns:** `void`
130
+
131
+
132
+
133
+ ### runScript
134
+
135
+ Runs a script file with Bun, inheriting stdout for full TTY passthrough (animations, colors, cursor movement) while capturing stderr in a rolling buffer.
136
+
137
+ **Parameters:**
138
+
139
+ | Name | Type | Required | Description |
140
+ |------|------|----------|-------------|
141
+ | `scriptPath` | `string` | ✓ | Absolute path to the script file |
142
+ | `options` | `{ cwd?: string; maxLines?: number; env?: Record<string, string> }` | | Options |
143
+
144
+ `{ cwd?: string; maxLines?: number; env?: Record<string, string> }` properties:
145
+
146
+ | Property | Type | Description |
147
+ |----------|------|-------------|
148
+ | `cwd` | `any` | Working directory |
149
+ | `maxLines` | `any` | Max stderr lines to keep |
150
+ | `env` | `any` | Extra environment variables |
151
+
152
+ **Returns:** `Promise<{ exitCode: number; stderr: string[] }>`
153
+
154
+ ```ts
155
+ const { exitCode, stderr } = await proc.runScript('/path/to/script.ts')
156
+ if (exitCode !== 0) {
157
+ console.log('Error:', stderr.join('\n'))
158
+ }
159
+ ```
160
+
161
+
162
+
163
+ ### exec
164
+
165
+ Execute a command synchronously and return its output. Runs a shell command and waits for it to complete before returning. Useful for simple commands where you need the result immediately.
166
+
167
+ **Parameters:**
168
+
169
+ | Name | Type | Required | Description |
170
+ |------|------|----------|-------------|
171
+ | `command` | `string` | ✓ | The command to execute |
172
+ | `options` | `any` | | Options for command execution (cwd, encoding, etc.) |
173
+
174
+ **Returns:** `string`
175
+
176
+ ```ts
177
+ const branch = proc.exec('git branch --show-current')
178
+ const version = proc.exec('node --version')
179
+ ```
180
+
181
+
182
+
183
+ ### establishLock
184
+
185
+ Establishes a PID-file lock to prevent duplicate process instances. Writes the current process PID to the given file path. If the file already exists and the PID inside it refers to a running process, the current process exits immediately. Stale PID files (where the process is no longer running) are automatically cleaned up. Cleanup handlers are registered on SIGTERM, SIGINT, and process exit to remove the PID file when the process shuts down.
186
+
187
+ **Parameters:**
188
+
189
+ | Name | Type | Required | Description |
190
+ |------|------|----------|-------------|
191
+ | `pidPath` | `string` | ✓ | Path to the PID file, resolved relative to container.cwd |
192
+
193
+ **Returns:** `{ release: () => void }`
194
+
195
+ ```ts
196
+ // In a command handler — exits if already running
197
+ const lock = proc.establishLock('tmp/luca-main.pid')
198
+
199
+ // Later, if you need to release manually
200
+ lock.release()
201
+ ```
202
+
203
+
204
+
205
+ ### kill
206
+
207
+ Kills a process by its PID.
208
+
209
+ **Parameters:**
210
+
211
+ | Name | Type | Required | Description |
212
+ |------|------|----------|-------------|
213
+ | `pid` | `number` | ✓ | The process ID to kill |
214
+ | `signal` | `NodeJS.Signals | number` | | The signal to send (e.g. 'SIGTERM', 'SIGKILL', 9) |
215
+
216
+ **Returns:** `boolean`
217
+
218
+ ```ts
219
+ // Gracefully terminate a process
220
+ proc.kill(12345)
221
+
222
+ // Force kill a process
223
+ proc.kill(12345, 'SIGKILL')
224
+ ```
225
+
226
+
227
+
228
+ ### findPidsByPort
229
+
230
+ Finds PIDs of processes listening on a given port. Uses `lsof` on macOS/Linux to discover which processes have a socket bound to the specified port.
231
+
232
+ **Parameters:**
233
+
234
+ | Name | Type | Required | Description |
235
+ |------|------|----------|-------------|
236
+ | `port` | `number` | ✓ | The port number to search for |
237
+
238
+ **Returns:** `number[]`
239
+
240
+ ```ts
241
+ const pids = proc.findPidsByPort(3000)
242
+ console.log(`Processes on port 3000: ${pids}`)
243
+
244
+ // Kill everything on port 3000
245
+ for (const pid of proc.findPidsByPort(3000)) {
246
+ proc.kill(pid)
247
+ }
248
+ ```
249
+
250
+
251
+
252
+ ### onSignal
253
+
254
+ Registers a handler for a process signal (e.g. SIGINT, SIGTERM, SIGUSR1). Returns a cleanup function that removes the listener when called.
255
+
256
+ **Parameters:**
257
+
258
+ | Name | Type | Required | Description |
259
+ |------|------|----------|-------------|
260
+ | `signal` | `NodeJS.Signals` | ✓ | The signal name to listen for (e.g. 'SIGINT', 'SIGTERM', 'SIGUSR2') |
261
+ | `handler` | `() => void` | ✓ | The function to call when the signal is received |
262
+
263
+ **Returns:** `() => void`
264
+
265
+ ```ts
266
+ // Graceful shutdown
267
+ proc.onSignal('SIGTERM', () => {
268
+ console.log('Shutting down gracefully...')
269
+ process.exit(0)
270
+ })
271
+
272
+ // Remove the listener later
273
+ const off = proc.onSignal('SIGUSR2', () => {
274
+ console.log('Received SIGUSR2')
275
+ })
276
+ off()
277
+ ```
278
+
279
+
280
+
281
+ ## State (Zod v4 schema)
282
+
283
+ | Property | Type | Description |
284
+ |----------|------|-------------|
285
+ | `enabled` | `boolean` | Whether this feature is currently enabled |
286
+
287
+ ## Examples
288
+
289
+ **features.proc**
290
+
291
+ ```ts
292
+ const proc = container.feature('proc')
293
+
294
+ // Execute a simple command synchronously
295
+ const result = proc.exec('echo "Hello World"')
296
+ console.log(result) // 'Hello World'
297
+
298
+ // Execute and capture output asynchronously
299
+ const { stdout, stderr } = await proc.spawnAndCapture('npm', ['--version'])
300
+ console.log(`npm version: ${stdout}`)
301
+
302
+ // Execute with callbacks for real-time output
303
+ await proc.spawnAndCapture('npm', ['install'], {
304
+ onOutput: (data) => console.log('OUT:', data),
305
+ onError: (data) => console.log('ERR:', data)
306
+ })
307
+ ```
308
+
309
+
310
+
311
+ **execAndCapture**
312
+
313
+ ```ts
314
+ // Execute a git command
315
+ const result = await proc.execAndCapture('git status --porcelain')
316
+ if (result.exitCode === 0) {
317
+ console.log('Git status:', result.stdout)
318
+ } else {
319
+ console.error('Git error:', result.stderr)
320
+ }
321
+
322
+ // Execute with options
323
+ const result = await proc.execAndCapture('npm list --depth=0', {
324
+ cwd: '/path/to/project'
325
+ })
326
+ ```
327
+
328
+
329
+
330
+ **spawnAndCapture**
331
+
332
+ ```ts
333
+ // Basic usage
334
+ const result = await proc.spawnAndCapture('node', ['--version'])
335
+ console.log(`Node version: ${result.stdout}`)
336
+
337
+ // With real-time output monitoring
338
+ const result = await proc.spawnAndCapture('npm', ['install'], {
339
+ onOutput: (data) => console.log('📦 ', data.trim()),
340
+ onError: (data) => console.error('❌ ', data.trim()),
341
+ onExit: (code) => console.log(`Process exited with code ${code}`)
342
+ })
343
+
344
+ // Long-running process with custom working directory
345
+ const buildResult = await proc.spawnAndCapture('npm', ['run', 'build'], {
346
+ cwd: '/path/to/project',
347
+ onOutput: (data) => {
348
+ if (data.includes('error')) {
349
+ console.error('Build error detected:', data)
350
+ }
351
+ }
352
+ })
353
+ ```
354
+
355
+
356
+
357
+ **runScript**
358
+
359
+ ```ts
360
+ const { exitCode, stderr } = await proc.runScript('/path/to/script.ts')
361
+ if (exitCode !== 0) {
362
+ console.log('Error:', stderr.join('\n'))
363
+ }
364
+ ```
365
+
366
+
367
+
368
+ **exec**
369
+
370
+ ```ts
371
+ const branch = proc.exec('git branch --show-current')
372
+ const version = proc.exec('node --version')
373
+ ```
374
+
375
+
376
+
377
+ **establishLock**
378
+
379
+ ```ts
380
+ // In a command handler — exits if already running
381
+ const lock = proc.establishLock('tmp/luca-main.pid')
382
+
383
+ // Later, if you need to release manually
384
+ lock.release()
385
+ ```
386
+
387
+
388
+
389
+ **kill**
390
+
391
+ ```ts
392
+ // Gracefully terminate a process
393
+ proc.kill(12345)
394
+
395
+ // Force kill a process
396
+ proc.kill(12345, 'SIGKILL')
397
+ ```
398
+
399
+
400
+
401
+ **findPidsByPort**
402
+
403
+ ```ts
404
+ const pids = proc.findPidsByPort(3000)
405
+ console.log(`Processes on port 3000: ${pids}`)
406
+
407
+ // Kill everything on port 3000
408
+ for (const pid of proc.findPidsByPort(3000)) {
409
+ proc.kill(pid)
410
+ }
411
+ ```
412
+
413
+
414
+
415
+ **onSignal**
416
+
417
+ ```ts
418
+ // Graceful shutdown
419
+ proc.onSignal('SIGTERM', () => {
420
+ console.log('Shutting down gracefully...')
421
+ process.exit(0)
422
+ })
423
+
424
+ // Remove the listener later
425
+ const off = proc.onSignal('SIGUSR2', () => {
426
+ console.log('Received SIGUSR2')
427
+ })
428
+ off()
429
+ ```
430
+