@soederpop/luca 0.0.6 → 0.0.8

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 (208) hide show
  1. package/CLAUDE.md +10 -1
  2. package/RUNME.md +56 -0
  3. package/bun.lock +1 -1
  4. package/commands/build-bootstrap.ts +78 -0
  5. package/commands/build-scaffolds.ts +24 -2
  6. package/commands/try-all-challenges.ts +543 -0
  7. package/commands/try-challenge.ts +100 -0
  8. package/docs/README.md +52 -80
  9. package/docs/TABLE-OF-CONTENTS.md +82 -51
  10. package/docs/apis/clients/elevenlabs.md +232 -8
  11. package/docs/apis/clients/graph.md +59 -8
  12. package/docs/apis/clients/openai.md +362 -2
  13. package/docs/apis/clients/rest.md +122 -2
  14. package/docs/apis/clients/websocket.md +71 -17
  15. package/docs/apis/features/agi/assistant.md +9 -3
  16. package/docs/apis/features/agi/assistants-manager.md +2 -2
  17. package/docs/apis/features/agi/claude-code.md +153 -14
  18. package/docs/apis/features/agi/conversation-history.md +15 -3
  19. package/docs/apis/features/agi/conversation.md +133 -20
  20. package/docs/apis/features/agi/openai-codex.md +90 -12
  21. package/docs/apis/features/agi/skills-library.md +23 -5
  22. package/docs/apis/features/node/container-link.md +59 -0
  23. package/docs/apis/features/node/content-db.md +1 -1
  24. package/docs/apis/features/node/disk-cache.md +1 -1
  25. package/docs/apis/features/node/dns.md +1 -0
  26. package/docs/apis/features/node/docker.md +2 -1
  27. package/docs/apis/features/node/esbuild.md +4 -3
  28. package/docs/apis/features/node/file-manager.md +13 -4
  29. package/docs/apis/features/node/fs.md +726 -171
  30. package/docs/apis/features/node/git.md +1 -0
  31. package/docs/apis/features/node/google-auth.md +23 -4
  32. package/docs/apis/features/node/google-calendar.md +14 -2
  33. package/docs/apis/features/node/google-docs.md +15 -2
  34. package/docs/apis/features/node/google-drive.md +21 -3
  35. package/docs/apis/features/node/google-sheets.md +14 -2
  36. package/docs/apis/features/node/grep.md +2 -0
  37. package/docs/apis/features/node/helpers.md +29 -0
  38. package/docs/apis/features/node/ink.md +2 -2
  39. package/docs/apis/features/node/networking.md +39 -4
  40. package/docs/apis/features/node/os.md +28 -0
  41. package/docs/apis/features/node/postgres.md +26 -4
  42. package/docs/apis/features/node/proc.md +37 -28
  43. package/docs/apis/features/node/process-manager.md +33 -5
  44. package/docs/apis/features/node/repl.md +1 -1
  45. package/docs/apis/features/node/runpod.md +1 -0
  46. package/docs/apis/features/node/secure-shell.md +7 -0
  47. package/docs/apis/features/node/semantic-search.md +12 -5
  48. package/docs/apis/features/node/sqlite.md +26 -4
  49. package/docs/apis/features/node/telegram.md +30 -5
  50. package/docs/apis/features/node/tts.md +17 -2
  51. package/docs/apis/features/node/ui.md +1 -1
  52. package/docs/apis/features/node/vault.md +4 -9
  53. package/docs/apis/features/node/vm.md +3 -12
  54. package/docs/apis/features/node/window-manager.md +128 -20
  55. package/docs/apis/features/web/asset-loader.md +13 -1
  56. package/docs/apis/features/web/container-link.md +59 -0
  57. package/docs/apis/features/web/esbuild.md +4 -3
  58. package/docs/apis/features/web/helpers.md +29 -0
  59. package/docs/apis/features/web/network.md +16 -2
  60. package/docs/apis/features/web/speech.md +16 -2
  61. package/docs/apis/features/web/vault.md +4 -9
  62. package/docs/apis/features/web/vm.md +3 -12
  63. package/docs/apis/features/web/voice.md +18 -1
  64. package/docs/apis/servers/express.md +18 -2
  65. package/docs/apis/servers/mcp.md +29 -4
  66. package/docs/apis/servers/websocket.md +34 -6
  67. package/docs/bootstrap/CLAUDE.md +100 -0
  68. package/docs/bootstrap/SKILL.md +222 -0
  69. package/docs/bootstrap/templates/about-command.ts +41 -0
  70. package/docs/bootstrap/templates/docs-models.ts +22 -0
  71. package/docs/bootstrap/templates/docs-readme.md +43 -0
  72. package/docs/bootstrap/templates/example-feature.ts +53 -0
  73. package/docs/bootstrap/templates/health-endpoint.ts +15 -0
  74. package/docs/bootstrap/templates/luca-cli.ts +25 -0
  75. package/docs/bootstrap/templates/runme.md +54 -0
  76. package/docs/challenges/caching-proxy.md +16 -0
  77. package/docs/challenges/content-db-round-trip.md +14 -0
  78. package/docs/challenges/custom-command.md +9 -0
  79. package/docs/challenges/file-watcher-pipeline.md +11 -0
  80. package/docs/challenges/grep-audit-report.md +15 -0
  81. package/docs/challenges/multi-feature-dashboard.md +14 -0
  82. package/docs/challenges/process-orchestrator.md +17 -0
  83. package/docs/challenges/rest-api-server-with-client.md +12 -0
  84. package/docs/challenges/script-runner-with-vm.md +11 -0
  85. package/docs/challenges/simple-rest-api.md +15 -0
  86. package/docs/challenges/websocket-serve-and-client.md +11 -0
  87. package/docs/challenges/yaml-config-system.md +14 -0
  88. package/docs/command-system-overhaul.md +94 -0
  89. package/docs/examples/assistant/CORE.md +18 -0
  90. package/docs/examples/assistant/hooks.ts +3 -0
  91. package/docs/examples/assistant/tools.ts +10 -0
  92. package/docs/examples/window-manager-layouts.md +180 -0
  93. package/docs/in-memory-fs.md +4 -0
  94. package/docs/models.ts +13 -10
  95. package/docs/philosophy.md +4 -3
  96. package/docs/reports/console-hmr-design.md +170 -0
  97. package/docs/reports/helper-semantic-search.md +72 -0
  98. package/docs/scaffolds/client.md +29 -20
  99. package/docs/scaffolds/command.md +64 -50
  100. package/docs/scaffolds/endpoint.md +31 -36
  101. package/docs/scaffolds/feature.md +28 -18
  102. package/docs/scaffolds/selector.md +91 -0
  103. package/docs/scaffolds/server.md +18 -9
  104. package/docs/selectors.md +115 -0
  105. package/docs/sessions/custom-command/attempt-log-2.md +195 -0
  106. package/docs/sessions/file-watcher-pipeline/attempt-log-1.md +728 -0
  107. package/docs/sessions/file-watcher-pipeline/attempt-log-2.md +555 -0
  108. package/docs/sessions/grep-audit-report/attempt-log-1.md +289 -0
  109. package/docs/sessions/multi-feature-dashboard/attempt-log-2.md +679 -0
  110. package/docs/sessions/rest-api-server-with-client/attempt-log-1.md +1 -0
  111. package/docs/sessions/rest-api-server-with-client/attempt-log-3.md +920 -0
  112. package/docs/sessions/simple-rest-api/attempt-log-1.md +593 -0
  113. package/docs/sessions/websocket-serve-and-client/attempt-log-2.md +995 -0
  114. package/docs/tutorials/00-bootstrap.md +148 -0
  115. package/docs/tutorials/07-endpoints.md +7 -7
  116. package/docs/tutorials/08-commands.md +153 -72
  117. package/luca.cli.ts +3 -0
  118. package/package.json +6 -5
  119. package/public/index.html +1430 -0
  120. package/scripts/examples/using-ollama.ts +2 -1
  121. package/scripts/update-introspection-data.ts +2 -2
  122. package/src/agi/endpoints/experts.ts +1 -1
  123. package/src/agi/features/assistant.ts +7 -0
  124. package/src/agi/features/assistants-manager.ts +5 -5
  125. package/src/agi/features/claude-code.ts +263 -3
  126. package/src/agi/features/conversation-history.ts +7 -1
  127. package/src/agi/features/conversation.ts +26 -3
  128. package/src/agi/features/openai-codex.ts +26 -2
  129. package/src/agi/features/openapi.ts +6 -1
  130. package/src/agi/features/skills-library.ts +9 -1
  131. package/src/bootstrap/generated.ts +595 -0
  132. package/src/cli/cli.ts +64 -21
  133. package/src/client.ts +23 -357
  134. package/src/clients/civitai/index.ts +1 -1
  135. package/src/clients/client-template.ts +1 -1
  136. package/src/clients/comfyui/index.ts +13 -2
  137. package/src/clients/elevenlabs/index.ts +2 -1
  138. package/src/clients/graph.ts +87 -0
  139. package/src/clients/openai/index.ts +10 -1
  140. package/src/clients/rest.ts +207 -0
  141. package/src/clients/websocket.ts +176 -0
  142. package/src/command.ts +281 -34
  143. package/src/commands/bootstrap.ts +185 -0
  144. package/src/commands/chat.ts +5 -4
  145. package/src/commands/describe.ts +341 -4
  146. package/src/commands/help.ts +35 -9
  147. package/src/commands/index.ts +3 -0
  148. package/src/commands/introspect.ts +92 -2
  149. package/src/commands/prompt.ts +5 -6
  150. package/src/commands/run.ts +75 -10
  151. package/src/commands/save-api-docs.ts +49 -0
  152. package/src/commands/scaffold.ts +169 -23
  153. package/src/commands/select.ts +94 -0
  154. package/src/commands/serve.ts +10 -1
  155. package/src/container.ts +15 -0
  156. package/src/endpoint.ts +19 -0
  157. package/src/graft.ts +181 -0
  158. package/src/introspection/generated.agi.ts +12458 -8968
  159. package/src/introspection/generated.node.ts +10573 -7145
  160. package/src/introspection/generated.web.ts +1 -1
  161. package/src/introspection/index.ts +26 -0
  162. package/src/node/container.ts +6 -7
  163. package/src/node/features/content-db.ts +49 -2
  164. package/src/node/features/disk-cache.ts +16 -9
  165. package/src/node/features/dns.ts +16 -3
  166. package/src/node/features/docker.ts +16 -4
  167. package/src/node/features/esbuild.ts +22 -2
  168. package/src/node/features/file-manager.ts +184 -29
  169. package/src/node/features/fs.ts +704 -248
  170. package/src/node/features/git.ts +21 -8
  171. package/src/node/features/grep.ts +23 -3
  172. package/src/node/features/helpers.ts +372 -43
  173. package/src/node/features/networking.ts +39 -4
  174. package/src/node/features/opener.ts +28 -15
  175. package/src/node/features/os.ts +76 -0
  176. package/src/node/features/port-exposer.ts +11 -1
  177. package/src/node/features/postgres.ts +17 -1
  178. package/src/node/features/proc.ts +4 -1
  179. package/src/node/features/python.ts +63 -14
  180. package/src/node/features/repl.ts +11 -7
  181. package/src/node/features/runpod.ts +16 -3
  182. package/src/node/features/secure-shell.ts +27 -2
  183. package/src/node/features/semantic-search.ts +12 -1
  184. package/src/node/features/ui.ts +5 -69
  185. package/src/node/features/vm.ts +17 -0
  186. package/src/node/features/window-manager.ts +68 -20
  187. package/src/node.ts +5 -0
  188. package/src/scaffolds/generated.ts +492 -290
  189. package/src/scaffolds/template.ts +9 -0
  190. package/src/schemas/base.ts +46 -5
  191. package/src/selector.ts +282 -0
  192. package/src/server.ts +11 -0
  193. package/src/servers/express.ts +27 -12
  194. package/src/servers/socket.ts +45 -11
  195. package/src/web/clients/socket.ts +4 -1
  196. package/src/web/container.ts +2 -1
  197. package/src/web/features/network.ts +7 -1
  198. package/src/web/features/voice-recognition.ts +16 -1
  199. package/test/clients-servers.test.ts +2 -1
  200. package/test/command.test.ts +267 -0
  201. package/test/vm-context.test.ts +146 -0
  202. package/test-integration/assistants-manager.test.ts +10 -20
  203. package/docs/apis/features/node/launcher-app-command-listener.md +0 -145
  204. package/docs/examples/launcher-app-command-listener.md +0 -120
  205. package/docs/tasks/web-container-helper-discovery.md +0 -71
  206. package/docs/todos.md +0 -1
  207. package/scripts/test-command-listener.ts +0 -123
  208. package/src/node/features/launcher-app-command-listener.ts +0 -389
package/CLAUDE.md CHANGED
@@ -56,7 +56,8 @@ When creating a new feature (e.g. `gws`), all four of these steps must be comple
56
56
 
57
57
  1. **Feature file** — `src/node/features/gws.ts`
58
58
  - Export the class: `export class Gws extends Feature { ... }`
59
- - Register at bottom: `export default features.register('gws', Gws)`
59
+ - Register inside the class: `static { Feature.register(this, 'gws') }`
60
+ - Default export is just the class: `export default Gws`
60
61
 
61
62
  2. **Side-effect import** — `src/node/container.ts` (import block ~line 20-63)
62
63
  - Add `import "./features/gws";` (this triggers registration)
@@ -79,6 +80,14 @@ If the feature has a test, it goes in `test/gws.test.ts`.
79
80
  - For more descriptive things like class descriptions, method descriptions, we rely on jsdoc blocks. These are parsed and used to generate modules we commit to source. We shouldn't let these drift, so for this reason we have a pre-commit hook which ensures they're up to date
80
81
  - We rely on module augmentation a lot to make sure `container.feature()` can provide type signatures for everything that gets added to it by extension modules down the road. ( kind of like we did with AGIContainer extending NodeContainer )
81
82
 
83
+ ## Generated Files — Build Artifacts
84
+
85
+ **Files matching `generated.ts` or `.generated*.ts` are BUILD ARTIFACTS, not source of truth.** They are produced by the introspection system (which parses JSDoc blocks, Zod schemas, etc.) and bundled into the binary at compile time. **Never edit these files directly** — your changes will be overwritten on the next build.
86
+
87
+ The source of truth for scaffolds and templates is the markdown files and the actual source code with their JSDoc annotations. If scaffold output is wrong, fix the markdown source or the JSDoc blocks on the real classes, then rebuild.
88
+
89
+ This means **JSDoc blocks on helpers (features, clients, servers) must be valid and complete** — they are picked up by the introspection system, used to generate API docs, scaffold tutorials, and the `luca describe` output. Treat JSDoc as documentation infrastructure, not comments.
90
+
82
91
  ## Testing
83
92
 
84
93
  - Test runner is **bun** (not vitest). Do not import from or add vitest.
package/RUNME.md ADDED
@@ -0,0 +1,56 @@
1
+ # Runnable Markdown
2
+
3
+ The `luca` CLI allows you to run markdown blocks as long as they're tagged with `ts` in the language.
4
+
5
+ ```ts
6
+ const banner = ui.banner('LUCA', {
7
+ font: 'Puffy',
8
+ colors: ['red','white','blue']
9
+ })
10
+
11
+ ui.print(banner)
12
+ ```
13
+
14
+ What is kind of cool is ( so long as there's no top-level-await in the block ) the context will preserve:
15
+
16
+ ```ts
17
+ if(typeof banner === 'undefined') {
18
+ ui.print.red('uh oh, something broke.')
19
+ }
20
+ ```
21
+
22
+ You can skip blocks too with the skip tag in the language of the fenced block
23
+
24
+ ```ts skip
25
+ console.log('Not gonna say anything')
26
+ ```
27
+
28
+ Did you hear something? No.
29
+
30
+ Something even cooler is the ability to render React blocks. This makes luca kind of like a poor man's MDX. I just define some Blocks in the markdown by creating an h2 `## Blocks` section with a fenced codeblock that uses `tsx`. The `ink.components` and `ink.React` globals are injected into the scope.
31
+
32
+ ## Blocks
33
+
34
+ ```tsx
35
+ const { Box, Text } = ink.components
36
+ const React = ink.React
37
+
38
+ function Greeting({ name, role }) {
39
+ return (
40
+ <Box borderStyle="round" padding={1}>
41
+ <Text color="green" bold>Hello {name}!</Text>
42
+ <Text dimColor> ({role})</Text>
43
+ </Box>
44
+ )
45
+ }
46
+ ```
47
+
48
+ ## Rendering React Blocks
49
+
50
+ Then I can use the Blocks in code.
51
+
52
+ ```ts
53
+ await render('Greeting', { name: 'Jon', role: 'Humble Servant' })
54
+ ```
55
+
56
+
package/bun.lock CHANGED
@@ -18,7 +18,7 @@
18
18
  "chokidar": "^3.5.3",
19
19
  "cli-markdown": "^3.5.0",
20
20
  "compromise": "^14.14.5",
21
- "contentbase": "",
21
+ "contentbase": "^0.0.5",
22
22
  "cors": "^2.8.5",
23
23
  "detect-port": "^1.5.1",
24
24
  "dotenv": "^17.2.4",
@@ -0,0 +1,78 @@
1
+ import { z } from 'zod'
2
+ import type { ContainerContext } from '@soederpop/luca'
3
+ import { CommandOptionsSchema } from '@soederpop/luca/schemas'
4
+
5
+ export const argsSchema = CommandOptionsSchema.extend({})
6
+
7
+ async function buildBootstrap(options: z.infer<typeof argsSchema>, context: ContainerContext) {
8
+ const container = context.container as any
9
+ const fs = container.feature('fs')
10
+
11
+ const sourceDir = 'docs/bootstrap'
12
+ const outputPath = 'src/bootstrap/generated.ts'
13
+
14
+ if (!fs.exists(sourceDir)) {
15
+ console.log(`Source directory ${sourceDir} not found`)
16
+ return
17
+ }
18
+
19
+ // 1. Collect top-level markdown files (SKILL.md, CLAUDE.md, etc.)
20
+ const allFiles = await fs.readdir(sourceDir)
21
+ const mdFiles = allFiles.filter((f: string) => f.endsWith('.md'))
22
+ const entries: Record<string, string> = {}
23
+
24
+ for (const file of mdFiles) {
25
+ const content = await fs.readFileAsync(`${sourceDir}/${file}`)
26
+ const name = file.replace(/\.md$/, '')
27
+ entries[name] = content
28
+ console.log(` ${name}: ${content.length} chars`)
29
+ }
30
+
31
+ // 2. Collect template files (docs/bootstrap/templates/*)
32
+ const templates: Record<string, string> = {}
33
+ const templatesDir = `${sourceDir}/templates`
34
+ if (fs.exists(templatesDir)) {
35
+ const templateFiles = await fs.readdir(templatesDir)
36
+ for (const file of templateFiles) {
37
+ const content = await fs.readFileAsync(`${templatesDir}/${file}`)
38
+ const name = file.replace(/\.[^.]+$/, '') // strip any extension
39
+ templates[name] = content
40
+ console.log(` template/${name}: ${content.length} chars`)
41
+ }
42
+ }
43
+
44
+ const escapeForTemplate = (s: string) => s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${')
45
+
46
+ const fileEntries = Object.entries(entries).map(([name, content]) =>
47
+ ` ${JSON.stringify(name)}: \`${escapeForTemplate(content)}\``
48
+ ).join(',\n')
49
+
50
+ const templateEntries = Object.entries(templates).map(([name, content]) =>
51
+ ` ${JSON.stringify(name)}: \`${escapeForTemplate(content)}\``
52
+ ).join(',\n')
53
+
54
+ const output = `// Auto-generated bootstrap content
55
+ // Generated at: ${new Date().toISOString()}
56
+ // Source: docs/bootstrap/*.md, docs/bootstrap/templates/*
57
+ //
58
+ // Do not edit manually. Run: luca build-bootstrap
59
+
60
+ export const bootstrapFiles: Record<string, string> = {
61
+ ${fileEntries}
62
+ }
63
+
64
+ export const bootstrapTemplates: Record<string, string> = {
65
+ ${templateEntries}
66
+ }
67
+ `
68
+
69
+ fs.ensureFolder('src/bootstrap')
70
+ await fs.writeFileAsync(outputPath, output)
71
+ console.log(`\nGenerated ${outputPath}`)
72
+ }
73
+
74
+ export default {
75
+ description: 'Bundle docs/bootstrap/*.md into src/bootstrap/generated.ts for the compiled binary',
76
+ argsSchema,
77
+ handler: buildBootstrap,
78
+ }
@@ -77,7 +77,7 @@ async function buildScaffolds(options: z.infer<typeof argsSchema>, context: Cont
77
77
  const readmePath = 'docs/mcp/readme.md'
78
78
  const outputPath = 'src/scaffolds/generated.ts'
79
79
 
80
- const types = ['feature', 'client', 'server', 'command', 'endpoint']
80
+ const types = ['feature', 'client', 'server', 'command', 'endpoint', 'selector']
81
81
  const scaffolds: Record<string, ScaffoldData> = {}
82
82
 
83
83
  for (const type of types) {
@@ -92,6 +92,20 @@ async function buildScaffolds(options: z.infer<typeof argsSchema>, context: Cont
92
92
  console.log(` 📄 ${type}: ${scaffolds[type].sections.length} sections, full template: ${scaffolds[type].full ? 'yes' : 'no'}`)
93
93
  }
94
94
 
95
+ // Bundle the assistant example as a multi-file scaffold
96
+ const assistantDir = 'docs/examples/assistant'
97
+ const assistantFiles: Record<string, string> = {}
98
+ const assistantFileNames = ['CORE.md', 'tools.ts', 'hooks.ts']
99
+ for (const fileName of assistantFileNames) {
100
+ const filePath = `${assistantDir}/${fileName}`
101
+ if (fs.exists(filePath)) {
102
+ assistantFiles[fileName] = fs.readFile(filePath)
103
+ }
104
+ }
105
+ if (Object.keys(assistantFiles).length > 0) {
106
+ console.log(` 📄 assistant: ${Object.keys(assistantFiles).length} files (${Object.keys(assistantFiles).join(', ')})`)
107
+ }
108
+
95
109
  // Read the MCP readme
96
110
  let mcpReadme = ''
97
111
  if (fs.exists(readmePath)) {
@@ -118,9 +132,13 @@ ${sectionsStr}
118
132
  }`
119
133
  }).join(',\n')
120
134
 
135
+ const assistantFilesEntries = Object.entries(assistantFiles).map(([name, content]) =>
136
+ ` ${JSON.stringify(name)}: \`${escapeForTemplate(content)}\``
137
+ ).join(',\n')
138
+
121
139
  const output = `// Auto-generated scaffold and MCP readme content
122
140
  // Generated at: ${new Date().toISOString()}
123
- // Source: docs/scaffolds/*.md and docs/mcp/readme.md
141
+ // Source: docs/scaffolds/*.md, docs/examples/assistant/, and docs/mcp/readme.md
124
142
  //
125
143
  // Do not edit manually. Run: luca build-scaffolds
126
144
 
@@ -139,6 +157,10 @@ export const scaffolds: Record<string, ScaffoldData> = {
139
157
  ${scaffoldEntries}
140
158
  }
141
159
 
160
+ export const assistantFiles: Record<string, string> = {
161
+ ${assistantFilesEntries}
162
+ }
163
+
142
164
  export const mcpReadme = \`${escapeForTemplate(mcpReadme)}\`
143
165
  `
144
166