@soederpop/luca 0.0.32 → 0.0.35
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.
- package/README.md +241 -36
- package/bun.lock +24 -6
- package/commands/build-python-bridge.ts +43 -0
- package/docs/README.md +1 -1
- package/docs/TABLE-OF-CONTENTS.md +0 -1
- package/docs/apis/clients/rest.md +7 -7
- package/docs/apis/clients/websocket.md +23 -10
- package/docs/apis/features/agi/assistant.md +155 -8
- package/docs/apis/features/agi/assistants-manager.md +90 -22
- package/docs/apis/features/agi/auto-assistant.md +377 -0
- package/docs/apis/features/agi/browser-use.md +802 -0
- package/docs/apis/features/agi/claude-code.md +6 -1
- package/docs/apis/features/agi/conversation-history.md +7 -6
- package/docs/apis/features/agi/conversation.md +111 -38
- package/docs/apis/features/agi/docs-reader.md +35 -57
- package/docs/apis/features/agi/file-tools.md +163 -0
- package/docs/apis/features/agi/openapi.md +2 -2
- package/docs/apis/features/agi/skills-library.md +227 -0
- package/docs/apis/features/node/content-db.md +125 -4
- package/docs/apis/features/node/disk-cache.md +11 -11
- package/docs/apis/features/node/downloader.md +1 -1
- package/docs/apis/features/node/file-manager.md +15 -15
- package/docs/apis/features/node/fs.md +78 -21
- package/docs/apis/features/node/git.md +50 -10
- package/docs/apis/features/node/google-calendar.md +3 -0
- package/docs/apis/features/node/google-docs.md +10 -1
- package/docs/apis/features/node/google-drive.md +3 -0
- package/docs/apis/features/node/google-mail.md +214 -0
- package/docs/apis/features/node/google-sheets.md +3 -0
- package/docs/apis/features/node/ink.md +10 -10
- package/docs/apis/features/node/ipc-socket.md +83 -93
- package/docs/apis/features/node/networking.md +5 -5
- package/docs/apis/features/node/os.md +7 -7
- package/docs/apis/features/node/package-finder.md +14 -14
- package/docs/apis/features/node/proc.md +2 -1
- package/docs/apis/features/node/process-manager.md +70 -3
- package/docs/apis/features/node/python.md +265 -9
- package/docs/apis/features/node/redis.md +380 -0
- package/docs/apis/features/node/ui.md +13 -13
- package/docs/apis/servers/express.md +35 -7
- package/docs/apis/servers/mcp.md +3 -3
- package/docs/apis/servers/websocket.md +51 -8
- package/docs/bootstrap/CLAUDE.md +1 -1
- package/docs/bootstrap/SKILL.md +93 -7
- package/docs/examples/feature-as-tool-provider.md +143 -0
- package/docs/examples/python.md +42 -1
- package/docs/introspection.md +15 -5
- package/docs/tutorials/00-bootstrap.md +3 -3
- package/docs/tutorials/02-container.md +2 -2
- package/docs/tutorials/10-creating-features.md +5 -0
- package/docs/tutorials/13-introspection.md +12 -2
- package/docs/tutorials/19-python-sessions.md +401 -0
- package/package.json +8 -5
- package/scripts/examples/using-assistant-with-mcp.ts +2 -7
- package/scripts/test-linux-binary.sh +80 -0
- package/src/agi/container.server.ts +8 -0
- package/src/agi/features/assistant.ts +18 -0
- package/src/agi/features/autonomous-assistant.ts +435 -0
- package/src/agi/features/conversation.ts +58 -6
- package/src/agi/features/file-tools.ts +286 -0
- package/src/agi/features/luca-coder.ts +643 -0
- package/src/bootstrap/generated.ts +705 -107
- package/src/cli/build-info.ts +2 -2
- package/src/cli/cli.ts +22 -13
- package/src/commands/bootstrap.ts +49 -6
- package/src/commands/code.ts +369 -0
- package/src/commands/describe.ts +7 -2
- package/src/commands/index.ts +1 -0
- package/src/commands/sandbox-mcp.ts +7 -7
- package/src/commands/save-api-docs.ts +1 -1
- package/src/container-describer.ts +4 -4
- package/src/container.ts +10 -19
- package/src/helper.ts +24 -33
- package/src/introspection/generated.agi.ts +3026 -849
- package/src/introspection/generated.node.ts +1690 -1012
- package/src/introspection/generated.web.ts +15 -57
- package/src/node/container.ts +5 -5
- package/src/node/features/figlet-fonts.ts +597 -0
- package/src/node/features/fs.ts +3 -9
- package/src/node/features/helpers.ts +20 -0
- package/src/node/features/python.ts +429 -16
- package/src/node/features/redis.ts +446 -0
- package/src/node/features/ui.ts +4 -11
- package/src/python/bridge.py +220 -0
- package/src/python/generated.ts +227 -0
- package/src/scaffolds/generated.ts +1 -1
- package/test/python-session.test.ts +105 -0
- package/assistants/lucaExpert/CORE.md +0 -37
- package/assistants/lucaExpert/hooks.ts +0 -9
- package/assistants/lucaExpert/tools.ts +0 -177
- package/docs/examples/port-exposer.md +0 -89
- package/src/node/features/port-exposer.ts +0 -351
|
@@ -20,7 +20,7 @@ Parse markdown text and render it for terminal display using marked-terminal.
|
|
|
20
20
|
|------|------|----------|-------------|
|
|
21
21
|
| `text` | `string` | ✓ | The markdown string to parse and render |
|
|
22
22
|
|
|
23
|
-
**Returns:** `
|
|
23
|
+
**Returns:** `string | Promise<string>`
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
@@ -64,7 +64,7 @@ Creates an interactive wizard using inquirer prompts. This method provides a con
|
|
|
64
64
|
| `questions` | `any[]` | ✓ | Array of inquirer question objects |
|
|
65
65
|
| `initialAnswers` | `any` | | Pre-populated answers to skip questions or provide defaults |
|
|
66
66
|
|
|
67
|
-
**Returns:** `
|
|
67
|
+
**Returns:** `Promise<any>`
|
|
68
68
|
|
|
69
69
|
```ts
|
|
70
70
|
// Basic wizard
|
|
@@ -109,7 +109,7 @@ Prompt the user with a single text input question.
|
|
|
109
109
|
|------|------|----------|-------------|
|
|
110
110
|
| `question` | `string` | ✓ | The question message to display |
|
|
111
111
|
|
|
112
|
-
**Returns:** `
|
|
112
|
+
**Returns:** `Promise<any>`
|
|
113
113
|
|
|
114
114
|
|
|
115
115
|
|
|
@@ -124,7 +124,7 @@ Opens text in the user's external editor for editing. This method integrates wit
|
|
|
124
124
|
| `text` | `string` | ✓ | The initial text content to edit |
|
|
125
125
|
| `extension` | `any` | | File extension for syntax highlighting (default: ".ts") |
|
|
126
126
|
|
|
127
|
-
**Returns:** `
|
|
127
|
+
**Returns:** `Promise<unknown>`
|
|
128
128
|
|
|
129
129
|
```ts
|
|
130
130
|
// Edit code snippet
|
|
@@ -153,7 +153,7 @@ Generates ASCII art from text using the specified font. This method converts reg
|
|
|
153
153
|
| `text` | `string` | ✓ | The text to convert to ASCII art |
|
|
154
154
|
| `font` | `Fonts` | ✓ | The figlet font to use (see fonts property for available options) |
|
|
155
155
|
|
|
156
|
-
**Returns:** `
|
|
156
|
+
**Returns:** `string`
|
|
157
157
|
|
|
158
158
|
```ts
|
|
159
159
|
// Create a banner
|
|
@@ -191,7 +191,7 @@ Creates a styled banner with ASCII art and color gradients. This method combines
|
|
|
191
191
|
| `font` | `any` | The figlet font to use for ASCII art generation |
|
|
192
192
|
| `colors` | `any` | Array of colors for the gradient effect |
|
|
193
193
|
|
|
194
|
-
**Returns:** `
|
|
194
|
+
**Returns:** `string`
|
|
195
195
|
|
|
196
196
|
```ts
|
|
197
197
|
// Classic patriotic banner
|
|
@@ -229,7 +229,7 @@ Dedent and format a tagged template literal using endent. Strips leading indenta
|
|
|
229
229
|
|------|------|----------|-------------|
|
|
230
230
|
| `args` | `any[]` | ✓ | Tagged template literal arguments |
|
|
231
231
|
|
|
232
|
-
**Returns:** `
|
|
232
|
+
**Returns:** `string`
|
|
233
233
|
|
|
234
234
|
|
|
235
235
|
|
|
@@ -245,7 +245,7 @@ Applies color gradients to text with configurable direction. This method creates
|
|
|
245
245
|
| `lineColors` | `Color[]` | | Array of colors to cycle through in the gradient |
|
|
246
246
|
| `direction` | `"horizontal" | "vertical"` | | Gradient direction: 'horizontal' or 'vertical' |
|
|
247
247
|
|
|
248
|
-
**Returns:** `
|
|
248
|
+
**Returns:** `string`
|
|
249
249
|
|
|
250
250
|
```ts
|
|
251
251
|
// Horizontal rainbow effect
|
|
@@ -281,7 +281,7 @@ Applies horizontal color gradients character by character. This method creates c
|
|
|
281
281
|
| `text` | `string` | ✓ | The text to apply horizontal gradients to |
|
|
282
282
|
| `lineColors` | `Color[]` | | Array of colors to cycle through |
|
|
283
283
|
|
|
284
|
-
**Returns:** `
|
|
284
|
+
**Returns:** `string`
|
|
285
285
|
|
|
286
286
|
```ts
|
|
287
287
|
// Rainbow effect across characters
|
|
@@ -310,7 +310,7 @@ Applies vertical color gradients line by line. This method creates color transit
|
|
|
310
310
|
| `text` | `string` | ✓ | The text to apply vertical gradients to (supports newlines) |
|
|
311
311
|
| `lineColors` | `Color[]` | | Array of colors to cycle through for each line |
|
|
312
312
|
|
|
313
|
-
**Returns:** `
|
|
313
|
+
**Returns:** `string`
|
|
314
314
|
|
|
315
315
|
```ts
|
|
316
316
|
// Patriotic vertical gradient
|
|
@@ -342,7 +342,7 @@ Pads text on the left to reach the specified length. This utility method adds pa
|
|
|
342
342
|
| `length` | `number` | ✓ | The desired total length after padding |
|
|
343
343
|
| `padChar` | `any` | | The character to use for padding (default: " ") |
|
|
344
344
|
|
|
345
|
-
**Returns:** `
|
|
345
|
+
**Returns:** `string`
|
|
346
346
|
|
|
347
347
|
```ts
|
|
348
348
|
// Number alignment
|
|
@@ -375,7 +375,7 @@ Pads text on the right to reach the specified length. This utility method adds p
|
|
|
375
375
|
| `length` | `number` | ✓ | The desired total length after padding |
|
|
376
376
|
| `padChar` | `any` | | The character to use for padding (default: " ") |
|
|
377
377
|
|
|
378
|
-
**Returns:** `
|
|
378
|
+
**Returns:** `string`
|
|
379
379
|
|
|
380
380
|
```ts
|
|
381
381
|
// Create aligned table columns
|
|
@@ -409,7 +409,7 @@ const menuItem = ui.padRight('Coffee', 20, '.') + '$3.50';
|
|
|
409
409
|
|----------|------|-------------|
|
|
410
410
|
| `colors` | `typeof colors` | Provides access to the full chalk colors API. Chalk provides extensive color and styling capabilities including: - Basic colors: red, green, blue, yellow, etc. - Background colors: bgRed, bgGreen, etc. - Styles: bold, italic, underline, strikethrough - Advanced: rgb, hex, hsl color support Colors and styles can be chained for complex formatting. |
|
|
411
411
|
| `colorPalette` | `string[]` | Gets the current color palette used for automatic color assignment. The color palette is a predefined set of hex colors that are automatically assigned to named entities in a cycling fashion. This ensures consistent color assignment across the application. |
|
|
412
|
-
| `randomColor` | `
|
|
412
|
+
| `randomColor` | `string | undefined` | Gets a random color name from the available chalk colors. This provides access to a randomly selected color from chalk's built-in color set. Useful for adding variety to terminal output or testing. |
|
|
413
413
|
| `fonts` | `string[]` | Gets an array of available fonts for ASCII art generation. This method provides access to all fonts available through figlet for creating ASCII art. The fonts are automatically discovered and cached on first access for performance. **Font Discovery:** - Fonts are loaded from figlet's built-in font collection - Results are cached in state to avoid repeated file system access - Returns comprehensive list of available font names |
|
|
414
414
|
|
|
415
415
|
## State (Zod v4 schema)
|
|
@@ -39,25 +39,27 @@ container.server('express', {
|
|
|
39
39
|
|
|
40
40
|
### start
|
|
41
41
|
|
|
42
|
+
Start the Express HTTP server. A runtime `port` overrides the constructor option and is written to state so `server.port` always reflects reality.
|
|
43
|
+
|
|
42
44
|
**Parameters:**
|
|
43
45
|
|
|
44
46
|
| Name | Type | Required | Description |
|
|
45
47
|
|------|------|----------|-------------|
|
|
46
|
-
| `options` | `StartOptions` | |
|
|
48
|
+
| `options` | `StartOptions` | | Optional runtime overrides for port and host |
|
|
47
49
|
|
|
48
|
-
**Returns:** `
|
|
50
|
+
**Returns:** `Promise<this>`
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
|
|
52
54
|
### stop
|
|
53
55
|
|
|
54
|
-
**Returns:** `
|
|
56
|
+
**Returns:** `Promise<this>`
|
|
55
57
|
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
### configure
|
|
59
61
|
|
|
60
|
-
**Returns:** `
|
|
62
|
+
**Returns:** `Promise<this>`
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
|
|
@@ -85,6 +87,32 @@ container.server('express', {
|
|
|
85
87
|
|
|
86
88
|
|
|
87
89
|
|
|
90
|
+
### reloadEndpoint
|
|
91
|
+
|
|
92
|
+
Reload a mounted endpoint by its file path. Re-reads the module through the helpers VM loader so the next request picks up the new handlers.
|
|
93
|
+
|
|
94
|
+
**Parameters:**
|
|
95
|
+
|
|
96
|
+
| Name | Type | Required | Description |
|
|
97
|
+
|------|------|----------|-------------|
|
|
98
|
+
| `filePath` | `string` | ✓ | Absolute path to the endpoint file |
|
|
99
|
+
|
|
100
|
+
**Returns:** `Promise<Endpoint | null>`
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
### useEndpointModules
|
|
105
|
+
|
|
106
|
+
**Parameters:**
|
|
107
|
+
|
|
108
|
+
| Name | Type | Required | Description |
|
|
109
|
+
|------|------|----------|-------------|
|
|
110
|
+
| `modules` | `EndpointModule[]` | ✓ | Parameter modules |
|
|
111
|
+
|
|
112
|
+
**Returns:** `Promise<this>`
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
88
116
|
### serveOpenAPISpec
|
|
89
117
|
|
|
90
118
|
**Parameters:**
|
|
@@ -113,9 +141,9 @@ container.server('express', {
|
|
|
113
141
|
|
|
114
142
|
| Property | Type | Description |
|
|
115
143
|
|----------|------|-------------|
|
|
116
|
-
| `express` | `
|
|
117
|
-
| `hooks` | `any` | |
|
|
118
|
-
| `app` | `
|
|
144
|
+
| `express` | `typeof express` | |
|
|
145
|
+
| `hooks` | `{ create: (app: Express, server: Server) => Express; beforeStart: (options: any, server: Server) => any }` | |
|
|
146
|
+
| `app` | `Express` | |
|
|
119
147
|
|
|
120
148
|
## State (Zod v4 schema)
|
|
121
149
|
|
package/docs/apis/servers/mcp.md
CHANGED
|
@@ -102,7 +102,7 @@ Register an MCP prompt. Prompts are reusable message templates that AI clients c
|
|
|
102
102
|
|
|
103
103
|
Configure the MCP protocol server and register all protocol handlers. Called automatically before start() if not already configured.
|
|
104
104
|
|
|
105
|
-
**Returns:** `
|
|
105
|
+
**Returns:** `Promise<this>`
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
|
|
@@ -135,7 +135,7 @@ Start the MCP server with the specified transport.
|
|
|
135
135
|
| `transport` | `any` | 'stdio' for CLI integration, 'http' for remote access |
|
|
136
136
|
| `port` | `any` | Port for HTTP transport (default 3001) |
|
|
137
137
|
|
|
138
|
-
**Returns:** `
|
|
138
|
+
**Returns:** `Promise<this>`
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
|
|
@@ -143,7 +143,7 @@ Start the MCP server with the specified transport.
|
|
|
143
143
|
|
|
144
144
|
Stop the MCP server and close all connections.
|
|
145
145
|
|
|
146
|
-
**Returns:** `
|
|
146
|
+
**Returns:** `Promise<this>`
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# WebsocketServer (servers.websocket)
|
|
2
2
|
|
|
3
|
-
WebSocket server built on the `ws` library with optional JSON message framing. Manages WebSocket connections, tracks connected clients, and bridges messages to Luca's event bus. When `json` mode is enabled, incoming messages are automatically JSON-parsed (with `.toString()` for Buffer data) and outgoing messages via `send()` / `broadcast()` are JSON-stringified. When `json` mode is disabled, raw message data is emitted as-is and `send()` / `broadcast()` still JSON-stringify for safety.
|
|
3
|
+
WebSocket server built on the `ws` library with optional JSON message framing. Manages WebSocket connections, tracks connected clients, and bridges messages to Luca's event bus. When `json` mode is enabled, incoming messages are automatically JSON-parsed (with `.toString()` for Buffer data) and outgoing messages via `send()` / `broadcast()` are JSON-stringified. When `json` mode is disabled, raw message data is emitted as-is and `send()` / `broadcast()` still JSON-stringify for safety. Supports ask/reply semantics when paired with the Luca WebSocket client. The server can `ask(ws, type, data)` a connected client and await a typed response, or handle incoming asks from clients by listening for messages with a `requestId` and replying via `send(ws, { replyTo, data })`. Requests time out if no reply arrives within the configurable window.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -33,7 +33,7 @@ container.server('websocket', {
|
|
|
33
33
|
|------|------|----------|-------------|
|
|
34
34
|
| `message` | `any` | ✓ | Parameter message |
|
|
35
35
|
|
|
36
|
-
**Returns:** `
|
|
36
|
+
**Returns:** `Promise<this>`
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
|
|
@@ -46,25 +46,51 @@ container.server('websocket', {
|
|
|
46
46
|
| `ws` | `any` | ✓ | Parameter ws |
|
|
47
47
|
| `message` | `any` | ✓ | Parameter message |
|
|
48
48
|
|
|
49
|
-
**Returns:** `
|
|
49
|
+
**Returns:** `Promise<this>`
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### ask
|
|
54
|
+
|
|
55
|
+
Send a request to a specific client and wait for a correlated response. The client is expected to reply with a message whose `replyTo` matches the `requestId` of this message.
|
|
56
|
+
|
|
57
|
+
**Parameters:**
|
|
58
|
+
|
|
59
|
+
| Name | Type | Required | Description |
|
|
60
|
+
|------|------|----------|-------------|
|
|
61
|
+
| `ws` | `any` | ✓ | The WebSocket client to ask |
|
|
62
|
+
| `type` | `string` | ✓ | A string identifying the request type |
|
|
63
|
+
| `data` | `any` | | Optional payload |
|
|
64
|
+
| `timeout` | `any` | | How long to wait (default 10 000 ms) |
|
|
65
|
+
|
|
66
|
+
**Returns:** `Promise<R>`
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
ws.on('connection', async (client) => {
|
|
70
|
+
const info = await ws.ask(client, 'identify')
|
|
71
|
+
console.log('Client says:', info)
|
|
72
|
+
})
|
|
73
|
+
```
|
|
50
74
|
|
|
51
75
|
|
|
52
76
|
|
|
53
77
|
### start
|
|
54
78
|
|
|
79
|
+
Start the WebSocket server. A runtime `port` overrides the constructor option and is written to state before the underlying `ws.Server` is created, so the server binds to the correct port.
|
|
80
|
+
|
|
55
81
|
**Parameters:**
|
|
56
82
|
|
|
57
83
|
| Name | Type | Required | Description |
|
|
58
84
|
|------|------|----------|-------------|
|
|
59
|
-
| `options` | `StartOptions` | |
|
|
85
|
+
| `options` | `StartOptions` | | Optional runtime overrides for port and host |
|
|
60
86
|
|
|
61
|
-
**Returns:** `
|
|
87
|
+
**Returns:** `Promise<this>`
|
|
62
88
|
|
|
63
89
|
|
|
64
90
|
|
|
65
91
|
### stop
|
|
66
92
|
|
|
67
|
-
**Returns:** `
|
|
93
|
+
**Returns:** `Promise<this>`
|
|
68
94
|
|
|
69
95
|
|
|
70
96
|
|
|
@@ -72,8 +98,8 @@ container.server('websocket', {
|
|
|
72
98
|
|
|
73
99
|
| Property | Type | Description |
|
|
74
100
|
|----------|------|-------------|
|
|
75
|
-
| `wss` | `
|
|
76
|
-
| `port` | `
|
|
101
|
+
| `wss` | `BaseServer` | |
|
|
102
|
+
| `port` | `number` | The port this server will bind to. Defaults to 8081 if not set via constructor options or start(). |
|
|
77
103
|
|
|
78
104
|
## Events (Zod v4 schema)
|
|
79
105
|
|
|
@@ -123,5 +149,22 @@ ws.on('message', (data, client) => {
|
|
|
123
149
|
console.log('Received:', data)
|
|
124
150
|
ws.broadcast({ echo: data })
|
|
125
151
|
})
|
|
152
|
+
|
|
153
|
+
// ask/reply: request info from a connected client
|
|
154
|
+
ws.on('connection', async (client) => {
|
|
155
|
+
const info = await ws.ask(client, 'identify')
|
|
156
|
+
console.log('Client says:', info)
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
**ask**
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
ws.on('connection', async (client) => {
|
|
166
|
+
const info = await ws.ask(client, 'identify')
|
|
167
|
+
console.log('Client says:', info)
|
|
168
|
+
})
|
|
126
169
|
```
|
|
127
170
|
|
package/docs/bootstrap/CLAUDE.md
CHANGED
|
@@ -32,7 +32,7 @@ The `luca` binary is available in the path. Key commands:
|
|
|
32
32
|
1. **Discover** — Run `luca describe features`, `luca describe clients`, `luca describe servers` to see what's available. Then `luca describe <name>` for full docs on any helper, or `luca describe <name>.<member>` to drill into a specific method or getter. This is your first move, always. (See `.claude/skills/luca-framework/SKILL.md` for the full mental model.)
|
|
33
33
|
2. **Build** — Run `luca scaffold <type> --tutorial` before creating a new helper. It covers the full guide for that type.
|
|
34
34
|
3. **Prototype** — Use `luca eval "expression"` to test container code before wiring up full handlers. Reach for eval when you're stuck — it gives you full runtime access.
|
|
35
|
-
4. **Reference** —
|
|
35
|
+
4. **Reference** — The skill file (`.claude/skills/luca-framework/SKILL.md`) includes a full Framework Index with every feature, client, and server organized by category
|
|
36
36
|
|
|
37
37
|
## Project Structure
|
|
38
38
|
|
package/docs/bootstrap/SKILL.md
CHANGED
|
@@ -18,7 +18,7 @@ There are three things to learn, in this order:
|
|
|
18
18
|
|
|
19
19
|
## Phase 1: Discover with `luca describe`
|
|
20
20
|
|
|
21
|
-
This is your primary tool.
|
|
21
|
+
This is your primary tool. The `luca` binary is a compiled artifact that bundles all introspection data — it is the authority on what the container provides. Run `luca describe` first — it outputs full documentation for any part of the container: methods, options, events, state, examples. Reading source can be helpful for additional context if it exists in the project, but the source for built-in helpers may not be present — the binary is always the ground truth.
|
|
22
22
|
|
|
23
23
|
### See what's available
|
|
24
24
|
|
|
@@ -70,6 +70,18 @@ luca describe fs git --examples # just examples for both
|
|
|
70
70
|
luca describe fs --usage --methods # combine sections
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
### Get approximate TypeScript types
|
|
74
|
+
|
|
75
|
+
Need to know the shape of a helper for type-safe code? Use `--ts`:
|
|
76
|
+
|
|
77
|
+
```shell
|
|
78
|
+
luca describe fs --ts # approximate TS interface for fs
|
|
79
|
+
luca describe conversation --ts # see the conversation feature's type surface
|
|
80
|
+
luca describe rest --ts # client type shape
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This outputs a ~95% accurate TypeScript representation based on runtime introspection. If a type looks wrong or a method signature seems off, verify with `luca eval` against the live instance.
|
|
84
|
+
|
|
73
85
|
### Describe the container itself
|
|
74
86
|
|
|
75
87
|
```shell
|
|
@@ -85,7 +97,9 @@ luca describe --help # full flag reference for describe
|
|
|
85
97
|
luca help scaffold # help for any command
|
|
86
98
|
```
|
|
87
99
|
|
|
88
|
-
**Use `luca describe` liberally.** It is the fastest, safest way to understand what the container provides. Every feature, client, and server is self-describing — if you know a name, describe will tell you everything about it. Use dot notation (`ui.banner`, `fs.readFile`) when you need docs on just one method or getter.
|
|
100
|
+
**Use `luca describe` liberally.** It is the fastest, safest way to understand what the container provides. Every feature, client, and server is self-describing — if you know a name, describe will tell you everything about it. Use dot notation (`ui.banner`, `fs.readFile`) when you need docs on just one method or getter. Use `--ts` when you need type information for writing code.
|
|
101
|
+
|
|
102
|
+
> **NOTE:** The `luca` binary is compiled and bundles all introspection data. `luca describe` reflects what actually ships in the binary — source files for built-in helpers may not exist in your project. Reading source can add context when it's available, but `luca describe` and `luca eval` are always the authority.
|
|
89
103
|
|
|
90
104
|
---
|
|
91
105
|
|
|
@@ -232,7 +246,7 @@ Everything `luca describe` outputs is also available at runtime in code:
|
|
|
232
246
|
```js
|
|
233
247
|
container.features.describe('fs') // markdown docs (same as the CLI)
|
|
234
248
|
feature.introspect() // structured object: { methods, events, state, options }
|
|
235
|
-
container.
|
|
249
|
+
container.introspectAsText() // full container overview as markdown
|
|
236
250
|
```
|
|
237
251
|
|
|
238
252
|
This is useful inside commands and scripts where you need introspection data programmatically.
|
|
@@ -248,8 +262,80 @@ This is useful inside commands and scripts where you need introspection data pro
|
|
|
248
262
|
- `luca serve --any-port` will open on any port
|
|
249
263
|
|
|
250
264
|
|
|
251
|
-
##
|
|
265
|
+
## Framework Index
|
|
266
|
+
|
|
267
|
+
A table of contents for the container. **Run `luca describe <name>` for full docs on any item.** Use `luca describe <name> --ts` when you need type information. Source may not exist locally for built-in helpers — the compiled binary is the authority.
|
|
268
|
+
|
|
269
|
+
### Features by Category
|
|
270
|
+
|
|
271
|
+
| Category | Features | What they do |
|
|
272
|
+
|----------|----------|--------------|
|
|
273
|
+
| **File System & Code** | `fs`, `grep`, `fileManager` | Read/write files, search code, watch for changes |
|
|
274
|
+
| **Process & Shell** | `proc`, `processManager`, `secureShell` | Run commands, manage long-running processes, SSH |
|
|
275
|
+
| **AI Assistants** | `assistant`, `assistantsManager`, `conversation`, `conversationHistory`, `fileTools` | Build AI assistants, manage conversations, tool calling. `fileTools` composes lower-level features (`fs`, `grep`) into an assistant-ready tool surface — a good example of how features can define tools for assistants (see `references/examples/feature-as-tool-provider.md`). |
|
|
276
|
+
| **AI Agent Wrappers** | `claudeCode`, `openaiCodex`, `lucaCoder` | Spawn and manage external AI agent CLIs as subprocesses |
|
|
277
|
+
| **Data & Storage** | `sqlite`, `postgres`, `diskCache`, `contentDb`, `redis` | Databases, caching, document management |
|
|
278
|
+
| **Networking** | `networking`, `dns` | Network utilities, DNS |
|
|
279
|
+
| **Google Workspace** | `googleAuth`, `googleDrive`, `googleDocs`, `googleSheets`, `googleCalendar`, `googleMail` | OAuth and Google service wrappers |
|
|
280
|
+
| **Dev Tools** | `git`, `docker`, `esbuild`, `vm`, `python`, `packageFinder` | Version control, containers, bundling, sandboxed execution |
|
|
281
|
+
| **Content & NLP** | `docsReader`, `nlp`, `semanticSearch`, `skillsLibrary`, `jsonTree`, `yamlTree` | Document Q&A, text analysis, semantic search, skills, structured file ingestion |
|
|
282
|
+
| **UI & Output** | `ui`, `ink`, `yaml` | Terminal UI, colors, ascii art, structured data display |
|
|
283
|
+
| **Media & Browser** | `browserUse`, `tts`, `downloader`, `opener`, `telegram` | Browser automation, text-to-speech, downloads, messaging |
|
|
284
|
+
| **System** | `os`, `vault`, `helpers`, `introspectionScanner`, `containerLink`, `repl`, `runpod` | OS info, secrets, runtime introspection, remote container linking |
|
|
285
|
+
|
|
286
|
+
### Clients
|
|
287
|
+
|
|
288
|
+
| Client | Purpose |
|
|
289
|
+
|--------|---------|
|
|
290
|
+
| `openai` | Chat completions, embeddings, image generation |
|
|
291
|
+
| `rest` | Generic HTTP client (GET/POST/PUT/PATCH/DELETE) |
|
|
292
|
+
| `websocket` | WebSocket connections |
|
|
293
|
+
| `elevenlabs` | Text-to-speech synthesis |
|
|
294
|
+
| `graph` | GraphQL queries and mutations |
|
|
295
|
+
|
|
296
|
+
### Servers
|
|
297
|
+
|
|
298
|
+
| Server | Purpose |
|
|
299
|
+
|--------|---------|
|
|
300
|
+
| `express` | HTTP server with file-based endpoint routing |
|
|
301
|
+
| `mcp` | Model Context Protocol server for AI tool exposure |
|
|
302
|
+
| `websocket` | WebSocket server with JSON framing |
|
|
303
|
+
| `ipcSocket` | Local IPC socket server for inter-process communication |
|
|
304
|
+
|
|
305
|
+
### Type Discovery
|
|
306
|
+
|
|
307
|
+
`luca describe <name> --ts` outputs an approximate TypeScript representation of any helper as it exists at runtime — ~95% accurate. This is your go-to for writing type-safe code against the container. The binary compiles in the introspection data, so `--ts` reflects what actually exists at runtime even when source isn't available. Reading source can provide additional context when it's there.
|
|
308
|
+
|
|
309
|
+
```shell
|
|
310
|
+
luca describe fs --ts # approximate TS interface for the fs feature
|
|
311
|
+
luca describe conversation --ts # conversation feature type surface
|
|
312
|
+
luca describe express --ts # express server type shape
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
If a method signature or return type looks wrong, verify with `luca eval`:
|
|
316
|
+
|
|
317
|
+
```shell
|
|
318
|
+
luca eval "typeof container.feature('fs').readFile"
|
|
319
|
+
luca eval "container.feature('fs').readFile('package.json')"
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Bundled Examples and Tutorials
|
|
323
|
+
|
|
324
|
+
The skill directory includes reference material:
|
|
325
|
+
|
|
326
|
+
- **`references/examples/`** — short, focused example docs for individual features (e.g. `fs.md`, `git.md`, `proc.md`)
|
|
327
|
+
- **`references/tutorials/`** — longer-form guides covering the container, helpers, commands, endpoints, state/events, assistants, and more
|
|
328
|
+
|
|
329
|
+
These complement `luca describe` — describe gives you the API surface, examples show you patterns in action, and tutorials walk through building things end to end.
|
|
330
|
+
|
|
331
|
+
**Tip:** Runnable markdown is a great artifact to produce when building with luca. `luca run doc.md` executes code blocks inside the Luca VM — useful for both testing and documentation. When prototyping a feature or writing a how-to, consider writing it as a markdown file that can be run.
|
|
332
|
+
|
|
333
|
+
### Container Primitives
|
|
252
334
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
335
|
+
| Primitive | Access | Purpose |
|
|
336
|
+
|-----------|--------|---------|
|
|
337
|
+
| State | `container.state`, `helper.state` | Observable key-value state on every object |
|
|
338
|
+
| Events | `container.on()`, `helper.on()` | Event bus on every object |
|
|
339
|
+
| Paths | `container.paths` | `resolve()`, `join()`, `cwd` |
|
|
340
|
+
| Utils | `container.utils` | `uuid()`, `lodash`, `stringUtils`, `hashObject()` |
|
|
341
|
+
| Registries | `container.features`, `.clients`, `.servers` | Discovery and metadata for all helpers |
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Features as Tool Providers for Assistants"
|
|
3
|
+
tags: [feature, tools, assistant, composition, use, setupToolsConsumer]
|
|
4
|
+
lastTested: null
|
|
5
|
+
lastTestPassed: null
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Features as Tool Providers for Assistants
|
|
9
|
+
|
|
10
|
+
Any feature can expose tools that assistants pick up via `assistant.use(feature)`. This is how you compose lower-level container capabilities into an assistant-ready tool surface. The built-in `fileTools` feature is the canonical example — it wraps `fs` and `grep` into a focused set of tools modeled on what coding assistants need.
|
|
11
|
+
|
|
12
|
+
## The Pattern
|
|
13
|
+
|
|
14
|
+
A feature becomes a tool provider by defining three things:
|
|
15
|
+
|
|
16
|
+
1. **`static tools`** — a record mapping tool names to Zod schemas with descriptions
|
|
17
|
+
2. **Matching methods** — instance methods whose names match the keys in `static tools`
|
|
18
|
+
3. **`setupToolsConsumer()`** (optional) — a hook that runs when an assistant calls `use()`, perfect for injecting system prompt guidance
|
|
19
|
+
|
|
20
|
+
When an assistant calls `assistant.use(feature)`, the framework:
|
|
21
|
+
- Reads `static tools` to register each tool with its schema
|
|
22
|
+
- Routes tool calls to the matching instance methods
|
|
23
|
+
- Calls `setupToolsConsumer()` so the feature can configure the assistant (e.g. add system prompt extensions)
|
|
24
|
+
|
|
25
|
+
## Anatomy of fileTools
|
|
26
|
+
|
|
27
|
+
Here's the structure of the built-in `fileTools` feature (simplified for clarity):
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { z } from 'zod'
|
|
31
|
+
import { Feature } from '@soederpop/luca/feature'
|
|
32
|
+
|
|
33
|
+
export class FileTools extends Feature {
|
|
34
|
+
static { Feature.register(this, 'fileTools') }
|
|
35
|
+
|
|
36
|
+
// ── 1. Declare tools with Zod schemas ──────────────────────────
|
|
37
|
+
static tools = {
|
|
38
|
+
readFile: {
|
|
39
|
+
description: 'Read the contents of a file.',
|
|
40
|
+
schema: z.object({
|
|
41
|
+
path: z.string().describe('File path relative to the project root'),
|
|
42
|
+
offset: z.number().optional().describe('Line number to start reading from'),
|
|
43
|
+
limit: z.number().optional().describe('Maximum number of lines to read'),
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
searchFiles: {
|
|
47
|
+
description: 'Search file contents for a pattern using ripgrep.',
|
|
48
|
+
schema: z.object({
|
|
49
|
+
pattern: z.string().describe('Search pattern (regex supported)'),
|
|
50
|
+
path: z.string().optional().describe('Directory to search in'),
|
|
51
|
+
include: z.string().optional().describe('Glob pattern to filter files'),
|
|
52
|
+
}),
|
|
53
|
+
},
|
|
54
|
+
editFile: {
|
|
55
|
+
description: 'Replace an exact string match in a file.',
|
|
56
|
+
schema: z.object({
|
|
57
|
+
path: z.string().describe('File path relative to the project root'),
|
|
58
|
+
oldString: z.string().describe('The exact text to find and replace'),
|
|
59
|
+
newString: z.string().describe('The replacement text'),
|
|
60
|
+
}),
|
|
61
|
+
},
|
|
62
|
+
// ... more tools
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ── 2. Implement each tool as an instance method ───────────────
|
|
66
|
+
// Method names must match the keys in static tools exactly.
|
|
67
|
+
// Each receives the parsed args object and returns a string.
|
|
68
|
+
|
|
69
|
+
async readFile(args: { path: string; offset?: number; limit?: number }) {
|
|
70
|
+
const fs = this.container.feature('fs')
|
|
71
|
+
const content = await fs.readFileAsync(args.path)
|
|
72
|
+
// ... handle offset/limit
|
|
73
|
+
return content
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async searchFiles(args: { pattern: string; path?: string; include?: string }) {
|
|
77
|
+
const grep = this.container.feature('grep')
|
|
78
|
+
const results = await grep.search({ pattern: args.pattern, path: args.path, include: args.include })
|
|
79
|
+
return JSON.stringify(results.map(r => ({ file: r.file, line: r.line, content: r.content })))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async editFile(args: { path: string; oldString: string; newString: string }) {
|
|
83
|
+
const fs = this.container.feature('fs')
|
|
84
|
+
const content = await fs.readFileAsync(args.path)
|
|
85
|
+
const updated = content.replace(args.oldString, args.newString)
|
|
86
|
+
await fs.writeFileAsync(args.path, updated)
|
|
87
|
+
return `Edited ${args.path}`
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── 3. Configure the assistant when it calls use() ─────────────
|
|
91
|
+
override setupToolsConsumer(consumer) {
|
|
92
|
+
// If the consumer is an assistant, inject guidance into its system prompt
|
|
93
|
+
if (typeof consumer.addSystemPromptExtension === 'function') {
|
|
94
|
+
consumer.addSystemPromptExtension('fileTools', [
|
|
95
|
+
'## File Tools',
|
|
96
|
+
'- All file paths are relative to the project root unless they start with /',
|
|
97
|
+
'- Use searchFiles to understand code before modifying it',
|
|
98
|
+
'- Use editFile for surgical changes — prefer it over writeFile',
|
|
99
|
+
].join('\n'))
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Using It
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const assistant = container.feature('assistant', {
|
|
109
|
+
systemPrompt: 'You are a coding assistant.',
|
|
110
|
+
model: 'gpt-4.1-mini',
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const fileTools = container.feature('fileTools')
|
|
114
|
+
assistant.use(fileTools)
|
|
115
|
+
await assistant.start()
|
|
116
|
+
|
|
117
|
+
// The assistant now has readFile, searchFiles, editFile, etc.
|
|
118
|
+
// and its system prompt includes the fileTools guidance.
|
|
119
|
+
console.log(Object.keys(assistant.tools))
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Selective tool registration
|
|
123
|
+
|
|
124
|
+
You can expose only a subset of tools:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
assistant.use(fileTools.toTools({ only: ['readFile', 'searchFiles', 'listDirectory'] }))
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Why This Pattern Matters
|
|
131
|
+
|
|
132
|
+
This is how features compose for AI. Instead of the assistant importing `fs` and `grep` directly:
|
|
133
|
+
|
|
134
|
+
- The **feature** owns the tool surface — schemas, descriptions, and implementations in one place
|
|
135
|
+
- The **assistant** gets a curated interface, not raw container access
|
|
136
|
+
- **`setupToolsConsumer()`** lets the feature teach the assistant how to use the tools well
|
|
137
|
+
- **`toTools({ only })`** lets you scope down what the assistant can do
|
|
138
|
+
|
|
139
|
+
Any feature you build can follow this same pattern. Define `static tools`, implement matching methods, optionally override `setupToolsConsumer()`, and assistants can `use()` it.
|
|
140
|
+
|
|
141
|
+
## Summary
|
|
142
|
+
|
|
143
|
+
Features are the natural place to package tools for assistants. The `static tools` record declares the schema, instance methods implement the logic, and `setupToolsConsumer()` wires up assistant-specific configuration like system prompt extensions. This keeps tool definitions, implementations, and assistant guidance co-located in a single feature class.
|
package/docs/examples/python.md
CHANGED
|
@@ -86,6 +86,47 @@ console.log('Install exit code:', result.exitCode)
|
|
|
86
86
|
|
|
87
87
|
When no `installCommand` is provided, the feature infers the correct command from the detected environment type (e.g., `uv sync` for uv, `pip install -e .` for venv).
|
|
88
88
|
|
|
89
|
+
## Persistent Sessions
|
|
90
|
+
|
|
91
|
+
Start a long-lived Python process where state persists across calls. Ideal for working inside real Python codebases, data analysis, and anything with expensive setup.
|
|
92
|
+
|
|
93
|
+
```ts skip
|
|
94
|
+
const python = container.feature('python', { dir: '/path/to/python-project' })
|
|
95
|
+
await python.enable()
|
|
96
|
+
await python.startSession()
|
|
97
|
+
|
|
98
|
+
// State persists across calls
|
|
99
|
+
await python.run('x = 42')
|
|
100
|
+
const result = await python.run('print(x * 2)')
|
|
101
|
+
console.log('stdout:', result.stdout) // '84\n'
|
|
102
|
+
|
|
103
|
+
// Evaluate expressions and get values back
|
|
104
|
+
const val = await python.eval('x + 1')
|
|
105
|
+
console.log('eval:', val) // 43
|
|
106
|
+
|
|
107
|
+
// Import project modules (sys.path is set up automatically)
|
|
108
|
+
await python.importModule('json')
|
|
109
|
+
const encoded = await python.call('json.dumps', [{ key: 'value' }], { indent: 2 })
|
|
110
|
+
console.log('call:', encoded)
|
|
111
|
+
|
|
112
|
+
// Inspect the namespace
|
|
113
|
+
const locals = await python.getLocals()
|
|
114
|
+
console.log('locals:', Object.keys(locals))
|
|
115
|
+
|
|
116
|
+
// Errors don't crash the session
|
|
117
|
+
const bad = await python.run('raise ValueError("oops")')
|
|
118
|
+
console.log('error:', bad.error) // 'oops'
|
|
119
|
+
|
|
120
|
+
// Still alive
|
|
121
|
+
const check = await python.run('print("still here")')
|
|
122
|
+
console.log(check.stdout) // 'still here\n'
|
|
123
|
+
|
|
124
|
+
// Clean up
|
|
125
|
+
await python.stopSession()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
See the [Python Sessions tutorial](../tutorials/19-python-sessions.md) for real-world patterns (data pipelines, Django, ML models).
|
|
129
|
+
|
|
89
130
|
## Summary
|
|
90
131
|
|
|
91
|
-
The `python` feature bridges Luca and Python by auto-detecting environments, managing dependencies, and providing
|
|
132
|
+
The `python` feature bridges Luca and Python by auto-detecting environments, managing dependencies, and providing both stateless execution and persistent sessions. It supports uv, conda, venv, and system Python installations.
|