@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.
Files changed (92) hide show
  1. package/README.md +241 -36
  2. package/bun.lock +24 -6
  3. package/commands/build-python-bridge.ts +43 -0
  4. package/docs/README.md +1 -1
  5. package/docs/TABLE-OF-CONTENTS.md +0 -1
  6. package/docs/apis/clients/rest.md +7 -7
  7. package/docs/apis/clients/websocket.md +23 -10
  8. package/docs/apis/features/agi/assistant.md +155 -8
  9. package/docs/apis/features/agi/assistants-manager.md +90 -22
  10. package/docs/apis/features/agi/auto-assistant.md +377 -0
  11. package/docs/apis/features/agi/browser-use.md +802 -0
  12. package/docs/apis/features/agi/claude-code.md +6 -1
  13. package/docs/apis/features/agi/conversation-history.md +7 -6
  14. package/docs/apis/features/agi/conversation.md +111 -38
  15. package/docs/apis/features/agi/docs-reader.md +35 -57
  16. package/docs/apis/features/agi/file-tools.md +163 -0
  17. package/docs/apis/features/agi/openapi.md +2 -2
  18. package/docs/apis/features/agi/skills-library.md +227 -0
  19. package/docs/apis/features/node/content-db.md +125 -4
  20. package/docs/apis/features/node/disk-cache.md +11 -11
  21. package/docs/apis/features/node/downloader.md +1 -1
  22. package/docs/apis/features/node/file-manager.md +15 -15
  23. package/docs/apis/features/node/fs.md +78 -21
  24. package/docs/apis/features/node/git.md +50 -10
  25. package/docs/apis/features/node/google-calendar.md +3 -0
  26. package/docs/apis/features/node/google-docs.md +10 -1
  27. package/docs/apis/features/node/google-drive.md +3 -0
  28. package/docs/apis/features/node/google-mail.md +214 -0
  29. package/docs/apis/features/node/google-sheets.md +3 -0
  30. package/docs/apis/features/node/ink.md +10 -10
  31. package/docs/apis/features/node/ipc-socket.md +83 -93
  32. package/docs/apis/features/node/networking.md +5 -5
  33. package/docs/apis/features/node/os.md +7 -7
  34. package/docs/apis/features/node/package-finder.md +14 -14
  35. package/docs/apis/features/node/proc.md +2 -1
  36. package/docs/apis/features/node/process-manager.md +70 -3
  37. package/docs/apis/features/node/python.md +265 -9
  38. package/docs/apis/features/node/redis.md +380 -0
  39. package/docs/apis/features/node/ui.md +13 -13
  40. package/docs/apis/servers/express.md +35 -7
  41. package/docs/apis/servers/mcp.md +3 -3
  42. package/docs/apis/servers/websocket.md +51 -8
  43. package/docs/bootstrap/CLAUDE.md +1 -1
  44. package/docs/bootstrap/SKILL.md +93 -7
  45. package/docs/examples/feature-as-tool-provider.md +143 -0
  46. package/docs/examples/python.md +42 -1
  47. package/docs/introspection.md +15 -5
  48. package/docs/tutorials/00-bootstrap.md +3 -3
  49. package/docs/tutorials/02-container.md +2 -2
  50. package/docs/tutorials/10-creating-features.md +5 -0
  51. package/docs/tutorials/13-introspection.md +12 -2
  52. package/docs/tutorials/19-python-sessions.md +401 -0
  53. package/package.json +8 -5
  54. package/scripts/examples/using-assistant-with-mcp.ts +2 -7
  55. package/scripts/test-linux-binary.sh +80 -0
  56. package/src/agi/container.server.ts +8 -0
  57. package/src/agi/features/assistant.ts +18 -0
  58. package/src/agi/features/autonomous-assistant.ts +435 -0
  59. package/src/agi/features/conversation.ts +58 -6
  60. package/src/agi/features/file-tools.ts +286 -0
  61. package/src/agi/features/luca-coder.ts +643 -0
  62. package/src/bootstrap/generated.ts +705 -107
  63. package/src/cli/build-info.ts +2 -2
  64. package/src/cli/cli.ts +22 -13
  65. package/src/commands/bootstrap.ts +49 -6
  66. package/src/commands/code.ts +369 -0
  67. package/src/commands/describe.ts +7 -2
  68. package/src/commands/index.ts +1 -0
  69. package/src/commands/sandbox-mcp.ts +7 -7
  70. package/src/commands/save-api-docs.ts +1 -1
  71. package/src/container-describer.ts +4 -4
  72. package/src/container.ts +10 -19
  73. package/src/helper.ts +24 -33
  74. package/src/introspection/generated.agi.ts +3026 -849
  75. package/src/introspection/generated.node.ts +1690 -1012
  76. package/src/introspection/generated.web.ts +15 -57
  77. package/src/node/container.ts +5 -5
  78. package/src/node/features/figlet-fonts.ts +597 -0
  79. package/src/node/features/fs.ts +3 -9
  80. package/src/node/features/helpers.ts +20 -0
  81. package/src/node/features/python.ts +429 -16
  82. package/src/node/features/redis.ts +446 -0
  83. package/src/node/features/ui.ts +4 -11
  84. package/src/python/bridge.py +220 -0
  85. package/src/python/generated.ts +227 -0
  86. package/src/scaffolds/generated.ts +1 -1
  87. package/test/python-session.test.ts +105 -0
  88. package/assistants/lucaExpert/CORE.md +0 -37
  89. package/assistants/lucaExpert/hooks.ts +0 -9
  90. package/assistants/lucaExpert/tools.ts +0 -177
  91. package/docs/examples/port-exposer.md +0 -89
  92. package/src/node/features/port-exposer.ts +0 -351
@@ -32,7 +32,7 @@ container.feature('ink', {
32
32
 
33
33
  Pre-load ink + react modules so the sync getters work. Called automatically by render(), but you can call it early.
34
34
 
35
- **Returns:** `void`
35
+ **Returns:** `Promise<this>`
36
36
 
37
37
  ```ts
38
38
  const ink = container.feature('ink', { enable: true })
@@ -54,7 +54,7 @@ Mount a React element to the terminal. Wraps `ink.render()` — automatically lo
54
54
  | `node` | `any` | ✓ | A React element (JSX or React.createElement) |
55
55
  | `options` | `Record<string, any>` | | Ink render options (stdout, stdin, debug, etc.) |
56
56
 
57
- **Returns:** `void`
57
+ **Returns:** `Promise<any>`
58
58
 
59
59
 
60
60
 
@@ -138,7 +138,7 @@ Register a named React function component as a renderable block.
138
138
  | `name` | `string` | ✓ | Unique block name |
139
139
  | `component` | `Function` | ✓ | A React function component |
140
140
 
141
- **Returns:** `void`
141
+ **Returns:** `this`
142
142
 
143
143
  ```ts
144
144
  ink.registerBlock('Greeting', ({ name }) =>
@@ -159,7 +159,7 @@ Render a registered block by name with optional props. Looks up the component, c
159
159
  | `name` | `string` | ✓ | The registered block name |
160
160
  | `data` | `Record<string, any>` | | Props to pass to the component |
161
161
 
162
- **Returns:** `void`
162
+ **Returns:** `Promise<void>`
163
163
 
164
164
  ```ts
165
165
  await ink.renderBlock('Greeting', { name: 'Jon' })
@@ -179,7 +179,7 @@ Render a registered block that needs to stay mounted for async work. The compone
179
179
  | `data` | `Record<string, any>` | | Props to pass to the component (a `done` prop is added automatically) |
180
180
  | `options` | `{ timeout?: number }` | | `timeout` in ms before force-unmounting (default 30 000) |
181
181
 
182
- **Returns:** `void`
182
+ **Returns:** `Promise<void>`
183
183
 
184
184
  ```tsx
185
185
  // In a ## Blocks section:
@@ -205,12 +205,12 @@ await renderAsync('AsyncChart', { url: 'https://api.example.com/data' })
205
205
 
206
206
  | Property | Type | Description |
207
207
  |----------|------|-------------|
208
- | `React` | `any` | The React module (createElement, useState, useEffect, etc.) Exposed so consumers don't need a separate react import. Lazy-loaded — first access triggers the import. |
209
- | `components` | `any` | All Ink components as a single object for destructuring. ```ts const { Box, Text, Static, Spacer } = ink.components ``` |
210
- | `hooks` | `any` | All Ink hooks as a single object for destructuring. ```ts const { useInput, useApp, useFocus } = ink.hooks ``` |
211
- | `measureElement` | `any` | The Ink measureElement utility. |
208
+ | `React` | `typeof import('react')` | The React module (createElement, useState, useEffect, etc.) Exposed so consumers don't need a separate react import. Lazy-loaded — first access triggers the import. |
209
+ | `components` | `{ Box: typeof import('ink').Box; Text: typeof import('ink').Text; Static: typeof import('ink').Static; Transform: typeof import('ink').Transform; Newline: typeof import('ink').Newline; Spacer: typeof import('ink').Spacer }` | All Ink components as a single object for destructuring. ```ts const { Box, Text, Static, Spacer } = ink.components ``` |
210
+ | `hooks` | `{ useInput: typeof import('ink').useInput; useApp: typeof import('ink').useApp; useStdin: typeof import('ink').useStdin; useStdout: typeof import('ink').useStdout; useStderr: typeof import('ink').useStderr; useFocus: typeof import('ink').useFocus; useFocusManager: typeof import('ink').useFocusManager; useCursor: typeof import('ink').useCursor }` | All Ink hooks as a single object for destructuring. ```ts const { useInput, useApp, useFocus } = ink.hooks ``` |
211
+ | `measureElement` | `typeof import('ink').measureElement` | The Ink measureElement utility. |
212
212
  | `isMounted` | `boolean` | Whether an ink app is currently mounted. |
213
- | `instance` | `any` | The raw ink render instance if you need low-level access. |
213
+ | `instance` | `any | null` | The raw ink render instance if you need low-level access. |
214
214
  | `blocks` | `string[]` | List all registered block names. |
215
215
 
216
216
  ## Events (Zod v4 schema)
@@ -1,6 +1,6 @@
1
1
  # IpcSocket (features.ipcSocket)
2
2
 
3
- IpcSocket Feature - Inter-Process Communication via Unix Domain Sockets This feature provides robust IPC (Inter-Process Communication) capabilities using Unix domain sockets. It supports both server and client modes, allowing processes to communicate efficiently through file system-based socket connections. **Key Features:** - Dual-mode operation: server and client functionality - JSON message serialization/deserialization - Multiple client connection support (server mode) - Event-driven message handling - Automatic socket cleanup and management - Broadcast messaging to all connected clients - Lock file management for socket paths **Communication Pattern:** - Messages are automatically JSON-encoded with unique IDs - Both server and client emit 'message' events for incoming data - Server can broadcast to all connected clients - Client maintains single connection to server **Socket Management:** - Automatic cleanup of stale socket files - Connection tracking and management - Graceful shutdown procedures - Lock file protection against conflicts **Usage Examples:** **Server Mode:** ```typescript const ipc = container.feature('ipcSocket'); await ipc.listen('/tmp/myapp.sock', true); // removeLock=true ipc.on('connection', (socket) => { console.log('Client connected'); }); ipc.on('message', (data) => { console.log('Received:', data); ipc.broadcast({ reply: 'ACK', original: data }); }); ``` **Client Mode:** ```typescript const ipc = container.feature('ipcSocket'); await ipc.connect('/tmp/myapp.sock'); ipc.on('message', (data) => { console.log('Server says:', data); }); await ipc.send({ type: 'request', payload: 'hello' }); ```
3
+ IpcSocket Feature - Inter-Process Communication via Unix Domain Sockets This feature provides robust IPC (Inter-Process Communication) capabilities using Unix domain sockets. It supports both server and client modes, allowing processes to communicate efficiently through file system-based socket connections. **Key Features:** - Hub-and-spoke: one server, many named clients with identity tracking - Targeted messaging: sendTo(clientId), broadcast(msg, excludeId) - Request/reply: ask() + reply() with timeout-based correlation - Auto-reconnect: clients reconnect with exponential backoff - Stale socket detection: probeSocket() before listen() - Clean shutdown: stopServer() removes socket file **Server (Hub):** ```typescript const ipc = container.feature('ipcSocket'); await ipc.listen('/tmp/hub.sock', true); ipc.on('connection', (clientId, socket) => { console.log('Client joined:', clientId); }); ipc.on('message', (data, clientId) => { console.log(`From ${clientId}:`, data); // Reply to sender, or ask and wait ipc.sendTo(clientId, { ack: true }); }); ``` **Client (Spoke):** ```typescript const ipc = container.feature('ipcSocket'); await ipc.connect('/tmp/hub.sock', { reconnect: true, name: 'worker-1' }); // Fire and forget await ipc.send({ type: 'status', ready: true }); // Request/reply ipc.on('message', (data) => { if (data.requestId) ipc.reply(data.requestId, { result: 42 }); }); ```
4
4
 
5
5
  ## Usage
6
6
 
@@ -64,81 +64,113 @@ try {
64
64
 
65
65
  ### broadcast
66
66
 
67
- Broadcasts a message to all connected clients (server mode only). This method sends a JSON-encoded message with a unique ID to every client currently connected to the server. Each message is automatically wrapped with metadata including a UUID for tracking. **Message Format:** Messages are automatically wrapped in the format: ```json { "data": <your_message>, "id": "<uuid>" } ```
67
+ Broadcasts a message to all connected clients (server mode only).
68
68
 
69
69
  **Parameters:**
70
70
 
71
71
  | Name | Type | Required | Description |
72
72
  |------|------|----------|-------------|
73
- | `message` | `any` | ✓ | The message object to broadcast to all clients |
73
+ | `message` | `any` | ✓ | The message object to broadcast |
74
+ | `exclude` | `string` | | Optional client ID to exclude from broadcast |
74
75
 
75
- **Returns:** `void`
76
+ **Returns:** `this`
76
77
 
77
- ```ts
78
- // Broadcast to all connected clients
79
- ipc.broadcast({
80
- type: 'notification',
81
- message: 'Server is shutting down in 30 seconds',
82
- timestamp: Date.now()
83
- });
84
78
 
85
- // Chain multiple operations
86
- ipc.broadcast({ status: 'ready' })
87
- .broadcast({ time: new Date().toISOString() });
88
- ```
79
+
80
+ ### sendTo
81
+
82
+ Sends a message to a specific client by ID (server mode only).
83
+
84
+ **Parameters:**
85
+
86
+ | Name | Type | Required | Description |
87
+ |------|------|----------|-------------|
88
+ | `clientId` | `string` | ✓ | The target client ID |
89
+ | `message` | `any` | ✓ | The message to send |
90
+
91
+ **Returns:** `boolean`
89
92
 
90
93
 
91
94
 
92
95
  ### send
93
96
 
94
- Sends a message to the server (client mode only). This method sends a JSON-encoded message with a unique ID to the connected server. The message is automatically wrapped with metadata for tracking purposes. **Message Format:** Messages are automatically wrapped in the format: ```json { "data": <your_message>, "id": "<uuid>" } ```
97
+ Fire-and-forget: sends a message to the server (client mode only). For server→client, use sendTo() or broadcast().
95
98
 
96
99
  **Parameters:**
97
100
 
98
101
  | Name | Type | Required | Description |
99
102
  |------|------|----------|-------------|
100
- | `message` | `any` | ✓ | The message object to send to the server |
103
+ | `message` | `any` | ✓ | The message to send |
101
104
 
102
- **Returns:** `void`
105
+ **Returns:** `Promise<void>`
103
106
 
104
- ```ts
105
- // Send a simple message
106
- await ipc.send({ type: 'ping' });
107
107
 
108
- // Send complex data
109
- await ipc.send({
110
- type: 'data_update',
111
- payload: { users: [...], timestamp: Date.now() }
112
- });
113
- ```
108
+
109
+ ### ask
110
+
111
+ Sends a message and waits for a correlated reply. Works in both client and server mode. The recipient should call `reply(requestId, response)` to respond.
112
+
113
+ **Parameters:**
114
+
115
+ | Name | Type | Required | Description |
116
+ |------|------|----------|-------------|
117
+ | `message` | `any` | ✓ | The message to send |
118
+ | `options` | `{ clientId?: string; timeoutMs?: number }` | | Optional: clientId (server mode target), timeoutMs |
119
+
120
+ **Returns:** `Promise<any>`
121
+
122
+
123
+
124
+ ### reply
125
+
126
+ Sends a reply to a previous ask() call, correlated by requestId.
127
+
128
+ **Parameters:**
129
+
130
+ | Name | Type | Required | Description |
131
+ |------|------|----------|-------------|
132
+ | `requestId` | `string` | ✓ | The requestId from the incoming message |
133
+ | `data` | `any` | ✓ | The reply payload |
134
+ | `clientId` | `string` | | Target client (server mode; for client mode, omit) |
135
+
136
+ **Returns:** `void`
114
137
 
115
138
 
116
139
 
117
140
  ### connect
118
141
 
119
- Connects to an IPC server at the specified socket path (client mode). This method establishes a client connection to an existing IPC server. Once connected, the client can send messages to the server and receive responses. The connection is maintained until explicitly closed or the server terminates. **Connection Behavior:** - Sets the socket mode to 'client' - Returns existing connection if already connected - Automatically handles connection events and cleanup - JSON-parses incoming messages and emits 'message' events - Cleans up connection reference when socket closes **Error Handling:** - Throws error if already in server mode - Rejects promise on connection failures - Automatically cleans up on connection close
142
+ Connects to an IPC server at the specified socket path (client mode).
120
143
 
121
144
  **Parameters:**
122
145
 
123
146
  | Name | Type | Required | Description |
124
147
  |------|------|----------|-------------|
125
- | `socketPath` | `string` | ✓ | The file system path to the server's Unix domain socket |
148
+ | `socketPath` | `string` | ✓ | Path to the server's Unix domain socket |
149
+ | `options` | `{ reconnect?: boolean; name?: string }` | | Optional: reconnect (enable auto-reconnect), name (identify this client) |
126
150
 
127
151
  **Returns:** `Promise<Socket>`
128
152
 
129
- ```ts
130
- // Connect to server
131
- const socket = await ipc.connect('/tmp/myapp.sock');
132
- console.log('Connected to IPC server');
133
153
 
134
- // Handle incoming messages
135
- ipc.on('message', (data) => {
136
- console.log('Server message:', data);
137
- });
138
154
 
139
- // Send messages
140
- await ipc.send({ type: 'hello', client_id: 'client_001' });
141
- ```
155
+ ### disconnect
156
+
157
+ Disconnects the client and stops any reconnection attempts.
158
+
159
+ **Returns:** `void`
160
+
161
+
162
+
163
+ ### probeSocket
164
+
165
+ Probe an existing socket to see if a live listener is behind it. Attempts a quick connect — if it succeeds, someone is listening.
166
+
167
+ **Parameters:**
168
+
169
+ | Name | Type | Required | Description |
170
+ |------|------|----------|-------------|
171
+ | `socketPath` | `string` | ✓ | Parameter socketPath |
172
+
173
+ **Returns:** `Promise<boolean>`
142
174
 
143
175
 
144
176
 
@@ -146,12 +178,20 @@ await ipc.send({ type: 'hello', client_id: 'client_001' });
146
178
 
147
179
  | Property | Type | Description |
148
180
  |----------|------|-------------|
149
- | `isClient` | `any` | Checks if the IPC socket is operating in client mode. |
150
- | `isServer` | `any` | Checks if the IPC socket is operating in server mode. |
151
- | `connection` | `any` | Gets the current client connection socket. |
181
+ | `isClient` | `boolean` | Checks if the IPC socket is operating in client mode. |
182
+ | `isServer` | `boolean` | Checks if the IPC socket is operating in server mode. |
183
+ | `clientCount` | `number` | Returns the number of currently connected clients (server mode). |
184
+ | `connectedClients` | `Array<{ id: string; name?: string; connectedAt: number }>` | Returns info about all connected clients (server mode). |
185
+ | `connection` | `Socket | undefined` | Gets the current client connection socket. |
152
186
 
153
187
  ## Events (Zod v4 schema)
154
188
 
189
+ ### disconnection
190
+
191
+ Event emitted by IpcSocket
192
+
193
+
194
+
155
195
  ### connection
156
196
 
157
197
  Event emitted by IpcSocket
@@ -207,53 +247,3 @@ try {
207
247
  }
208
248
  ```
209
249
 
210
-
211
-
212
- **broadcast**
213
-
214
- ```ts
215
- // Broadcast to all connected clients
216
- ipc.broadcast({
217
- type: 'notification',
218
- message: 'Server is shutting down in 30 seconds',
219
- timestamp: Date.now()
220
- });
221
-
222
- // Chain multiple operations
223
- ipc.broadcast({ status: 'ready' })
224
- .broadcast({ time: new Date().toISOString() });
225
- ```
226
-
227
-
228
-
229
- **send**
230
-
231
- ```ts
232
- // Send a simple message
233
- await ipc.send({ type: 'ping' });
234
-
235
- // Send complex data
236
- await ipc.send({
237
- type: 'data_update',
238
- payload: { users: [...], timestamp: Date.now() }
239
- });
240
- ```
241
-
242
-
243
-
244
- **connect**
245
-
246
- ```ts
247
- // Connect to server
248
- const socket = await ipc.connect('/tmp/myapp.sock');
249
- console.log('Connected to IPC server');
250
-
251
- // Handle incoming messages
252
- ipc.on('message', (data) => {
253
- console.log('Server message:', data);
254
- });
255
-
256
- // Send messages
257
- await ipc.send({ type: 'hello', client_id: 'client_001' });
258
- ```
259
-
@@ -32,7 +32,7 @@ Finds the next available port starting from the specified port number. This meth
32
32
  |------|------|----------|-------------|
33
33
  | `startAt` | `any` | | The port number to start searching from (0 means system will choose) |
34
34
 
35
- **Returns:** `void`
35
+ **Returns:** `Promise<number>`
36
36
 
37
37
  ```ts
38
38
  // Find any available port
@@ -55,7 +55,7 @@ Checks if a specific port is available for use. This method attempts to detect i
55
55
  |------|------|----------|-------------|
56
56
  | `checkPort` | `any` | | The port number to check for availability |
57
57
 
58
- **Returns:** `void`
58
+ **Returns:** `Promise<boolean>`
59
59
 
60
60
  ```ts
61
61
  // Check if port 8080 is available
@@ -197,9 +197,9 @@ Convenience method: discover and port-scan hosts across all local networks.
197
197
 
198
198
  | Property | Type | Description |
199
199
  |----------|------|-------------|
200
- | `proc` | `any` | |
201
- | `os` | `any` | |
202
- | `nmap` | `any` | Optional nmap wrapper for users that already have nmap installed. |
200
+ | `proc` | `ReturnType<typeof this.container.feature<'proc'>>` | |
201
+ | `os` | `ReturnType<typeof this.container.feature<'os'>>` | |
202
+ | `nmap` | `{ isAvailable: () => Promise<boolean>; scan: (target: string, args?: string[]) => Promise<{ hosts: NmapHost[]; raw: string }>; quickScan: (cidr: string) => Promise<{ hosts: NmapHost[]; raw: string }>; fullScan: (target: string) => Promise<{ hosts: NmapHost[]; raw: string }> }` | Optional nmap wrapper for users that already have nmap installed. |
203
203
 
204
204
  ## Events (Zod v4 schema)
205
205
 
@@ -29,13 +29,13 @@ displays.forEach(d => {
29
29
 
30
30
  | Property | Type | Description |
31
31
  |----------|------|-------------|
32
- | `arch` | `any` | Gets the operating system CPU architecture. |
33
- | `tmpdir` | `any` | Gets the operating system's default directory for temporary files. |
34
- | `homedir` | `any` | Gets the current user's home directory path. |
35
- | `cpuCount` | `any` | Gets the number of logical CPU cores available on the system. |
36
- | `hostname` | `any` | Gets the hostname of the operating system. |
37
- | `platform` | `any` | Gets the operating system platform. |
38
- | `networkInterfaces` | `any` | Gets information about the system's network interfaces. |
32
+ | `arch` | `string` | Gets the operating system CPU architecture. |
33
+ | `tmpdir` | `string` | Gets the operating system's default directory for temporary files. |
34
+ | `homedir` | `string` | Gets the current user's home directory path. |
35
+ | `cpuCount` | `number` | Gets the number of logical CPU cores available on the system. |
36
+ | `hostname` | `string` | Gets the hostname of the operating system. |
37
+ | `platform` | `string` | Gets the operating system platform. |
38
+ | `networkInterfaces` | `NodeJS.Dict<os.NetworkInterfaceInfo[]>` | Gets information about the system's network interfaces. |
39
39
  | `macAddresses` | `string[]` | Gets an array of MAC addresses for non-internal IPv4 network interfaces. This filters the network interfaces to only include external IPv4 interfaces and returns their MAC addresses, which can be useful for system identification. |
40
40
 
41
41
  ## State (Zod v4 schema)
@@ -57,7 +57,7 @@ finder.addPackage({
57
57
 
58
58
  Starts the package finder and performs the initial workspace scan. This method is idempotent - calling it multiple times will not re-scan if already started. It triggers the complete workspace scanning process.
59
59
 
60
- **Returns:** `void`
60
+ **Returns:** `Promise<this | undefined>`
61
61
 
62
62
  ```ts
63
63
  await finder.start();
@@ -82,7 +82,7 @@ Performs a comprehensive scan of all node_modules directories in the workspace.
82
82
  |----------|------|-------------|
83
83
  | `exclude` | `any` | Optional exclusion patterns (not implemented) |
84
84
 
85
- **Returns:** `void`
85
+ **Returns:** `Promise<this>`
86
86
 
87
87
  ```ts
88
88
  // Manual scan (usually called automatically by start())
@@ -104,7 +104,7 @@ Finds the first package manifest matching the given name. If multiple versions o
104
104
  |------|------|----------|-------------|
105
105
  | `name` | `string` | ✓ | The exact package name to search for |
106
106
 
107
- **Returns:** `void`
107
+ **Returns:** `PartialManifest | undefined`
108
108
 
109
109
  ```ts
110
110
  const lodash = finder.findByName('lodash');
@@ -125,7 +125,7 @@ Finds all packages that declare the specified package as a dependency. Searches
125
125
  |------|------|----------|-------------|
126
126
  | `packageName` | `string` | ✓ | The name of the package to find dependents for |
127
127
 
128
- **Returns:** `void`
128
+ **Returns:** `PartialManifest[]`
129
129
 
130
130
  ```ts
131
131
  const reactDependents = finder.findDependentsOf('react');
@@ -147,7 +147,7 @@ Finds the first package manifest matching the provided filter function.
147
147
  |------|------|----------|-------------|
148
148
  | `filter` | `(manifest: PartialManifest) => boolean` | ✓ | Function that returns true for matching packages |
149
149
 
150
- **Returns:** `void`
150
+ **Returns:** `PartialManifest | undefined`
151
151
 
152
152
  ```ts
153
153
  // Find a package with specific version
@@ -169,7 +169,7 @@ Finds all package manifests matching the provided filter function.
169
169
  |------|------|----------|-------------|
170
170
  | `filter` | `(manifest: PartialManifest) => boolean` | ✓ | Function that returns true for matching packages |
171
171
 
172
- **Returns:** `void`
172
+ **Returns:** `PartialManifest[]`
173
173
 
174
174
  ```ts
175
175
  // Find all packages with 'babel' in the name
@@ -194,7 +194,7 @@ Returns all packages that do NOT match the provided filter function. This is the
194
194
  |------|------|----------|-------------|
195
195
  | `filter` | `(manifest: PartialManifest) => boolean` | ✓ | Function that returns true for packages to exclude |
196
196
 
197
- **Returns:** `void`
197
+ **Returns:** `PartialManifest[]`
198
198
 
199
199
  ```ts
200
200
  // Get all non-development packages (those not in devDependencies)
@@ -208,7 +208,7 @@ const unscoped = finder.exclude(pkg => pkg.name.startsWith('@'));
208
208
 
209
209
  ### findLocalPackageFolders
210
210
 
211
- **Returns:** `void`
211
+ **Returns:** `Promise<string[]>`
212
212
 
213
213
 
214
214
 
@@ -216,12 +216,12 @@ const unscoped = finder.exclude(pkg => pkg.name.startsWith('@'));
216
216
 
217
217
  | Property | Type | Description |
218
218
  |----------|------|-------------|
219
- | `duplicates` | `any` | Gets a list of package names that have multiple versions/instances installed. This is useful for identifying potential dependency conflicts or opportunities for deduplication in the project. |
220
- | `isStarted` | `any` | Checks if the package finder has completed its initial scan. |
221
- | `packageNames` | `any` | Gets an array of all unique package names discovered in the workspace. |
222
- | `scopes` | `any` | Gets an array of all scoped package prefixes found in the workspace. Scoped packages are those starting with '@' (e.g., @types/node, @babel/core). This returns just the scope part (e.g., '@types', '@babel'). |
223
- | `manifests` | `any` | Gets a flat array of all package manifests found in the workspace. This includes all versions/instances of packages, unlike packageNames which returns unique names only. |
224
- | `counts` | `any` | Gets a count of instances for each package name. Useful for quickly identifying which packages have multiple versions and how many instances of each exist. |
219
+ | `duplicates` | `string[]` | Gets a list of package names that have multiple versions/instances installed. This is useful for identifying potential dependency conflicts or opportunities for deduplication in the project. |
220
+ | `isStarted` | `boolean` | Checks if the package finder has completed its initial scan. |
221
+ | `packageNames` | `string[]` | Gets an array of all unique package names discovered in the workspace. |
222
+ | `scopes` | `string[]` | Gets an array of all scoped package prefixes found in the workspace. Scoped packages are those starting with '@' (e.g., @types/node, @babel/core). This returns just the scope part (e.g., '@types', '@babel'). |
223
+ | `manifests` | `(PartialManifest & { __path: string })[]` | Gets a flat array of all package manifests found in the workspace. This includes all versions/instances of packages, unlike packageNames which returns unique names only. |
224
+ | `counts` | `Record<string, number>` | Gets a count of instances for each package name. Useful for quickly identifying which packages have multiple versions and how many instances of each exist. |
225
225
 
226
226
  ## State (Zod v4 schema)
227
227
 
@@ -70,6 +70,7 @@ Spawns a process and captures its output with real-time monitoring capabilities.
70
70
  | `onError` | `(data: string) => void` | Callback invoked when stderr data is received |
71
71
  | `onOutput` | `(data: string) => void` | Callback invoked when stdout data is received |
72
72
  | `onExit` | `(code: number) => void` | Callback invoked when the process exits |
73
+ | `onStart` | `(childProcess: ChildProcess) => void` | Callback invoked when the process starts |
73
74
 
74
75
  **Returns:** `Promise<{
75
76
  stderr: string;
@@ -126,7 +127,7 @@ Spawn a raw child process and return the handle immediately. Useful when callers
126
127
  | `stdout` | `"pipe" | "inherit" | "ignore"` | Stdout mode for the child process |
127
128
  | `stderr` | `"pipe" | "inherit" | "ignore"` | Stderr mode for the child process |
128
129
 
129
- **Returns:** `void`
130
+ **Returns:** `import('child_process').ChildProcess`
130
131
 
131
132
 
132
133
 
@@ -1,6 +1,6 @@
1
1
  # ProcessManager (features.processManager)
2
2
 
3
- Manages long-running child processes with tracking, events, and automatic cleanup. Unlike the `proc` feature whose spawn methods block until the child exits, ProcessManager returns a SpawnHandler immediately — a handle object with its own state, events, and lifecycle methods. The feature tracks all spawned processes, maintains observable state, and can automatically kill them on parent exit.
3
+ Manages long-running child processes with tracking, events, and automatic cleanup. Unlike the `proc` feature whose spawn methods block until the child exits, ProcessManager returns a SpawnHandler immediately — a handle object with its own state, events, and lifecycle methods. The feature tracks all spawned processes, maintains observable state, and can automatically kill them on parent exit. Each handler maintains a memory-efficient output buffer: the first 20 lines (head) and last 50 lines (tail) of stdout/stderr are kept, everything in between is discarded.
4
4
 
5
5
  ## Usage
6
6
 
@@ -19,6 +19,70 @@ container.feature('processManager', {
19
19
 
20
20
  ## Methods
21
21
 
22
+ ### spawnProcess
23
+
24
+ Tool handler: spawn a long-running background process.
25
+
26
+ **Parameters:**
27
+
28
+ | Name | Type | Required | Description |
29
+ |------|------|----------|-------------|
30
+ | `args` | `{ command: string; args?: string; tag?: string; cwd?: string }` | ✓ | Parameter args |
31
+
32
+ **Returns:** `void`
33
+
34
+
35
+
36
+ ### runCommand
37
+
38
+ Tool handler: run a command to completion and return its output.
39
+
40
+ **Parameters:**
41
+
42
+ | Name | Type | Required | Description |
43
+ |------|------|----------|-------------|
44
+ | `args` | `{ command: string; cwd?: string }` | ✓ | Parameter args |
45
+
46
+ **Returns:** `void`
47
+
48
+
49
+
50
+ ### listProcesses
51
+
52
+ Tool handler: list all tracked processes.
53
+
54
+ **Returns:** `void`
55
+
56
+
57
+
58
+ ### getProcessOutput
59
+
60
+ Tool handler: peek at a process's buffered output.
61
+
62
+ **Parameters:**
63
+
64
+ | Name | Type | Required | Description |
65
+ |------|------|----------|-------------|
66
+ | `args` | `{ id?: string; tag?: string; stream?: string }` | ✓ | Parameter args |
67
+
68
+ **Returns:** `void`
69
+
70
+
71
+
72
+ ### killProcess
73
+
74
+ Tool handler: kill a process by ID or tag.
75
+
76
+ **Parameters:**
77
+
78
+ | Name | Type | Required | Description |
79
+ |------|------|----------|-------------|
80
+ | `args` | `{ id?: string; tag?: string; signal?: string }` | ✓ | Parameter args |
81
+
82
+ **Returns:** `void`
83
+
84
+
85
+
22
86
  ### spawn
23
87
 
24
88
  Spawn a long-running process and return a handle immediately. The returned SpawnHandler provides events for stdout/stderr streaming, exit/crash notifications, and methods to kill or await the process.
@@ -157,7 +221,7 @@ Emitted when a new process is spawned
157
221
  | Name | Type | Description |
158
222
  |------|------|-------------|
159
223
  | `arg0` | `string` | process ID |
160
- | `arg1` | `any` | process metadata |
224
+ | `arg1` | `string` | process metadata |
161
225
 
162
226
 
163
227
 
@@ -184,7 +248,7 @@ Emitted when a process exits with non-zero code
184
248
  |------|------|-------------|
185
249
  | `arg0` | `string` | process ID |
186
250
  | `arg1` | `number` | exit code |
187
- | `arg2` | `any` | error info |
251
+ | `arg2` | `string` | error info |
188
252
 
189
253
 
190
254
 
@@ -225,6 +289,9 @@ const server = pm.spawn('node', ['server.js'], { tag: 'api', cwd: '/app' })
225
289
  server.on('stdout', (data) => console.log('[api]', data))
226
290
  server.on('crash', (code) => console.error('API crashed:', code))
227
291
 
292
+ // Peek at buffered output
293
+ const { head, tail } = server.peek()
294
+
228
295
  // Kill one
229
296
  server.kill()
230
297