@soederpop/luca 0.0.26 → 0.0.29

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.
@@ -1,7 +1,7 @@
1
1
  import { setBuildTimeData, setContainerBuildTimeData } from './index.js';
2
2
 
3
3
  // Auto-generated introspection registry data
4
- // Generated at: 2026-03-22T20:57:23.197Z
4
+ // Generated at: 2026-03-24T01:41:39.242Z
5
5
 
6
6
  setBuildTimeData('features.googleDocs', {
7
7
  "id": "features.googleDocs",
@@ -1525,7 +1525,7 @@ setBuildTimeData('features.downloader', {
1525
1525
 
1526
1526
  setBuildTimeData('features.windowManager', {
1527
1527
  "id": "features.windowManager",
1528
- "description": "WindowManager Feature — Native window control via LucaVoiceLauncher Acts as an IPC server that the native macOS launcher app connects to. Communicates over a Unix domain socket using NDJSON (newline-delimited JSON). **Protocol:** - Bun listens on a Unix domain socket; the native app connects as a client - Window dispatch commands are sent as NDJSON with a `window` field - The app executes window commands and sends back `windowAck` messages - Any non-windowAck message from the app is emitted as a `message` event - Other features can use `send()` to write arbitrary NDJSON to the app **Capabilities:** - Spawn native browser windows with configurable chrome - Navigate, focus, close, and eval JavaScript in windows - Automatic socket file cleanup and fallback paths",
1528
+ "description": "WindowManager Feature — Native window control via LucaVoiceLauncher Uses a broker/producer architecture so multiple luca processes can trigger window operations without competing for the same Unix socket. **Architecture:** - The first process to call `listen()` becomes the **broker**. It owns the app-facing socket (`ipc-window.sock`) and a control socket (`ipc-window-control.sock`). - Subsequent processes detect the broker and become **producers**. They connect to the control socket and route commands through the broker. - The broker forwards producer commands to the native app and routes acks and lifecycle events back to the originating producer. **Protocol:** - Bun listens on a Unix domain socket; the native app connects as a client - Window dispatch commands are sent as NDJSON with a `window` field - The app executes window commands and sends back `windowAck` messages - Any non-windowAck message from the app is emitted as a `message` event - Other features can use `send()` to write arbitrary NDJSON to the app **Capabilities:** - Spawn native browser windows with configurable chrome - Navigate, focus, close, and eval JavaScript in windows - Multiple luca processes can trigger window operations simultaneously - Automatic broker detection and producer fallback Observable state includes `windows` (open window metadata), `pendingOperations` (in-flight command ids), and `producerCount` (broker). Sockets, promises, and `WindowHandle` instances stay internal. **Producer state:** The broker pushes `windowStateSync` on the control socket when a producer connects and whenever the window roster changes, so every process sees the same `windows` / `windowCount` / `clientConnected` as the broker (not only its own acks).",
1529
1529
  "shortcut": "features.windowManager",
1530
1530
  "className": "WindowManager",
1531
1531
  "methods": {
@@ -1541,7 +1541,18 @@ setBuildTimeData('features.windowManager', {
1541
1541
  "returns": "Promise<this>"
1542
1542
  },
1543
1543
  "listen": {
1544
- "description": "Start listening on the Unix domain socket for the native app to connect. Fire-and-forget binds the socket and returns immediately. Sits quietly until the native app connects; does nothing visible if it never does.",
1544
+ "description": "Start the window manager. Automatically detects whether a broker already exists and either becomes the broker or connects as a producer. - If no broker is running: becomes the broker, binds the app socket and a control socket for producers. - If a broker is already running: connects as a producer through the control socket.",
1545
+ "parameters": {
1546
+ "socketPath": {
1547
+ "type": "string",
1548
+ "description": "Override the configured app socket path"
1549
+ }
1550
+ },
1551
+ "required": [],
1552
+ "returns": "Promise<this>"
1553
+ },
1554
+ "cleanupSocket": {
1555
+ "description": "Remove stale socket files without starting or stopping the server. Useful when a previous process crashed and left dead sockets behind. Will not remove sockets that have live listeners.",
1545
1556
  "parameters": {
1546
1557
  "socketPath": {
1547
1558
  "type": "string",
@@ -1549,10 +1560,10 @@ setBuildTimeData('features.windowManager', {
1549
1560
  }
1550
1561
  },
1551
1562
  "required": [],
1552
- "returns": "this"
1563
+ "returns": "Promise<boolean>"
1553
1564
  },
1554
1565
  "stop": {
1555
- "description": "Stop the IPC server and clean up all connections. Rejects any pending window operation requests.",
1566
+ "description": "Stop the window manager and clean up all connections. Rejects any pending window operation requests.",
1556
1567
  "parameters": {},
1557
1568
  "required": [],
1558
1569
  "returns": "Promise<this>"
@@ -1825,7 +1836,7 @@ setBuildTimeData('features.windowManager', {
1825
1836
  ]
1826
1837
  },
1827
1838
  "send": {
1828
- "description": "Write an NDJSON message to the connected app client. Public so other features can send arbitrary protocol messages over the same socket.",
1839
+ "description": "Write an NDJSON message to the connected app client. In producer mode, routes through the broker. Public so other features can send arbitrary protocol messages over the same socket.",
1829
1840
  "parameters": {
1830
1841
  "msg": {
1831
1842
  "type": "Record<string, any>",
@@ -1839,12 +1850,20 @@ setBuildTimeData('features.windowManager', {
1839
1850
  }
1840
1851
  },
1841
1852
  "getters": {
1853
+ "isBroker": {
1854
+ "description": "Whether this instance is acting as the broker.",
1855
+ "returns": "boolean"
1856
+ },
1857
+ "isProducer": {
1858
+ "description": "Whether this instance is acting as a producer.",
1859
+ "returns": "boolean"
1860
+ },
1842
1861
  "isListening": {
1843
- "description": "Whether the IPC server is currently listening.",
1862
+ "description": "Whether the IPC server is currently listening (broker) or connected to broker (producer).",
1844
1863
  "returns": "boolean"
1845
1864
  },
1846
1865
  "isClientConnected": {
1847
- "description": "Whether the native app client is currently connected.",
1866
+ "description": "Whether the native app client is currently connected (only meaningful for broker).",
1848
1867
  "returns": "boolean"
1849
1868
  }
1850
1869
  },
@@ -1879,6 +1898,11 @@ setBuildTimeData('features.windowManager', {
1879
1898
  "description": "Event emitted by WindowManager",
1880
1899
  "arguments": {}
1881
1900
  },
1901
+ "windowFocus": {
1902
+ "name": "windowFocus",
1903
+ "description": "Event emitted by WindowManager",
1904
+ "arguments": {}
1905
+ },
1882
1906
  "message": {
1883
1907
  "name": "message",
1884
1908
  "description": "Event emitted by WindowManager",
@@ -5749,6 +5773,32 @@ setBuildTimeData('features.fs', {
5749
5773
  }
5750
5774
  ]
5751
5775
  },
5776
+ "isSymlink": {
5777
+ "description": "Checks if a path is a symbolic link.",
5778
+ "parameters": {
5779
+ "path": {
5780
+ "type": "string",
5781
+ "description": "The path to check"
5782
+ }
5783
+ },
5784
+ "required": [
5785
+ "path"
5786
+ ],
5787
+ "returns": "boolean"
5788
+ },
5789
+ "realpath": {
5790
+ "description": "Resolves a symlink to its real path. Returns the resolved path as-is if not a symlink.",
5791
+ "parameters": {
5792
+ "path": {
5793
+ "type": "string",
5794
+ "description": "The path to resolve"
5795
+ }
5796
+ },
5797
+ "required": [
5798
+ "path"
5799
+ ],
5800
+ "returns": "string"
5801
+ },
5752
5802
  "stat": {
5753
5803
  "description": "Synchronously returns the stat object for a file or directory.",
5754
5804
  "parameters": {
@@ -6223,7 +6273,7 @@ setBuildTimeData('features.fs', {
6223
6273
 
6224
6274
  setBuildTimeData('features.ipcSocket', {
6225
6275
  "id": "features.ipcSocket",
6226
- "description": "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' }); ```",
6276
+ "description": "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 }); }); ```",
6227
6277
  "shortcut": "features.ipcSocket",
6228
6278
  "className": "IpcSocket",
6229
6279
  "methods": {
@@ -6263,61 +6313,127 @@ setBuildTimeData('features.ipcSocket', {
6263
6313
  ]
6264
6314
  },
6265
6315
  "broadcast": {
6266
- "description": "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>\" } ```",
6316
+ "description": "Broadcasts a message to all connected clients (server mode only).",
6267
6317
  "parameters": {
6268
6318
  "message": {
6269
6319
  "type": "any",
6270
- "description": "The message object to broadcast to all clients"
6320
+ "description": "The message object to broadcast"
6321
+ },
6322
+ "exclude": {
6323
+ "type": "string",
6324
+ "description": "Optional client ID to exclude from broadcast"
6271
6325
  }
6272
6326
  },
6273
6327
  "required": [
6274
6328
  "message"
6275
6329
  ],
6276
- "returns": "void",
6277
- "examples": [
6278
- {
6279
- "language": "ts",
6280
- "code": "// Broadcast to all connected clients\nipc.broadcast({ \n type: 'notification',\n message: 'Server is shutting down in 30 seconds',\n timestamp: Date.now()\n});\n\n// Chain multiple operations\nipc.broadcast({ status: 'ready' })\n .broadcast({ time: new Date().toISOString() });"
6330
+ "returns": "void"
6331
+ },
6332
+ "sendTo": {
6333
+ "description": "Sends a message to a specific client by ID (server mode only).",
6334
+ "parameters": {
6335
+ "clientId": {
6336
+ "type": "string",
6337
+ "description": "The target client ID"
6338
+ },
6339
+ "message": {
6340
+ "type": "any",
6341
+ "description": "The message to send"
6281
6342
  }
6282
- ]
6343
+ },
6344
+ "required": [
6345
+ "clientId",
6346
+ "message"
6347
+ ],
6348
+ "returns": "boolean"
6283
6349
  },
6284
6350
  "send": {
6285
- "description": "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>\" } ```",
6351
+ "description": "Fire-and-forget: sends a message to the server (client mode only). For server→client, use sendTo() or broadcast().",
6286
6352
  "parameters": {
6287
6353
  "message": {
6288
6354
  "type": "any",
6289
- "description": "The message object to send to the server"
6355
+ "description": "The message to send"
6290
6356
  }
6291
6357
  },
6292
6358
  "required": [
6293
6359
  "message"
6294
6360
  ],
6295
- "returns": "void",
6296
- "examples": [
6297
- {
6298
- "language": "ts",
6299
- "code": "// Send a simple message\nawait ipc.send({ type: 'ping' });\n\n// Send complex data\nawait ipc.send({\n type: 'data_update',\n payload: { users: [...], timestamp: Date.now() }\n});"
6361
+ "returns": "void"
6362
+ },
6363
+ "ask": {
6364
+ "description": "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.",
6365
+ "parameters": {
6366
+ "message": {
6367
+ "type": "any",
6368
+ "description": "The message to send"
6369
+ },
6370
+ "options": {
6371
+ "type": "{ clientId?: string; timeoutMs?: number }",
6372
+ "description": "Optional: clientId (server mode target), timeoutMs"
6300
6373
  }
6301
- ]
6374
+ },
6375
+ "required": [
6376
+ "message"
6377
+ ],
6378
+ "returns": "Promise<any>"
6379
+ },
6380
+ "reply": {
6381
+ "description": "Sends a reply to a previous ask() call, correlated by requestId.",
6382
+ "parameters": {
6383
+ "requestId": {
6384
+ "type": "string",
6385
+ "description": "The requestId from the incoming message"
6386
+ },
6387
+ "data": {
6388
+ "type": "any",
6389
+ "description": "The reply payload"
6390
+ },
6391
+ "clientId": {
6392
+ "type": "string",
6393
+ "description": "Target client (server mode; for client mode, omit)"
6394
+ }
6395
+ },
6396
+ "required": [
6397
+ "requestId",
6398
+ "data"
6399
+ ],
6400
+ "returns": "void"
6302
6401
  },
6303
6402
  "connect": {
6304
- "description": "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",
6403
+ "description": "Connects to an IPC server at the specified socket path (client mode).",
6305
6404
  "parameters": {
6306
6405
  "socketPath": {
6307
6406
  "type": "string",
6308
- "description": "The file system path to the server's Unix domain socket"
6407
+ "description": "Path to the server's Unix domain socket"
6408
+ },
6409
+ "options": {
6410
+ "type": "{ reconnect?: boolean; name?: string }",
6411
+ "description": "Optional: reconnect (enable auto-reconnect), name (identify this client)"
6309
6412
  }
6310
6413
  },
6311
6414
  "required": [
6312
6415
  "socketPath"
6313
6416
  ],
6314
- "returns": "Promise<Socket>",
6315
- "examples": [
6316
- {
6317
- "language": "ts",
6318
- "code": "// Connect to server\nconst socket = await ipc.connect('/tmp/myapp.sock');\nconsole.log('Connected to IPC server');\n\n// Handle incoming messages\nipc.on('message', (data) => {\n console.log('Server message:', data);\n});\n\n// Send messages\nawait ipc.send({ type: 'hello', client_id: 'client_001' });"
6417
+ "returns": "Promise<Socket>"
6418
+ },
6419
+ "disconnect": {
6420
+ "description": "Disconnects the client and stops any reconnection attempts.",
6421
+ "parameters": {},
6422
+ "required": [],
6423
+ "returns": "void"
6424
+ },
6425
+ "probeSocket": {
6426
+ "description": "Probe an existing socket to see if a live listener is behind it. Attempts a quick connect — if it succeeds, someone is listening.",
6427
+ "parameters": {
6428
+ "socketPath": {
6429
+ "type": "string",
6430
+ "description": "Parameter socketPath"
6319
6431
  }
6320
- ]
6432
+ },
6433
+ "required": [
6434
+ "socketPath"
6435
+ ],
6436
+ "returns": "Promise<boolean>"
6321
6437
  }
6322
6438
  },
6323
6439
  "getters": {
@@ -6329,12 +6445,25 @@ setBuildTimeData('features.ipcSocket', {
6329
6445
  "description": "Checks if the IPC socket is operating in server mode.",
6330
6446
  "returns": "any"
6331
6447
  },
6448
+ "clientCount": {
6449
+ "description": "Returns the number of currently connected clients (server mode).",
6450
+ "returns": "any"
6451
+ },
6452
+ "connectedClients": {
6453
+ "description": "Returns info about all connected clients (server mode).",
6454
+ "returns": "Array<{ id: string; name?: string; connectedAt: number }>"
6455
+ },
6332
6456
  "connection": {
6333
6457
  "description": "Gets the current client connection socket.",
6334
6458
  "returns": "any"
6335
6459
  }
6336
6460
  },
6337
6461
  "events": {
6462
+ "disconnection": {
6463
+ "name": "disconnection",
6464
+ "description": "Event emitted by IpcSocket",
6465
+ "arguments": {}
6466
+ },
6338
6467
  "connection": {
6339
6468
  "name": "connection",
6340
6469
  "description": "Event emitted by IpcSocket",
@@ -7255,10 +7384,68 @@ setBuildTimeData('features.packageFinder', {
7255
7384
 
7256
7385
  setBuildTimeData('features.processManager', {
7257
7386
  "id": "features.processManager",
7258
- "description": "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.",
7387
+ "description": "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.",
7259
7388
  "shortcut": "features.processManager",
7260
7389
  "className": "ProcessManager",
7261
7390
  "methods": {
7391
+ "spawnProcess": {
7392
+ "description": "Tool handler: spawn a long-running background process.",
7393
+ "parameters": {
7394
+ "args": {
7395
+ "type": "{ command: string; args?: string; tag?: string; cwd?: string }",
7396
+ "description": "Parameter args"
7397
+ }
7398
+ },
7399
+ "required": [
7400
+ "args"
7401
+ ],
7402
+ "returns": "void"
7403
+ },
7404
+ "runCommand": {
7405
+ "description": "Tool handler: run a command to completion and return its output.",
7406
+ "parameters": {
7407
+ "args": {
7408
+ "type": "{ command: string; cwd?: string }",
7409
+ "description": "Parameter args"
7410
+ }
7411
+ },
7412
+ "required": [
7413
+ "args"
7414
+ ],
7415
+ "returns": "void"
7416
+ },
7417
+ "listProcesses": {
7418
+ "description": "Tool handler: list all tracked processes.",
7419
+ "parameters": {},
7420
+ "required": [],
7421
+ "returns": "void"
7422
+ },
7423
+ "getProcessOutput": {
7424
+ "description": "Tool handler: peek at a process's buffered output.",
7425
+ "parameters": {
7426
+ "args": {
7427
+ "type": "{ id?: string; tag?: string; stream?: string }",
7428
+ "description": "Parameter args"
7429
+ }
7430
+ },
7431
+ "required": [
7432
+ "args"
7433
+ ],
7434
+ "returns": "void"
7435
+ },
7436
+ "killProcess": {
7437
+ "description": "Tool handler: kill a process by ID or tag.",
7438
+ "parameters": {
7439
+ "args": {
7440
+ "type": "{ id?: string; tag?: string; signal?: string }",
7441
+ "description": "Parameter args"
7442
+ }
7443
+ },
7444
+ "required": [
7445
+ "args"
7446
+ ],
7447
+ "returns": "void"
7448
+ },
7262
7449
  "spawn": {
7263
7450
  "description": "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.",
7264
7451
  "parameters": {
@@ -7436,7 +7623,7 @@ setBuildTimeData('features.processManager', {
7436
7623
  "examples": [
7437
7624
  {
7438
7625
  "language": "ts",
7439
- "code": "const pm = container.feature('processManager', { enable: true })\n\nconst server = pm.spawn('node', ['server.js'], { tag: 'api', cwd: '/app' })\nserver.on('stdout', (data) => console.log('[api]', data))\nserver.on('crash', (code) => console.error('API crashed:', code))\n\n// Kill one\nserver.kill()\n\n// Kill all tracked processes\npm.killAll()\n\n// List and lookup\npm.list() // SpawnHandler[]\npm.getByTag('api') // SpawnHandler | undefined"
7626
+ "code": "const pm = container.feature('processManager', { enable: true })\n\nconst server = pm.spawn('node', ['server.js'], { tag: 'api', cwd: '/app' })\nserver.on('stdout', (data) => console.log('[api]', data))\nserver.on('crash', (code) => console.error('API crashed:', code))\n\n// Peek at buffered output\nconst { head, tail } = server.peek()\n\n// Kill one\nserver.kill()\n\n// Kill all tracked processes\npm.killAll()\n\n// List and lookup\npm.list() // SpawnHandler[]\npm.getByTag('api') // SpawnHandler | undefined"
7440
7627
  }
7441
7628
  ]
7442
7629
  });
@@ -9805,7 +9992,7 @@ setBuildTimeData('clients.rest', {
9805
9992
 
9806
9993
  setBuildTimeData('clients.websocket', {
9807
9994
  "id": "clients.websocket",
9808
- "description": "WebSocket client that bridges raw WebSocket events to Luca's Helper event bus, providing a clean interface for sending/receiving messages, tracking connection state, and optional auto-reconnection with exponential backoff. Events emitted: - `open` — connection established - `message` — message received (JSON-parsed when possible) - `close` — connection closed (with code and reason) - `error` — connection error - `reconnecting` — attempting reconnection (with attempt number)",
9995
+ "description": "WebSocketClient helper",
9809
9996
  "shortcut": "clients.websocket",
9810
9997
  "className": "WebSocketClient",
9811
9998
  "methods": {
@@ -9828,6 +10015,59 @@ setBuildTimeData('clients.websocket', {
9828
10015
  ],
9829
10016
  "returns": "Promise<void>"
9830
10017
  },
10018
+ "ask": {
10019
+ "description": "Send a request and wait for a correlated response. The message is sent with a unique `requestId`; the remote side is expected to reply with a message containing `replyTo` set to that same ID.",
10020
+ "parameters": {
10021
+ "type": {
10022
+ "type": "string",
10023
+ "description": "A string identifying the request type"
10024
+ },
10025
+ "data": {
10026
+ "type": "any",
10027
+ "description": "Optional payload to include with the request"
10028
+ },
10029
+ "timeout": {
10030
+ "type": "any",
10031
+ "description": "How long to wait for a response (default 10 000 ms)"
10032
+ }
10033
+ },
10034
+ "required": [
10035
+ "type"
10036
+ ],
10037
+ "returns": "Promise<R>",
10038
+ "examples": [
10039
+ {
10040
+ "language": "ts",
10041
+ "code": "const result = await ws.ask('getUser', { id: 42 })"
10042
+ }
10043
+ ]
10044
+ },
10045
+ "_handleReply": {
10046
+ "description": "",
10047
+ "parameters": {
10048
+ "message": {
10049
+ "type": "any",
10050
+ "description": "Parameter message"
10051
+ }
10052
+ },
10053
+ "required": [
10054
+ "message"
10055
+ ],
10056
+ "returns": "boolean"
10057
+ },
10058
+ "_rejectAllPending": {
10059
+ "description": "",
10060
+ "parameters": {
10061
+ "reason": {
10062
+ "type": "string",
10063
+ "description": "Parameter reason"
10064
+ }
10065
+ },
10066
+ "required": [
10067
+ "reason"
10068
+ ],
10069
+ "returns": "void"
10070
+ },
9831
10071
  "disconnect": {
9832
10072
  "description": "Gracefully close the WebSocket connection. Suppresses auto-reconnect and updates connection state to disconnected.",
9833
10073
  "parameters": {},
@@ -9870,13 +10110,7 @@ setBuildTimeData('clients.websocket', {
9870
10110
  },
9871
10111
  "state": {},
9872
10112
  "options": {},
9873
- "envVars": [],
9874
- "examples": [
9875
- {
9876
- "language": "ts",
9877
- "code": "const ws = container.client('websocket', {\n baseURL: 'ws://localhost:8080',\n reconnect: true,\n maxReconnectAttempts: 5\n})\nws.on('message', (data) => console.log('Received:', data))\nawait ws.connect()\nawait ws.send({ type: 'hello' })"
9878
- }
9879
- ]
10113
+ "envVars": []
9880
10114
  });
9881
10115
 
9882
10116
  setBuildTimeData('clients.openai', {
@@ -10343,38 +10577,240 @@ setBuildTimeData('clients.supabase', {
10343
10577
  ]
10344
10578
  });
10345
10579
 
10346
- setBuildTimeData('clients.comfyui', {
10347
- "id": "clients.comfyui",
10348
- "description": "ComfyUI client — execute Stable Diffusion workflows via the ComfyUI API. Connects to a ComfyUI instance to queue prompts, track execution via WebSocket or polling, and download generated images. Supports both UI-format and API-format workflows with automatic conversion.",
10349
- "shortcut": "clients.comfyui",
10350
- "className": "ComfyUIClient",
10580
+ setBuildTimeData('clients.elevenlabs', {
10581
+ "id": "clients.elevenlabs",
10582
+ "description": "ElevenLabs client — text-to-speech synthesis via the ElevenLabs REST API. Provides methods for listing voices, listing models, and generating speech audio. Audio is returned as a Buffer; use `say()` for a convenience method that writes to disk.",
10583
+ "shortcut": "clients.elevenlabs",
10584
+ "className": "ElevenLabsClient",
10351
10585
  "methods": {
10352
- "queuePrompt": {
10353
- "description": "Queue a prompt (API-format workflow) for execution.",
10354
- "parameters": {
10355
- "prompt": {
10356
- "type": "Record<string, any>",
10357
- "description": "The API-format workflow object"
10358
- },
10359
- "clientId": {
10360
- "type": "string",
10361
- "description": "Override the client ID for this request"
10362
- }
10363
- },
10364
- "required": [
10365
- "prompt"
10366
- ],
10367
- "returns": "Promise<{ prompt_id: string; number: number }>",
10586
+ "beforeRequest": {
10587
+ "description": "Inject the xi-api-key header before each request.",
10588
+ "parameters": {},
10589
+ "required": [],
10590
+ "returns": "void"
10591
+ },
10592
+ "connect": {
10593
+ "description": "Validate the API key by listing available models.",
10594
+ "parameters": {},
10595
+ "required": [],
10596
+ "returns": "Promise<this>",
10368
10597
  "examples": [
10369
10598
  {
10370
10599
  "language": "ts",
10371
- "code": "const { prompt_id } = await comfy.queuePrompt(apiWorkflow)"
10600
+ "code": "await el.connect()"
10372
10601
  }
10373
10602
  ]
10374
10603
  },
10375
- "getQueue": {
10376
- "description": "Get the current prompt queue status.",
10377
- "parameters": {},
10604
+ "listVoices": {
10605
+ "description": "List available voices with optional search and filtering.",
10606
+ "parameters": {
10607
+ "options": {
10608
+ "type": "{\n search?: string\n category?: string\n voice_type?: string\n page_size?: number\n next_page_token?: string\n }",
10609
+ "description": "Query parameters for filtering voices"
10610
+ }
10611
+ },
10612
+ "required": [],
10613
+ "returns": "Promise<any>",
10614
+ "examples": [
10615
+ {
10616
+ "language": "ts",
10617
+ "code": "const voices = await el.listVoices()\nconst premade = await el.listVoices({ category: 'premade' })"
10618
+ }
10619
+ ]
10620
+ },
10621
+ "getVoice": {
10622
+ "description": "Get details for a single voice.",
10623
+ "parameters": {
10624
+ "voiceId": {
10625
+ "type": "string",
10626
+ "description": "The voice ID to look up"
10627
+ }
10628
+ },
10629
+ "required": [
10630
+ "voiceId"
10631
+ ],
10632
+ "returns": "Promise<any>",
10633
+ "examples": [
10634
+ {
10635
+ "language": "ts",
10636
+ "code": "const voice = await el.getVoice('21m00Tcm4TlvDq8ikWAM')\nconsole.log(voice.name, voice.settings)"
10637
+ }
10638
+ ]
10639
+ },
10640
+ "listModels": {
10641
+ "description": "List available TTS models.",
10642
+ "parameters": {},
10643
+ "required": [],
10644
+ "returns": "Promise<any[]>",
10645
+ "examples": [
10646
+ {
10647
+ "language": "ts",
10648
+ "code": "const models = await el.listModels()\nconsole.log(models.map(m => m.model_id))"
10649
+ }
10650
+ ]
10651
+ },
10652
+ "synthesize": {
10653
+ "description": "Synthesize speech from text, returning audio as a Buffer.",
10654
+ "parameters": {
10655
+ "text": {
10656
+ "type": "string",
10657
+ "description": "The text to convert to speech"
10658
+ },
10659
+ "options": {
10660
+ "type": "SynthesizeOptions",
10661
+ "description": "Voice, model, format, and voice settings overrides",
10662
+ "properties": {
10663
+ "voiceId": {
10664
+ "type": "string",
10665
+ "description": ""
10666
+ },
10667
+ "modelId": {
10668
+ "type": "string",
10669
+ "description": ""
10670
+ },
10671
+ "outputFormat": {
10672
+ "type": "string",
10673
+ "description": ""
10674
+ },
10675
+ "voiceSettings": {
10676
+ "type": "ElevenLabsVoiceSettings",
10677
+ "description": ""
10678
+ },
10679
+ "disableCache": {
10680
+ "type": "boolean",
10681
+ "description": ""
10682
+ }
10683
+ }
10684
+ }
10685
+ },
10686
+ "required": [
10687
+ "text"
10688
+ ],
10689
+ "returns": "Promise<Buffer>",
10690
+ "examples": [
10691
+ {
10692
+ "language": "ts",
10693
+ "code": "const audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data\n\nconst custom = await el.synthesize('Hello', {\n voiceId: '21m00Tcm4TlvDq8ikWAM',\n voiceSettings: { stability: 0.5, similarityBoost: 0.8 }\n})"
10694
+ }
10695
+ ]
10696
+ },
10697
+ "say": {
10698
+ "description": "Synthesize speech and write the audio to a file.",
10699
+ "parameters": {
10700
+ "text": {
10701
+ "type": "string",
10702
+ "description": "The text to convert to speech"
10703
+ },
10704
+ "outputPath": {
10705
+ "type": "string",
10706
+ "description": "File path to write the audio to"
10707
+ },
10708
+ "options": {
10709
+ "type": "SynthesizeOptions",
10710
+ "description": "Voice, model, format, and voice settings overrides",
10711
+ "properties": {
10712
+ "voiceId": {
10713
+ "type": "string",
10714
+ "description": ""
10715
+ },
10716
+ "modelId": {
10717
+ "type": "string",
10718
+ "description": ""
10719
+ },
10720
+ "outputFormat": {
10721
+ "type": "string",
10722
+ "description": ""
10723
+ },
10724
+ "voiceSettings": {
10725
+ "type": "ElevenLabsVoiceSettings",
10726
+ "description": ""
10727
+ },
10728
+ "disableCache": {
10729
+ "type": "boolean",
10730
+ "description": ""
10731
+ }
10732
+ }
10733
+ }
10734
+ },
10735
+ "required": [
10736
+ "text",
10737
+ "outputPath"
10738
+ ],
10739
+ "returns": "Promise<string>",
10740
+ "examples": [
10741
+ {
10742
+ "language": "ts",
10743
+ "code": "const path = await el.say('Hello world', './hello.mp3')\nconsole.log(`Audio saved to ${path}`)"
10744
+ }
10745
+ ]
10746
+ }
10747
+ },
10748
+ "getters": {
10749
+ "apiKey": {
10750
+ "description": "The resolved API key from options or environment.",
10751
+ "returns": "string"
10752
+ }
10753
+ },
10754
+ "events": {
10755
+ "failure": {
10756
+ "name": "failure",
10757
+ "description": "Event emitted by ElevenLabsClient",
10758
+ "arguments": {}
10759
+ },
10760
+ "voices": {
10761
+ "name": "voices",
10762
+ "description": "Event emitted by ElevenLabsClient",
10763
+ "arguments": {}
10764
+ },
10765
+ "speech": {
10766
+ "name": "speech",
10767
+ "description": "Event emitted by ElevenLabsClient",
10768
+ "arguments": {}
10769
+ }
10770
+ },
10771
+ "state": {},
10772
+ "options": {},
10773
+ "envVars": [],
10774
+ "examples": [
10775
+ {
10776
+ "language": "ts",
10777
+ "code": "const el = container.client('elevenlabs')\nawait el.connect()\nconst voices = await el.listVoices()\nconst audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data"
10778
+ }
10779
+ ]
10780
+ });
10781
+
10782
+ setBuildTimeData('clients.comfyui', {
10783
+ "id": "clients.comfyui",
10784
+ "description": "ComfyUI client — execute Stable Diffusion workflows via the ComfyUI API. Connects to a ComfyUI instance to queue prompts, track execution via WebSocket or polling, and download generated images. Supports both UI-format and API-format workflows with automatic conversion.",
10785
+ "shortcut": "clients.comfyui",
10786
+ "className": "ComfyUIClient",
10787
+ "methods": {
10788
+ "queuePrompt": {
10789
+ "description": "Queue a prompt (API-format workflow) for execution.",
10790
+ "parameters": {
10791
+ "prompt": {
10792
+ "type": "Record<string, any>",
10793
+ "description": "The API-format workflow object"
10794
+ },
10795
+ "clientId": {
10796
+ "type": "string",
10797
+ "description": "Override the client ID for this request"
10798
+ }
10799
+ },
10800
+ "required": [
10801
+ "prompt"
10802
+ ],
10803
+ "returns": "Promise<{ prompt_id: string; number: number }>",
10804
+ "examples": [
10805
+ {
10806
+ "language": "ts",
10807
+ "code": "const { prompt_id } = await comfy.queuePrompt(apiWorkflow)"
10808
+ }
10809
+ ]
10810
+ },
10811
+ "getQueue": {
10812
+ "description": "Get the current prompt queue status.",
10813
+ "parameters": {},
10378
10814
  "required": [],
10379
10815
  "returns": "Promise<{ queue_running: any[]; queue_pending: any[] }>"
10380
10816
  },
@@ -10595,221 +11031,19 @@ setBuildTimeData('clients.comfyui', {
10595
11031
  ]
10596
11032
  });
10597
11033
 
10598
- setBuildTimeData('clients.elevenlabs', {
10599
- "id": "clients.elevenlabs",
10600
- "description": "ElevenLabs client text-to-speech synthesis via the ElevenLabs REST API. Provides methods for listing voices, listing models, and generating speech audio. Audio is returned as a Buffer; use `say()` for a convenience method that writes to disk.",
10601
- "shortcut": "clients.elevenlabs",
10602
- "className": "ElevenLabsClient",
11034
+ setBuildTimeData('servers.mcp', {
11035
+ "id": "servers.mcp",
11036
+ "description": "MCP (Model Context Protocol) server for exposing tools, resources, and prompts to AI clients like Claude Code. Uses the low-level MCP SDK Server class directly with Zod 4 native JSON Schema conversion. Register tools, resources, and prompts programmatically, then start the server over stdio (for CLI integration) or HTTP (for remote access).",
11037
+ "shortcut": "servers.mcp",
11038
+ "className": "MCPServer",
10603
11039
  "methods": {
10604
- "beforeRequest": {
10605
- "description": "Inject the xi-api-key header before each request.",
10606
- "parameters": {},
10607
- "required": [],
10608
- "returns": "void"
10609
- },
10610
- "connect": {
10611
- "description": "Validate the API key by listing available models.",
10612
- "parameters": {},
10613
- "required": [],
10614
- "returns": "Promise<this>",
10615
- "examples": [
10616
- {
10617
- "language": "ts",
10618
- "code": "await el.connect()"
10619
- }
10620
- ]
10621
- },
10622
- "listVoices": {
10623
- "description": "List available voices with optional search and filtering.",
11040
+ "tool": {
11041
+ "description": "Register an MCP tool. The tool's Zod schema is converted to JSON Schema for the protocol listing, and used for runtime argument validation. Tool handlers can return a string (auto-wrapped as text content) or a full CallToolResult object for advanced responses (images, errors, etc).",
10624
11042
  "parameters": {
10625
- "options": {
10626
- "type": "{\n search?: string\n category?: string\n voice_type?: string\n page_size?: number\n next_page_token?: string\n }",
10627
- "description": "Query parameters for filtering voices"
10628
- }
10629
- },
10630
- "required": [],
10631
- "returns": "Promise<any>",
10632
- "examples": [
10633
- {
10634
- "language": "ts",
10635
- "code": "const voices = await el.listVoices()\nconst premade = await el.listVoices({ category: 'premade' })"
10636
- }
10637
- ]
10638
- },
10639
- "getVoice": {
10640
- "description": "Get details for a single voice.",
10641
- "parameters": {
10642
- "voiceId": {
10643
- "type": "string",
10644
- "description": "The voice ID to look up"
10645
- }
10646
- },
10647
- "required": [
10648
- "voiceId"
10649
- ],
10650
- "returns": "Promise<any>",
10651
- "examples": [
10652
- {
10653
- "language": "ts",
10654
- "code": "const voice = await el.getVoice('21m00Tcm4TlvDq8ikWAM')\nconsole.log(voice.name, voice.settings)"
10655
- }
10656
- ]
10657
- },
10658
- "listModels": {
10659
- "description": "List available TTS models.",
10660
- "parameters": {},
10661
- "required": [],
10662
- "returns": "Promise<any[]>",
10663
- "examples": [
10664
- {
10665
- "language": "ts",
10666
- "code": "const models = await el.listModels()\nconsole.log(models.map(m => m.model_id))"
10667
- }
10668
- ]
10669
- },
10670
- "synthesize": {
10671
- "description": "Synthesize speech from text, returning audio as a Buffer.",
10672
- "parameters": {
10673
- "text": {
10674
- "type": "string",
10675
- "description": "The text to convert to speech"
10676
- },
10677
- "options": {
10678
- "type": "SynthesizeOptions",
10679
- "description": "Voice, model, format, and voice settings overrides",
10680
- "properties": {
10681
- "voiceId": {
10682
- "type": "string",
10683
- "description": ""
10684
- },
10685
- "modelId": {
10686
- "type": "string",
10687
- "description": ""
10688
- },
10689
- "outputFormat": {
10690
- "type": "string",
10691
- "description": ""
10692
- },
10693
- "voiceSettings": {
10694
- "type": "ElevenLabsVoiceSettings",
10695
- "description": ""
10696
- },
10697
- "disableCache": {
10698
- "type": "boolean",
10699
- "description": ""
10700
- }
10701
- }
10702
- }
10703
- },
10704
- "required": [
10705
- "text"
10706
- ],
10707
- "returns": "Promise<Buffer>",
10708
- "examples": [
10709
- {
10710
- "language": "ts",
10711
- "code": "const audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data\n\nconst custom = await el.synthesize('Hello', {\n voiceId: '21m00Tcm4TlvDq8ikWAM',\n voiceSettings: { stability: 0.5, similarityBoost: 0.8 }\n})"
10712
- }
10713
- ]
10714
- },
10715
- "say": {
10716
- "description": "Synthesize speech and write the audio to a file.",
10717
- "parameters": {
10718
- "text": {
10719
- "type": "string",
10720
- "description": "The text to convert to speech"
10721
- },
10722
- "outputPath": {
10723
- "type": "string",
10724
- "description": "File path to write the audio to"
10725
- },
10726
- "options": {
10727
- "type": "SynthesizeOptions",
10728
- "description": "Voice, model, format, and voice settings overrides",
10729
- "properties": {
10730
- "voiceId": {
10731
- "type": "string",
10732
- "description": ""
10733
- },
10734
- "modelId": {
10735
- "type": "string",
10736
- "description": ""
10737
- },
10738
- "outputFormat": {
10739
- "type": "string",
10740
- "description": ""
10741
- },
10742
- "voiceSettings": {
10743
- "type": "ElevenLabsVoiceSettings",
10744
- "description": ""
10745
- },
10746
- "disableCache": {
10747
- "type": "boolean",
10748
- "description": ""
10749
- }
10750
- }
10751
- }
10752
- },
10753
- "required": [
10754
- "text",
10755
- "outputPath"
10756
- ],
10757
- "returns": "Promise<string>",
10758
- "examples": [
10759
- {
10760
- "language": "ts",
10761
- "code": "const path = await el.say('Hello world', './hello.mp3')\nconsole.log(`Audio saved to ${path}`)"
10762
- }
10763
- ]
10764
- }
10765
- },
10766
- "getters": {
10767
- "apiKey": {
10768
- "description": "The resolved API key from options or environment.",
10769
- "returns": "string"
10770
- }
10771
- },
10772
- "events": {
10773
- "failure": {
10774
- "name": "failure",
10775
- "description": "Event emitted by ElevenLabsClient",
10776
- "arguments": {}
10777
- },
10778
- "voices": {
10779
- "name": "voices",
10780
- "description": "Event emitted by ElevenLabsClient",
10781
- "arguments": {}
10782
- },
10783
- "speech": {
10784
- "name": "speech",
10785
- "description": "Event emitted by ElevenLabsClient",
10786
- "arguments": {}
10787
- }
10788
- },
10789
- "state": {},
10790
- "options": {},
10791
- "envVars": [],
10792
- "examples": [
10793
- {
10794
- "language": "ts",
10795
- "code": "const el = container.client('elevenlabs')\nawait el.connect()\nconst voices = await el.listVoices()\nconst audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data"
10796
- }
10797
- ]
10798
- });
10799
-
10800
- setBuildTimeData('servers.mcp', {
10801
- "id": "servers.mcp",
10802
- "description": "MCP (Model Context Protocol) server for exposing tools, resources, and prompts to AI clients like Claude Code. Uses the low-level MCP SDK Server class directly with Zod 4 native JSON Schema conversion. Register tools, resources, and prompts programmatically, then start the server over stdio (for CLI integration) or HTTP (for remote access).",
10803
- "shortcut": "servers.mcp",
10804
- "className": "MCPServer",
10805
- "methods": {
10806
- "tool": {
10807
- "description": "Register an MCP tool. The tool's Zod schema is converted to JSON Schema for the protocol listing, and used for runtime argument validation. Tool handlers can return a string (auto-wrapped as text content) or a full CallToolResult object for advanced responses (images, errors, etc).",
10808
- "parameters": {
10809
- "name": {
10810
- "type": "string",
10811
- "description": "Unique tool name"
10812
- },
11043
+ "name": {
11044
+ "type": "string",
11045
+ "description": "Unique tool name"
11046
+ },
10813
11047
  "options": {
10814
11048
  "type": "ToolRegistrationOptions",
10815
11049
  "description": "Tool schema, description, and handler",
@@ -11081,7 +11315,7 @@ setBuildTimeData('servers.express', {
11081
11315
 
11082
11316
  setBuildTimeData('servers.websocket', {
11083
11317
  "id": "servers.websocket",
11084
- "description": "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.",
11318
+ "description": "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.",
11085
11319
  "shortcut": "servers.websocket",
11086
11320
  "className": "WebsocketServer",
11087
11321
  "methods": {
@@ -11116,6 +11350,64 @@ setBuildTimeData('servers.websocket', {
11116
11350
  ],
11117
11351
  "returns": "void"
11118
11352
  },
11353
+ "ask": {
11354
+ "description": "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.",
11355
+ "parameters": {
11356
+ "ws": {
11357
+ "type": "any",
11358
+ "description": "The WebSocket client to ask"
11359
+ },
11360
+ "type": {
11361
+ "type": "string",
11362
+ "description": "A string identifying the request type"
11363
+ },
11364
+ "data": {
11365
+ "type": "any",
11366
+ "description": "Optional payload"
11367
+ },
11368
+ "timeout": {
11369
+ "type": "any",
11370
+ "description": "How long to wait (default 10 000 ms)"
11371
+ }
11372
+ },
11373
+ "required": [
11374
+ "ws",
11375
+ "type"
11376
+ ],
11377
+ "returns": "Promise<R>",
11378
+ "examples": [
11379
+ {
11380
+ "language": "ts",
11381
+ "code": "ws.on('connection', async (client) => {\n const info = await ws.ask(client, 'identify')\n console.log('Client says:', info)\n})"
11382
+ }
11383
+ ]
11384
+ },
11385
+ "_handleReply": {
11386
+ "description": "",
11387
+ "parameters": {
11388
+ "message": {
11389
+ "type": "any",
11390
+ "description": "Parameter message"
11391
+ }
11392
+ },
11393
+ "required": [
11394
+ "message"
11395
+ ],
11396
+ "returns": "boolean"
11397
+ },
11398
+ "_rejectAllPending": {
11399
+ "description": "",
11400
+ "parameters": {
11401
+ "reason": {
11402
+ "type": "string",
11403
+ "description": "Parameter reason"
11404
+ }
11405
+ },
11406
+ "required": [
11407
+ "reason"
11408
+ ],
11409
+ "returns": "void"
11410
+ },
11119
11411
  "start": {
11120
11412
  "description": "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.",
11121
11413
  "parameters": {
@@ -11162,7 +11454,7 @@ setBuildTimeData('servers.websocket', {
11162
11454
  "examples": [
11163
11455
  {
11164
11456
  "language": "ts",
11165
- "code": "const ws = container.server('websocket', { json: true })\nawait ws.start({ port: 8080 })\n\nws.on('message', (data, client) => {\n console.log('Received:', data)\n ws.broadcast({ echo: data })\n})"
11457
+ "code": "const ws = container.server('websocket', { json: true })\nawait ws.start({ port: 8080 })\n\nws.on('message', (data, client) => {\n console.log('Received:', data)\n ws.broadcast({ echo: data })\n})\n\n// ask/reply: request info from a connected client\nws.on('connection', async (client) => {\n const info = await ws.ask(client, 'identify')\n console.log('Client says:', info)\n})"
11166
11458
  }
11167
11459
  ]
11168
11460
  });
@@ -11424,6 +11716,10 @@ setBuildTimeData('features.conversation', {
11424
11716
  "maxTokens": {
11425
11717
  "type": "number",
11426
11718
  "description": ""
11719
+ },
11720
+ "schema": {
11721
+ "type": "z.ZodType",
11722
+ "description": "When provided, enables OpenAI Structured Outputs. The model is constrained to return JSON matching this Zod schema. The return value of ask() will be the parsed object instead of a raw string."
11427
11723
  }
11428
11724
  }
11429
11725
  }
@@ -11541,6 +11837,21 @@ setBuildTimeData('features.conversation', {
11541
11837
  "description": "Event emitted by Conversation",
11542
11838
  "arguments": {}
11543
11839
  },
11840
+ "toolError": {
11841
+ "name": "toolError",
11842
+ "description": "Event emitted by Conversation",
11843
+ "arguments": {}
11844
+ },
11845
+ "toolCall": {
11846
+ "name": "toolCall",
11847
+ "description": "Event emitted by Conversation",
11848
+ "arguments": {}
11849
+ },
11850
+ "toolResult": {
11851
+ "name": "toolResult",
11852
+ "description": "Event emitted by Conversation",
11853
+ "arguments": {}
11854
+ },
11544
11855
  "turnStart": {
11545
11856
  "name": "turnStart",
11546
11857
  "description": "Event emitted by Conversation",
@@ -11576,33 +11887,18 @@ setBuildTimeData('features.conversation', {
11576
11887
  "description": "Event emitted by Conversation",
11577
11888
  "arguments": {}
11578
11889
  },
11579
- "toolError": {
11580
- "name": "toolError",
11890
+ "toolCallsEnd": {
11891
+ "name": "toolCallsEnd",
11581
11892
  "description": "Event emitted by Conversation",
11582
11893
  "arguments": {}
11583
11894
  },
11584
- "toolCall": {
11585
- "name": "toolCall",
11895
+ "turnEnd": {
11896
+ "name": "turnEnd",
11586
11897
  "description": "Event emitted by Conversation",
11587
11898
  "arguments": {}
11588
11899
  },
11589
- "toolResult": {
11590
- "name": "toolResult",
11591
- "description": "Event emitted by Conversation",
11592
- "arguments": {}
11593
- },
11594
- "toolCallsEnd": {
11595
- "name": "toolCallsEnd",
11596
- "description": "Event emitted by Conversation",
11597
- "arguments": {}
11598
- },
11599
- "turnEnd": {
11600
- "name": "turnEnd",
11601
- "description": "Event emitted by Conversation",
11602
- "arguments": {}
11603
- },
11604
- "response": {
11605
- "name": "response",
11900
+ "response": {
11901
+ "name": "response",
11606
11902
  "description": "Event emitted by Conversation",
11607
11903
  "arguments": {}
11608
11904
  }
@@ -12010,12 +12306,61 @@ setBuildTimeData('features.assistant', {
12010
12306
  "shortcut": "features.assistant",
12011
12307
  "className": "Assistant",
12012
12308
  "methods": {
12309
+ "intercept": {
12310
+ "description": "Register an interceptor at a given point in the pipeline.",
12311
+ "parameters": {
12312
+ "point": {
12313
+ "type": "K",
12314
+ "description": "The interception point"
12315
+ },
12316
+ "fn": {
12317
+ "type": "InterceptorFn<InterceptorPoints[K]>",
12318
+ "description": "Middleware function receiving (ctx, next)"
12319
+ }
12320
+ },
12321
+ "required": [
12322
+ "point",
12323
+ "fn"
12324
+ ],
12325
+ "returns": "this"
12326
+ },
12013
12327
  "afterInitialize": {
12014
12328
  "description": "Called immediately after the assistant is constructed. Synchronously loads the system prompt, tools, and hooks, then binds hooks as event listeners so every emitted event automatically invokes its corresponding hook.",
12015
12329
  "parameters": {},
12016
12330
  "required": [],
12017
12331
  "returns": "void"
12018
12332
  },
12333
+ "addSystemPromptExtension": {
12334
+ "description": "Add or update a named system prompt extension. The value is appended to the base system prompt when passed to the conversation.",
12335
+ "parameters": {
12336
+ "key": {
12337
+ "type": "string",
12338
+ "description": "A unique identifier for this extension"
12339
+ },
12340
+ "value": {
12341
+ "type": "string",
12342
+ "description": "The text to append"
12343
+ }
12344
+ },
12345
+ "required": [
12346
+ "key",
12347
+ "value"
12348
+ ],
12349
+ "returns": "this"
12350
+ },
12351
+ "removeSystemPromptExtension": {
12352
+ "description": "Remove a named system prompt extension.",
12353
+ "parameters": {
12354
+ "key": {
12355
+ "type": "string",
12356
+ "description": "The identifier of the extension to remove"
12357
+ }
12358
+ },
12359
+ "required": [
12360
+ "key"
12361
+ ],
12362
+ "returns": "this"
12363
+ },
12019
12364
  "use": {
12020
12365
  "description": "Apply a setup function or a Helper instance to this assistant. When passed a function, it receives the assistant and can configure tools, hooks, event listeners, etc. When passed a Helper instance that exposes tools via toTools(), those tools are automatically added to this assistant.",
12021
12366
  "parameters": {
@@ -12286,6 +12631,14 @@ setBuildTimeData('features.assistant', {
12286
12631
  "description": "The current system prompt text.",
12287
12632
  "returns": "string"
12288
12633
  },
12634
+ "systemPromptExtensions": {
12635
+ "description": "The named extensions appended to the system prompt.",
12636
+ "returns": "Record<string, string>"
12637
+ },
12638
+ "effectiveSystemPrompt": {
12639
+ "description": "The system prompt with all extensions appended. This is the value passed to the conversation.",
12640
+ "returns": "string"
12641
+ },
12289
12642
  "tools": {
12290
12643
  "description": "The tools registered with this assistant.",
12291
12644
  "returns": "Record<string, ConversationTool>"
@@ -12329,6 +12682,11 @@ setBuildTimeData('features.assistant', {
12329
12682
  "description": "Event emitted by Assistant",
12330
12683
  "arguments": {}
12331
12684
  },
12685
+ "systemPromptExtensionsChanged": {
12686
+ "name": "systemPromptExtensionsChanged",
12687
+ "description": "Event emitted by Assistant",
12688
+ "arguments": {}
12689
+ },
12332
12690
  "toolsChanged": {
12333
12691
  "name": "toolsChanged",
12334
12692
  "description": "Event emitted by Assistant",
@@ -15653,7 +16011,7 @@ export const introspectionData = [
15653
16011
  },
15654
16012
  {
15655
16013
  "id": "features.windowManager",
15656
- "description": "WindowManager Feature — Native window control via LucaVoiceLauncher Acts as an IPC server that the native macOS launcher app connects to. Communicates over a Unix domain socket using NDJSON (newline-delimited JSON). **Protocol:** - Bun listens on a Unix domain socket; the native app connects as a client - Window dispatch commands are sent as NDJSON with a `window` field - The app executes window commands and sends back `windowAck` messages - Any non-windowAck message from the app is emitted as a `message` event - Other features can use `send()` to write arbitrary NDJSON to the app **Capabilities:** - Spawn native browser windows with configurable chrome - Navigate, focus, close, and eval JavaScript in windows - Automatic socket file cleanup and fallback paths",
16014
+ "description": "WindowManager Feature — Native window control via LucaVoiceLauncher Uses a broker/producer architecture so multiple luca processes can trigger window operations without competing for the same Unix socket. **Architecture:** - The first process to call `listen()` becomes the **broker**. It owns the app-facing socket (`ipc-window.sock`) and a control socket (`ipc-window-control.sock`). - Subsequent processes detect the broker and become **producers**. They connect to the control socket and route commands through the broker. - The broker forwards producer commands to the native app and routes acks and lifecycle events back to the originating producer. **Protocol:** - Bun listens on a Unix domain socket; the native app connects as a client - Window dispatch commands are sent as NDJSON with a `window` field - The app executes window commands and sends back `windowAck` messages - Any non-windowAck message from the app is emitted as a `message` event - Other features can use `send()` to write arbitrary NDJSON to the app **Capabilities:** - Spawn native browser windows with configurable chrome - Navigate, focus, close, and eval JavaScript in windows - Multiple luca processes can trigger window operations simultaneously - Automatic broker detection and producer fallback Observable state includes `windows` (open window metadata), `pendingOperations` (in-flight command ids), and `producerCount` (broker). Sockets, promises, and `WindowHandle` instances stay internal. **Producer state:** The broker pushes `windowStateSync` on the control socket when a producer connects and whenever the window roster changes, so every process sees the same `windows` / `windowCount` / `clientConnected` as the broker (not only its own acks).",
15657
16015
  "shortcut": "features.windowManager",
15658
16016
  "className": "WindowManager",
15659
16017
  "methods": {
@@ -15669,7 +16027,18 @@ export const introspectionData = [
15669
16027
  "returns": "Promise<this>"
15670
16028
  },
15671
16029
  "listen": {
15672
- "description": "Start listening on the Unix domain socket for the native app to connect. Fire-and-forget binds the socket and returns immediately. Sits quietly until the native app connects; does nothing visible if it never does.",
16030
+ "description": "Start the window manager. Automatically detects whether a broker already exists and either becomes the broker or connects as a producer. - If no broker is running: becomes the broker, binds the app socket and a control socket for producers. - If a broker is already running: connects as a producer through the control socket.",
16031
+ "parameters": {
16032
+ "socketPath": {
16033
+ "type": "string",
16034
+ "description": "Override the configured app socket path"
16035
+ }
16036
+ },
16037
+ "required": [],
16038
+ "returns": "Promise<this>"
16039
+ },
16040
+ "cleanupSocket": {
16041
+ "description": "Remove stale socket files without starting or stopping the server. Useful when a previous process crashed and left dead sockets behind. Will not remove sockets that have live listeners.",
15673
16042
  "parameters": {
15674
16043
  "socketPath": {
15675
16044
  "type": "string",
@@ -15677,10 +16046,10 @@ export const introspectionData = [
15677
16046
  }
15678
16047
  },
15679
16048
  "required": [],
15680
- "returns": "this"
16049
+ "returns": "Promise<boolean>"
15681
16050
  },
15682
16051
  "stop": {
15683
- "description": "Stop the IPC server and clean up all connections. Rejects any pending window operation requests.",
16052
+ "description": "Stop the window manager and clean up all connections. Rejects any pending window operation requests.",
15684
16053
  "parameters": {},
15685
16054
  "required": [],
15686
16055
  "returns": "Promise<this>"
@@ -15953,7 +16322,7 @@ export const introspectionData = [
15953
16322
  ]
15954
16323
  },
15955
16324
  "send": {
15956
- "description": "Write an NDJSON message to the connected app client. Public so other features can send arbitrary protocol messages over the same socket.",
16325
+ "description": "Write an NDJSON message to the connected app client. In producer mode, routes through the broker. Public so other features can send arbitrary protocol messages over the same socket.",
15957
16326
  "parameters": {
15958
16327
  "msg": {
15959
16328
  "type": "Record<string, any>",
@@ -15967,12 +16336,20 @@ export const introspectionData = [
15967
16336
  }
15968
16337
  },
15969
16338
  "getters": {
16339
+ "isBroker": {
16340
+ "description": "Whether this instance is acting as the broker.",
16341
+ "returns": "boolean"
16342
+ },
16343
+ "isProducer": {
16344
+ "description": "Whether this instance is acting as a producer.",
16345
+ "returns": "boolean"
16346
+ },
15970
16347
  "isListening": {
15971
- "description": "Whether the IPC server is currently listening.",
16348
+ "description": "Whether the IPC server is currently listening (broker) or connected to broker (producer).",
15972
16349
  "returns": "boolean"
15973
16350
  },
15974
16351
  "isClientConnected": {
15975
- "description": "Whether the native app client is currently connected.",
16352
+ "description": "Whether the native app client is currently connected (only meaningful for broker).",
15976
16353
  "returns": "boolean"
15977
16354
  }
15978
16355
  },
@@ -16007,6 +16384,11 @@ export const introspectionData = [
16007
16384
  "description": "Event emitted by WindowManager",
16008
16385
  "arguments": {}
16009
16386
  },
16387
+ "windowFocus": {
16388
+ "name": "windowFocus",
16389
+ "description": "Event emitted by WindowManager",
16390
+ "arguments": {}
16391
+ },
16010
16392
  "message": {
16011
16393
  "name": "message",
16012
16394
  "description": "Event emitted by WindowManager",
@@ -19857,6 +20239,32 @@ export const introspectionData = [
19857
20239
  }
19858
20240
  ]
19859
20241
  },
20242
+ "isSymlink": {
20243
+ "description": "Checks if a path is a symbolic link.",
20244
+ "parameters": {
20245
+ "path": {
20246
+ "type": "string",
20247
+ "description": "The path to check"
20248
+ }
20249
+ },
20250
+ "required": [
20251
+ "path"
20252
+ ],
20253
+ "returns": "boolean"
20254
+ },
20255
+ "realpath": {
20256
+ "description": "Resolves a symlink to its real path. Returns the resolved path as-is if not a symlink.",
20257
+ "parameters": {
20258
+ "path": {
20259
+ "type": "string",
20260
+ "description": "The path to resolve"
20261
+ }
20262
+ },
20263
+ "required": [
20264
+ "path"
20265
+ ],
20266
+ "returns": "string"
20267
+ },
19860
20268
  "stat": {
19861
20269
  "description": "Synchronously returns the stat object for a file or directory.",
19862
20270
  "parameters": {
@@ -20330,7 +20738,7 @@ export const introspectionData = [
20330
20738
  },
20331
20739
  {
20332
20740
  "id": "features.ipcSocket",
20333
- "description": "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' }); ```",
20741
+ "description": "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 }); }); ```",
20334
20742
  "shortcut": "features.ipcSocket",
20335
20743
  "className": "IpcSocket",
20336
20744
  "methods": {
@@ -20370,61 +20778,127 @@ export const introspectionData = [
20370
20778
  ]
20371
20779
  },
20372
20780
  "broadcast": {
20373
- "description": "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>\" } ```",
20781
+ "description": "Broadcasts a message to all connected clients (server mode only).",
20374
20782
  "parameters": {
20375
20783
  "message": {
20376
20784
  "type": "any",
20377
- "description": "The message object to broadcast to all clients"
20785
+ "description": "The message object to broadcast"
20786
+ },
20787
+ "exclude": {
20788
+ "type": "string",
20789
+ "description": "Optional client ID to exclude from broadcast"
20378
20790
  }
20379
20791
  },
20380
20792
  "required": [
20381
20793
  "message"
20382
20794
  ],
20383
- "returns": "void",
20384
- "examples": [
20385
- {
20386
- "language": "ts",
20387
- "code": "// Broadcast to all connected clients\nipc.broadcast({ \n type: 'notification',\n message: 'Server is shutting down in 30 seconds',\n timestamp: Date.now()\n});\n\n// Chain multiple operations\nipc.broadcast({ status: 'ready' })\n .broadcast({ time: new Date().toISOString() });"
20795
+ "returns": "void"
20796
+ },
20797
+ "sendTo": {
20798
+ "description": "Sends a message to a specific client by ID (server mode only).",
20799
+ "parameters": {
20800
+ "clientId": {
20801
+ "type": "string",
20802
+ "description": "The target client ID"
20803
+ },
20804
+ "message": {
20805
+ "type": "any",
20806
+ "description": "The message to send"
20388
20807
  }
20389
- ]
20808
+ },
20809
+ "required": [
20810
+ "clientId",
20811
+ "message"
20812
+ ],
20813
+ "returns": "boolean"
20390
20814
  },
20391
20815
  "send": {
20392
- "description": "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>\" } ```",
20816
+ "description": "Fire-and-forget: sends a message to the server (client mode only). For server→client, use sendTo() or broadcast().",
20393
20817
  "parameters": {
20394
20818
  "message": {
20395
20819
  "type": "any",
20396
- "description": "The message object to send to the server"
20820
+ "description": "The message to send"
20397
20821
  }
20398
20822
  },
20399
20823
  "required": [
20400
20824
  "message"
20401
20825
  ],
20402
- "returns": "void",
20403
- "examples": [
20404
- {
20405
- "language": "ts",
20406
- "code": "// Send a simple message\nawait ipc.send({ type: 'ping' });\n\n// Send complex data\nawait ipc.send({\n type: 'data_update',\n payload: { users: [...], timestamp: Date.now() }\n});"
20826
+ "returns": "void"
20827
+ },
20828
+ "ask": {
20829
+ "description": "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.",
20830
+ "parameters": {
20831
+ "message": {
20832
+ "type": "any",
20833
+ "description": "The message to send"
20834
+ },
20835
+ "options": {
20836
+ "type": "{ clientId?: string; timeoutMs?: number }",
20837
+ "description": "Optional: clientId (server mode target), timeoutMs"
20407
20838
  }
20408
- ]
20839
+ },
20840
+ "required": [
20841
+ "message"
20842
+ ],
20843
+ "returns": "Promise<any>"
20844
+ },
20845
+ "reply": {
20846
+ "description": "Sends a reply to a previous ask() call, correlated by requestId.",
20847
+ "parameters": {
20848
+ "requestId": {
20849
+ "type": "string",
20850
+ "description": "The requestId from the incoming message"
20851
+ },
20852
+ "data": {
20853
+ "type": "any",
20854
+ "description": "The reply payload"
20855
+ },
20856
+ "clientId": {
20857
+ "type": "string",
20858
+ "description": "Target client (server mode; for client mode, omit)"
20859
+ }
20860
+ },
20861
+ "required": [
20862
+ "requestId",
20863
+ "data"
20864
+ ],
20865
+ "returns": "void"
20409
20866
  },
20410
20867
  "connect": {
20411
- "description": "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",
20868
+ "description": "Connects to an IPC server at the specified socket path (client mode).",
20412
20869
  "parameters": {
20413
20870
  "socketPath": {
20414
20871
  "type": "string",
20415
- "description": "The file system path to the server's Unix domain socket"
20872
+ "description": "Path to the server's Unix domain socket"
20873
+ },
20874
+ "options": {
20875
+ "type": "{ reconnect?: boolean; name?: string }",
20876
+ "description": "Optional: reconnect (enable auto-reconnect), name (identify this client)"
20416
20877
  }
20417
20878
  },
20418
20879
  "required": [
20419
20880
  "socketPath"
20420
20881
  ],
20421
- "returns": "Promise<Socket>",
20422
- "examples": [
20423
- {
20424
- "language": "ts",
20425
- "code": "// Connect to server\nconst socket = await ipc.connect('/tmp/myapp.sock');\nconsole.log('Connected to IPC server');\n\n// Handle incoming messages\nipc.on('message', (data) => {\n console.log('Server message:', data);\n});\n\n// Send messages\nawait ipc.send({ type: 'hello', client_id: 'client_001' });"
20882
+ "returns": "Promise<Socket>"
20883
+ },
20884
+ "disconnect": {
20885
+ "description": "Disconnects the client and stops any reconnection attempts.",
20886
+ "parameters": {},
20887
+ "required": [],
20888
+ "returns": "void"
20889
+ },
20890
+ "probeSocket": {
20891
+ "description": "Probe an existing socket to see if a live listener is behind it. Attempts a quick connect — if it succeeds, someone is listening.",
20892
+ "parameters": {
20893
+ "socketPath": {
20894
+ "type": "string",
20895
+ "description": "Parameter socketPath"
20426
20896
  }
20427
- ]
20897
+ },
20898
+ "required": [
20899
+ "socketPath"
20900
+ ],
20901
+ "returns": "Promise<boolean>"
20428
20902
  }
20429
20903
  },
20430
20904
  "getters": {
@@ -20436,12 +20910,25 @@ export const introspectionData = [
20436
20910
  "description": "Checks if the IPC socket is operating in server mode.",
20437
20911
  "returns": "any"
20438
20912
  },
20913
+ "clientCount": {
20914
+ "description": "Returns the number of currently connected clients (server mode).",
20915
+ "returns": "any"
20916
+ },
20917
+ "connectedClients": {
20918
+ "description": "Returns info about all connected clients (server mode).",
20919
+ "returns": "Array<{ id: string; name?: string; connectedAt: number }>"
20920
+ },
20439
20921
  "connection": {
20440
20922
  "description": "Gets the current client connection socket.",
20441
20923
  "returns": "any"
20442
20924
  }
20443
20925
  },
20444
20926
  "events": {
20927
+ "disconnection": {
20928
+ "name": "disconnection",
20929
+ "description": "Event emitted by IpcSocket",
20930
+ "arguments": {}
20931
+ },
20445
20932
  "connection": {
20446
20933
  "name": "connection",
20447
20934
  "description": "Event emitted by IpcSocket",
@@ -21356,10 +21843,68 @@ export const introspectionData = [
21356
21843
  },
21357
21844
  {
21358
21845
  "id": "features.processManager",
21359
- "description": "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.",
21846
+ "description": "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.",
21360
21847
  "shortcut": "features.processManager",
21361
21848
  "className": "ProcessManager",
21362
21849
  "methods": {
21850
+ "spawnProcess": {
21851
+ "description": "Tool handler: spawn a long-running background process.",
21852
+ "parameters": {
21853
+ "args": {
21854
+ "type": "{ command: string; args?: string; tag?: string; cwd?: string }",
21855
+ "description": "Parameter args"
21856
+ }
21857
+ },
21858
+ "required": [
21859
+ "args"
21860
+ ],
21861
+ "returns": "void"
21862
+ },
21863
+ "runCommand": {
21864
+ "description": "Tool handler: run a command to completion and return its output.",
21865
+ "parameters": {
21866
+ "args": {
21867
+ "type": "{ command: string; cwd?: string }",
21868
+ "description": "Parameter args"
21869
+ }
21870
+ },
21871
+ "required": [
21872
+ "args"
21873
+ ],
21874
+ "returns": "void"
21875
+ },
21876
+ "listProcesses": {
21877
+ "description": "Tool handler: list all tracked processes.",
21878
+ "parameters": {},
21879
+ "required": [],
21880
+ "returns": "void"
21881
+ },
21882
+ "getProcessOutput": {
21883
+ "description": "Tool handler: peek at a process's buffered output.",
21884
+ "parameters": {
21885
+ "args": {
21886
+ "type": "{ id?: string; tag?: string; stream?: string }",
21887
+ "description": "Parameter args"
21888
+ }
21889
+ },
21890
+ "required": [
21891
+ "args"
21892
+ ],
21893
+ "returns": "void"
21894
+ },
21895
+ "killProcess": {
21896
+ "description": "Tool handler: kill a process by ID or tag.",
21897
+ "parameters": {
21898
+ "args": {
21899
+ "type": "{ id?: string; tag?: string; signal?: string }",
21900
+ "description": "Parameter args"
21901
+ }
21902
+ },
21903
+ "required": [
21904
+ "args"
21905
+ ],
21906
+ "returns": "void"
21907
+ },
21363
21908
  "spawn": {
21364
21909
  "description": "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.",
21365
21910
  "parameters": {
@@ -21537,7 +22082,7 @@ export const introspectionData = [
21537
22082
  "examples": [
21538
22083
  {
21539
22084
  "language": "ts",
21540
- "code": "const pm = container.feature('processManager', { enable: true })\n\nconst server = pm.spawn('node', ['server.js'], { tag: 'api', cwd: '/app' })\nserver.on('stdout', (data) => console.log('[api]', data))\nserver.on('crash', (code) => console.error('API crashed:', code))\n\n// Kill one\nserver.kill()\n\n// Kill all tracked processes\npm.killAll()\n\n// List and lookup\npm.list() // SpawnHandler[]\npm.getByTag('api') // SpawnHandler | undefined"
22085
+ "code": "const pm = container.feature('processManager', { enable: true })\n\nconst server = pm.spawn('node', ['server.js'], { tag: 'api', cwd: '/app' })\nserver.on('stdout', (data) => console.log('[api]', data))\nserver.on('crash', (code) => console.error('API crashed:', code))\n\n// Peek at buffered output\nconst { head, tail } = server.peek()\n\n// Kill one\nserver.kill()\n\n// Kill all tracked processes\npm.killAll()\n\n// List and lookup\npm.list() // SpawnHandler[]\npm.getByTag('api') // SpawnHandler | undefined"
21541
22086
  }
21542
22087
  ]
21543
22088
  },
@@ -23895,7 +24440,7 @@ export const introspectionData = [
23895
24440
  },
23896
24441
  {
23897
24442
  "id": "clients.websocket",
23898
- "description": "WebSocket client that bridges raw WebSocket events to Luca's Helper event bus, providing a clean interface for sending/receiving messages, tracking connection state, and optional auto-reconnection with exponential backoff. Events emitted: - `open` — connection established - `message` — message received (JSON-parsed when possible) - `close` — connection closed (with code and reason) - `error` — connection error - `reconnecting` — attempting reconnection (with attempt number)",
24443
+ "description": "WebSocketClient helper",
23899
24444
  "shortcut": "clients.websocket",
23900
24445
  "className": "WebSocketClient",
23901
24446
  "methods": {
@@ -23918,24 +24463,77 @@ export const introspectionData = [
23918
24463
  ],
23919
24464
  "returns": "Promise<void>"
23920
24465
  },
23921
- "disconnect": {
23922
- "description": "Gracefully close the WebSocket connection. Suppresses auto-reconnect and updates connection state to disconnected.",
23923
- "parameters": {},
23924
- "required": [],
23925
- "returns": "Promise<this>"
23926
- }
23927
- },
23928
- "getters": {
23929
- "hasError": {
23930
- "description": "Whether the client is in an error state.",
23931
- "returns": "any"
23932
- }
23933
- },
23934
- "events": {
23935
- "open": {
23936
- "name": "open",
23937
- "description": "Event emitted by WebSocketClient",
23938
- "arguments": {}
24466
+ "ask": {
24467
+ "description": "Send a request and wait for a correlated response. The message is sent with a unique `requestId`; the remote side is expected to reply with a message containing `replyTo` set to that same ID.",
24468
+ "parameters": {
24469
+ "type": {
24470
+ "type": "string",
24471
+ "description": "A string identifying the request type"
24472
+ },
24473
+ "data": {
24474
+ "type": "any",
24475
+ "description": "Optional payload to include with the request"
24476
+ },
24477
+ "timeout": {
24478
+ "type": "any",
24479
+ "description": "How long to wait for a response (default 10 000 ms)"
24480
+ }
24481
+ },
24482
+ "required": [
24483
+ "type"
24484
+ ],
24485
+ "returns": "Promise<R>",
24486
+ "examples": [
24487
+ {
24488
+ "language": "ts",
24489
+ "code": "const result = await ws.ask('getUser', { id: 42 })"
24490
+ }
24491
+ ]
24492
+ },
24493
+ "_handleReply": {
24494
+ "description": "",
24495
+ "parameters": {
24496
+ "message": {
24497
+ "type": "any",
24498
+ "description": "Parameter message"
24499
+ }
24500
+ },
24501
+ "required": [
24502
+ "message"
24503
+ ],
24504
+ "returns": "boolean"
24505
+ },
24506
+ "_rejectAllPending": {
24507
+ "description": "",
24508
+ "parameters": {
24509
+ "reason": {
24510
+ "type": "string",
24511
+ "description": "Parameter reason"
24512
+ }
24513
+ },
24514
+ "required": [
24515
+ "reason"
24516
+ ],
24517
+ "returns": "void"
24518
+ },
24519
+ "disconnect": {
24520
+ "description": "Gracefully close the WebSocket connection. Suppresses auto-reconnect and updates connection state to disconnected.",
24521
+ "parameters": {},
24522
+ "required": [],
24523
+ "returns": "Promise<this>"
24524
+ }
24525
+ },
24526
+ "getters": {
24527
+ "hasError": {
24528
+ "description": "Whether the client is in an error state.",
24529
+ "returns": "any"
24530
+ }
24531
+ },
24532
+ "events": {
24533
+ "open": {
24534
+ "name": "open",
24535
+ "description": "Event emitted by WebSocketClient",
24536
+ "arguments": {}
23939
24537
  },
23940
24538
  "error": {
23941
24539
  "name": "error",
@@ -23960,13 +24558,7 @@ export const introspectionData = [
23960
24558
  },
23961
24559
  "state": {},
23962
24560
  "options": {},
23963
- "envVars": [],
23964
- "examples": [
23965
- {
23966
- "language": "ts",
23967
- "code": "const ws = container.client('websocket', {\n baseURL: 'ws://localhost:8080',\n reconnect: true,\n maxReconnectAttempts: 5\n})\nws.on('message', (data) => console.log('Received:', data))\nawait ws.connect()\nawait ws.send({ type: 'hello' })"
23968
- }
23969
- ]
24561
+ "envVars": []
23970
24562
  },
23971
24563
  {
23972
24564
  "id": "clients.openai",
@@ -24430,6 +25022,207 @@ export const introspectionData = [
24430
25022
  }
24431
25023
  ]
24432
25024
  },
25025
+ {
25026
+ "id": "clients.elevenlabs",
25027
+ "description": "ElevenLabs client — text-to-speech synthesis via the ElevenLabs REST API. Provides methods for listing voices, listing models, and generating speech audio. Audio is returned as a Buffer; use `say()` for a convenience method that writes to disk.",
25028
+ "shortcut": "clients.elevenlabs",
25029
+ "className": "ElevenLabsClient",
25030
+ "methods": {
25031
+ "beforeRequest": {
25032
+ "description": "Inject the xi-api-key header before each request.",
25033
+ "parameters": {},
25034
+ "required": [],
25035
+ "returns": "void"
25036
+ },
25037
+ "connect": {
25038
+ "description": "Validate the API key by listing available models.",
25039
+ "parameters": {},
25040
+ "required": [],
25041
+ "returns": "Promise<this>",
25042
+ "examples": [
25043
+ {
25044
+ "language": "ts",
25045
+ "code": "await el.connect()"
25046
+ }
25047
+ ]
25048
+ },
25049
+ "listVoices": {
25050
+ "description": "List available voices with optional search and filtering.",
25051
+ "parameters": {
25052
+ "options": {
25053
+ "type": "{\n search?: string\n category?: string\n voice_type?: string\n page_size?: number\n next_page_token?: string\n }",
25054
+ "description": "Query parameters for filtering voices"
25055
+ }
25056
+ },
25057
+ "required": [],
25058
+ "returns": "Promise<any>",
25059
+ "examples": [
25060
+ {
25061
+ "language": "ts",
25062
+ "code": "const voices = await el.listVoices()\nconst premade = await el.listVoices({ category: 'premade' })"
25063
+ }
25064
+ ]
25065
+ },
25066
+ "getVoice": {
25067
+ "description": "Get details for a single voice.",
25068
+ "parameters": {
25069
+ "voiceId": {
25070
+ "type": "string",
25071
+ "description": "The voice ID to look up"
25072
+ }
25073
+ },
25074
+ "required": [
25075
+ "voiceId"
25076
+ ],
25077
+ "returns": "Promise<any>",
25078
+ "examples": [
25079
+ {
25080
+ "language": "ts",
25081
+ "code": "const voice = await el.getVoice('21m00Tcm4TlvDq8ikWAM')\nconsole.log(voice.name, voice.settings)"
25082
+ }
25083
+ ]
25084
+ },
25085
+ "listModels": {
25086
+ "description": "List available TTS models.",
25087
+ "parameters": {},
25088
+ "required": [],
25089
+ "returns": "Promise<any[]>",
25090
+ "examples": [
25091
+ {
25092
+ "language": "ts",
25093
+ "code": "const models = await el.listModels()\nconsole.log(models.map(m => m.model_id))"
25094
+ }
25095
+ ]
25096
+ },
25097
+ "synthesize": {
25098
+ "description": "Synthesize speech from text, returning audio as a Buffer.",
25099
+ "parameters": {
25100
+ "text": {
25101
+ "type": "string",
25102
+ "description": "The text to convert to speech"
25103
+ },
25104
+ "options": {
25105
+ "type": "SynthesizeOptions",
25106
+ "description": "Voice, model, format, and voice settings overrides",
25107
+ "properties": {
25108
+ "voiceId": {
25109
+ "type": "string",
25110
+ "description": ""
25111
+ },
25112
+ "modelId": {
25113
+ "type": "string",
25114
+ "description": ""
25115
+ },
25116
+ "outputFormat": {
25117
+ "type": "string",
25118
+ "description": ""
25119
+ },
25120
+ "voiceSettings": {
25121
+ "type": "ElevenLabsVoiceSettings",
25122
+ "description": ""
25123
+ },
25124
+ "disableCache": {
25125
+ "type": "boolean",
25126
+ "description": ""
25127
+ }
25128
+ }
25129
+ }
25130
+ },
25131
+ "required": [
25132
+ "text"
25133
+ ],
25134
+ "returns": "Promise<Buffer>",
25135
+ "examples": [
25136
+ {
25137
+ "language": "ts",
25138
+ "code": "const audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data\n\nconst custom = await el.synthesize('Hello', {\n voiceId: '21m00Tcm4TlvDq8ikWAM',\n voiceSettings: { stability: 0.5, similarityBoost: 0.8 }\n})"
25139
+ }
25140
+ ]
25141
+ },
25142
+ "say": {
25143
+ "description": "Synthesize speech and write the audio to a file.",
25144
+ "parameters": {
25145
+ "text": {
25146
+ "type": "string",
25147
+ "description": "The text to convert to speech"
25148
+ },
25149
+ "outputPath": {
25150
+ "type": "string",
25151
+ "description": "File path to write the audio to"
25152
+ },
25153
+ "options": {
25154
+ "type": "SynthesizeOptions",
25155
+ "description": "Voice, model, format, and voice settings overrides",
25156
+ "properties": {
25157
+ "voiceId": {
25158
+ "type": "string",
25159
+ "description": ""
25160
+ },
25161
+ "modelId": {
25162
+ "type": "string",
25163
+ "description": ""
25164
+ },
25165
+ "outputFormat": {
25166
+ "type": "string",
25167
+ "description": ""
25168
+ },
25169
+ "voiceSettings": {
25170
+ "type": "ElevenLabsVoiceSettings",
25171
+ "description": ""
25172
+ },
25173
+ "disableCache": {
25174
+ "type": "boolean",
25175
+ "description": ""
25176
+ }
25177
+ }
25178
+ }
25179
+ },
25180
+ "required": [
25181
+ "text",
25182
+ "outputPath"
25183
+ ],
25184
+ "returns": "Promise<string>",
25185
+ "examples": [
25186
+ {
25187
+ "language": "ts",
25188
+ "code": "const path = await el.say('Hello world', './hello.mp3')\nconsole.log(`Audio saved to ${path}`)"
25189
+ }
25190
+ ]
25191
+ }
25192
+ },
25193
+ "getters": {
25194
+ "apiKey": {
25195
+ "description": "The resolved API key from options or environment.",
25196
+ "returns": "string"
25197
+ }
25198
+ },
25199
+ "events": {
25200
+ "failure": {
25201
+ "name": "failure",
25202
+ "description": "Event emitted by ElevenLabsClient",
25203
+ "arguments": {}
25204
+ },
25205
+ "voices": {
25206
+ "name": "voices",
25207
+ "description": "Event emitted by ElevenLabsClient",
25208
+ "arguments": {}
25209
+ },
25210
+ "speech": {
25211
+ "name": "speech",
25212
+ "description": "Event emitted by ElevenLabsClient",
25213
+ "arguments": {}
25214
+ }
25215
+ },
25216
+ "state": {},
25217
+ "options": {},
25218
+ "envVars": [],
25219
+ "examples": [
25220
+ {
25221
+ "language": "ts",
25222
+ "code": "const el = container.client('elevenlabs')\nawait el.connect()\nconst voices = await el.listVoices()\nconst audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data"
25223
+ }
25224
+ ]
25225
+ },
24433
25226
  {
24434
25227
  "id": "clients.comfyui",
24435
25228
  "description": "ComfyUI client — execute Stable Diffusion workflows via the ComfyUI API. Connects to a ComfyUI instance to queue prompts, track execution via WebSocket or polling, and download generated images. Supports both UI-format and API-format workflows with automatic conversion.",
@@ -24558,317 +25351,116 @@ export const introspectionData = [
24558
25351
  "filename"
24559
25352
  ],
24560
25353
  "returns": "Promise<Buffer>"
24561
- },
24562
- "connectWs": {
24563
- "description": "Open a WebSocket connection to ComfyUI for real-time execution tracking. Events emitted: `execution_start`, `executing`, `progress`, `executed`, `execution_cached`, `execution_error`, `execution_complete`.",
24564
- "parameters": {},
24565
- "required": [],
24566
- "returns": "Promise<void>"
24567
- },
24568
- "disconnectWs": {
24569
- "description": "Close the WebSocket connection.",
24570
- "parameters": {},
24571
- "required": [],
24572
- "returns": "void"
24573
- },
24574
- "toApiFormat": {
24575
- "description": "Convert a UI-format workflow to the API format that /prompt expects. Requires a running ComfyUI instance to fetch `object_info` so we can map positional `widgets_values` to their named input fields. If the workflow is already in API format, it's returned as-is.",
24576
- "parameters": {
24577
- "workflow": {
24578
- "type": "Record<string, any>",
24579
- "description": "Parameter workflow"
24580
- }
24581
- },
24582
- "required": [
24583
- "workflow"
24584
- ],
24585
- "returns": "Promise<Record<string, any>>"
24586
- },
24587
- "runWorkflow": {
24588
- "description": "Run a ComfyUI workflow with optional runtime input overrides. Inputs can be provided in two forms: **Direct node mapping** (when no `inputMap` in options): ``` { '3': { seed: 42 }, '6': { text: 'a cat' } } ``` **Named inputs** (when `inputMap` is provided in options): ``` inputs: { positive_prompt: 'a cat', seed: 42 } options.inputMap: { positive_prompt: { nodeId: '6', field: 'text' }, seed: { nodeId: '3', field: 'seed' } } ```",
24589
- "parameters": {
24590
- "workflow": {
24591
- "type": "Record<string, any>",
24592
- "description": "Parameter workflow"
24593
- },
24594
- "inputs": {
24595
- "type": "Record<string, any>",
24596
- "description": "Parameter inputs"
24597
- },
24598
- "options": {
24599
- "type": "WorkflowRunOptions",
24600
- "description": "Parameter options",
24601
- "properties": {
24602
- "poll": {
24603
- "type": "boolean",
24604
- "description": "Use polling instead of WebSocket for tracking execution"
24605
- },
24606
- "pollInterval": {
24607
- "type": "number",
24608
- "description": "Polling interval in ms (default 1000)"
24609
- },
24610
- "inputMap": {
24611
- "type": "InputMapping",
24612
- "description": "Named input mapping: semantic name -> { nodeId, field }"
24613
- },
24614
- "outputDir": {
24615
- "type": "string",
24616
- "description": "If provided, output images are downloaded to this directory"
24617
- }
24618
- }
24619
- }
24620
- },
24621
- "required": [
24622
- "workflow"
24623
- ],
24624
- "returns": "Promise<WorkflowResult>"
24625
- }
24626
- },
24627
- "getters": {
24628
- "clientId": {
24629
- "description": "The unique client ID used for WebSocket session tracking.",
24630
- "returns": "string"
24631
- },
24632
- "wsURL": {
24633
- "description": "The WebSocket URL derived from baseURL or overridden via options.",
24634
- "returns": "string"
24635
- }
24636
- },
24637
- "events": {
24638
- "execution_start": {
24639
- "name": "execution_start",
24640
- "description": "Event emitted by ComfyUIClient",
24641
- "arguments": {}
24642
- },
24643
- "execution_complete": {
24644
- "name": "execution_complete",
24645
- "description": "Event emitted by ComfyUIClient",
24646
- "arguments": {}
24647
- },
24648
- "executing": {
24649
- "name": "executing",
24650
- "description": "Event emitted by ComfyUIClient",
24651
- "arguments": {}
24652
- },
24653
- "progress": {
24654
- "name": "progress",
24655
- "description": "Event emitted by ComfyUIClient",
24656
- "arguments": {}
24657
- },
24658
- "executed": {
24659
- "name": "executed",
24660
- "description": "Event emitted by ComfyUIClient",
24661
- "arguments": {}
24662
- },
24663
- "execution_cached": {
24664
- "name": "execution_cached",
24665
- "description": "Event emitted by ComfyUIClient",
24666
- "arguments": {}
24667
- },
24668
- "execution_error": {
24669
- "name": "execution_error",
24670
- "description": "Event emitted by ComfyUIClient",
24671
- "arguments": {}
24672
- }
24673
- },
24674
- "state": {},
24675
- "options": {},
24676
- "envVars": [],
24677
- "examples": [
24678
- {
24679
- "language": "ts",
24680
- "code": "const comfy = container.client('comfyui', { baseURL: 'http://localhost:8188' })\nconst result = await comfy.runWorkflow(workflow, {\n '6': { text: 'a beautiful sunset' }\n})\nconsole.log(result.images)"
24681
- }
24682
- ]
24683
- },
24684
- {
24685
- "id": "clients.elevenlabs",
24686
- "description": "ElevenLabs client — text-to-speech synthesis via the ElevenLabs REST API. Provides methods for listing voices, listing models, and generating speech audio. Audio is returned as a Buffer; use `say()` for a convenience method that writes to disk.",
24687
- "shortcut": "clients.elevenlabs",
24688
- "className": "ElevenLabsClient",
24689
- "methods": {
24690
- "beforeRequest": {
24691
- "description": "Inject the xi-api-key header before each request.",
24692
- "parameters": {},
24693
- "required": [],
24694
- "returns": "void"
24695
- },
24696
- "connect": {
24697
- "description": "Validate the API key by listing available models.",
24698
- "parameters": {},
24699
- "required": [],
24700
- "returns": "Promise<this>",
24701
- "examples": [
24702
- {
24703
- "language": "ts",
24704
- "code": "await el.connect()"
24705
- }
24706
- ]
24707
- },
24708
- "listVoices": {
24709
- "description": "List available voices with optional search and filtering.",
24710
- "parameters": {
24711
- "options": {
24712
- "type": "{\n search?: string\n category?: string\n voice_type?: string\n page_size?: number\n next_page_token?: string\n }",
24713
- "description": "Query parameters for filtering voices"
24714
- }
24715
- },
24716
- "required": [],
24717
- "returns": "Promise<any>",
24718
- "examples": [
24719
- {
24720
- "language": "ts",
24721
- "code": "const voices = await el.listVoices()\nconst premade = await el.listVoices({ category: 'premade' })"
24722
- }
24723
- ]
24724
- },
24725
- "getVoice": {
24726
- "description": "Get details for a single voice.",
24727
- "parameters": {
24728
- "voiceId": {
24729
- "type": "string",
24730
- "description": "The voice ID to look up"
24731
- }
24732
- },
24733
- "required": [
24734
- "voiceId"
24735
- ],
24736
- "returns": "Promise<any>",
24737
- "examples": [
24738
- {
24739
- "language": "ts",
24740
- "code": "const voice = await el.getVoice('21m00Tcm4TlvDq8ikWAM')\nconsole.log(voice.name, voice.settings)"
24741
- }
24742
- ]
24743
- },
24744
- "listModels": {
24745
- "description": "List available TTS models.",
24746
- "parameters": {},
24747
- "required": [],
24748
- "returns": "Promise<any[]>",
24749
- "examples": [
24750
- {
24751
- "language": "ts",
24752
- "code": "const models = await el.listModels()\nconsole.log(models.map(m => m.model_id))"
24753
- }
24754
- ]
24755
- },
24756
- "synthesize": {
24757
- "description": "Synthesize speech from text, returning audio as a Buffer.",
24758
- "parameters": {
24759
- "text": {
24760
- "type": "string",
24761
- "description": "The text to convert to speech"
24762
- },
24763
- "options": {
24764
- "type": "SynthesizeOptions",
24765
- "description": "Voice, model, format, and voice settings overrides",
24766
- "properties": {
24767
- "voiceId": {
24768
- "type": "string",
24769
- "description": ""
24770
- },
24771
- "modelId": {
24772
- "type": "string",
24773
- "description": ""
24774
- },
24775
- "outputFormat": {
24776
- "type": "string",
24777
- "description": ""
24778
- },
24779
- "voiceSettings": {
24780
- "type": "ElevenLabsVoiceSettings",
24781
- "description": ""
24782
- },
24783
- "disableCache": {
24784
- "type": "boolean",
24785
- "description": ""
24786
- }
24787
- }
25354
+ },
25355
+ "connectWs": {
25356
+ "description": "Open a WebSocket connection to ComfyUI for real-time execution tracking. Events emitted: `execution_start`, `executing`, `progress`, `executed`, `execution_cached`, `execution_error`, `execution_complete`.",
25357
+ "parameters": {},
25358
+ "required": [],
25359
+ "returns": "Promise<void>"
25360
+ },
25361
+ "disconnectWs": {
25362
+ "description": "Close the WebSocket connection.",
25363
+ "parameters": {},
25364
+ "required": [],
25365
+ "returns": "void"
25366
+ },
25367
+ "toApiFormat": {
25368
+ "description": "Convert a UI-format workflow to the API format that /prompt expects. Requires a running ComfyUI instance to fetch `object_info` so we can map positional `widgets_values` to their named input fields. If the workflow is already in API format, it's returned as-is.",
25369
+ "parameters": {
25370
+ "workflow": {
25371
+ "type": "Record<string, any>",
25372
+ "description": "Parameter workflow"
24788
25373
  }
24789
25374
  },
24790
25375
  "required": [
24791
- "text"
25376
+ "workflow"
24792
25377
  ],
24793
- "returns": "Promise<Buffer>",
24794
- "examples": [
24795
- {
24796
- "language": "ts",
24797
- "code": "const audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data\n\nconst custom = await el.synthesize('Hello', {\n voiceId: '21m00Tcm4TlvDq8ikWAM',\n voiceSettings: { stability: 0.5, similarityBoost: 0.8 }\n})"
24798
- }
24799
- ]
25378
+ "returns": "Promise<Record<string, any>>"
24800
25379
  },
24801
- "say": {
24802
- "description": "Synthesize speech and write the audio to a file.",
25380
+ "runWorkflow": {
25381
+ "description": "Run a ComfyUI workflow with optional runtime input overrides. Inputs can be provided in two forms: **Direct node mapping** (when no `inputMap` in options): ``` { '3': { seed: 42 }, '6': { text: 'a cat' } } ``` **Named inputs** (when `inputMap` is provided in options): ``` inputs: { positive_prompt: 'a cat', seed: 42 } options.inputMap: { positive_prompt: { nodeId: '6', field: 'text' }, seed: { nodeId: '3', field: 'seed' } } ```",
24803
25382
  "parameters": {
24804
- "text": {
24805
- "type": "string",
24806
- "description": "The text to convert to speech"
25383
+ "workflow": {
25384
+ "type": "Record<string, any>",
25385
+ "description": "Parameter workflow"
24807
25386
  },
24808
- "outputPath": {
24809
- "type": "string",
24810
- "description": "File path to write the audio to"
25387
+ "inputs": {
25388
+ "type": "Record<string, any>",
25389
+ "description": "Parameter inputs"
24811
25390
  },
24812
25391
  "options": {
24813
- "type": "SynthesizeOptions",
24814
- "description": "Voice, model, format, and voice settings overrides",
25392
+ "type": "WorkflowRunOptions",
25393
+ "description": "Parameter options",
24815
25394
  "properties": {
24816
- "voiceId": {
24817
- "type": "string",
24818
- "description": ""
24819
- },
24820
- "modelId": {
24821
- "type": "string",
24822
- "description": ""
25395
+ "poll": {
25396
+ "type": "boolean",
25397
+ "description": "Use polling instead of WebSocket for tracking execution"
24823
25398
  },
24824
- "outputFormat": {
24825
- "type": "string",
24826
- "description": ""
25399
+ "pollInterval": {
25400
+ "type": "number",
25401
+ "description": "Polling interval in ms (default 1000)"
24827
25402
  },
24828
- "voiceSettings": {
24829
- "type": "ElevenLabsVoiceSettings",
24830
- "description": ""
25403
+ "inputMap": {
25404
+ "type": "InputMapping",
25405
+ "description": "Named input mapping: semantic name -> { nodeId, field }"
24831
25406
  },
24832
- "disableCache": {
24833
- "type": "boolean",
24834
- "description": ""
25407
+ "outputDir": {
25408
+ "type": "string",
25409
+ "description": "If provided, output images are downloaded to this directory"
24835
25410
  }
24836
25411
  }
24837
25412
  }
24838
25413
  },
24839
25414
  "required": [
24840
- "text",
24841
- "outputPath"
25415
+ "workflow"
24842
25416
  ],
24843
- "returns": "Promise<string>",
24844
- "examples": [
24845
- {
24846
- "language": "ts",
24847
- "code": "const path = await el.say('Hello world', './hello.mp3')\nconsole.log(`Audio saved to ${path}`)"
24848
- }
24849
- ]
25417
+ "returns": "Promise<WorkflowResult>"
24850
25418
  }
24851
25419
  },
24852
25420
  "getters": {
24853
- "apiKey": {
24854
- "description": "The resolved API key from options or environment.",
25421
+ "clientId": {
25422
+ "description": "The unique client ID used for WebSocket session tracking.",
25423
+ "returns": "string"
25424
+ },
25425
+ "wsURL": {
25426
+ "description": "The WebSocket URL derived from baseURL or overridden via options.",
24855
25427
  "returns": "string"
24856
25428
  }
24857
25429
  },
24858
25430
  "events": {
24859
- "failure": {
24860
- "name": "failure",
24861
- "description": "Event emitted by ElevenLabsClient",
25431
+ "execution_start": {
25432
+ "name": "execution_start",
25433
+ "description": "Event emitted by ComfyUIClient",
24862
25434
  "arguments": {}
24863
25435
  },
24864
- "voices": {
24865
- "name": "voices",
24866
- "description": "Event emitted by ElevenLabsClient",
25436
+ "execution_complete": {
25437
+ "name": "execution_complete",
25438
+ "description": "Event emitted by ComfyUIClient",
24867
25439
  "arguments": {}
24868
25440
  },
24869
- "speech": {
24870
- "name": "speech",
24871
- "description": "Event emitted by ElevenLabsClient",
25441
+ "executing": {
25442
+ "name": "executing",
25443
+ "description": "Event emitted by ComfyUIClient",
25444
+ "arguments": {}
25445
+ },
25446
+ "progress": {
25447
+ "name": "progress",
25448
+ "description": "Event emitted by ComfyUIClient",
25449
+ "arguments": {}
25450
+ },
25451
+ "executed": {
25452
+ "name": "executed",
25453
+ "description": "Event emitted by ComfyUIClient",
25454
+ "arguments": {}
25455
+ },
25456
+ "execution_cached": {
25457
+ "name": "execution_cached",
25458
+ "description": "Event emitted by ComfyUIClient",
25459
+ "arguments": {}
25460
+ },
25461
+ "execution_error": {
25462
+ "name": "execution_error",
25463
+ "description": "Event emitted by ComfyUIClient",
24872
25464
  "arguments": {}
24873
25465
  }
24874
25466
  },
@@ -24878,7 +25470,7 @@ export const introspectionData = [
24878
25470
  "examples": [
24879
25471
  {
24880
25472
  "language": "ts",
24881
- "code": "const el = container.client('elevenlabs')\nawait el.connect()\nconst voices = await el.listVoices()\nconst audio = await el.synthesize('Hello world')\n// audio is a Buffer of mp3 data"
25473
+ "code": "const comfy = container.client('comfyui', { baseURL: 'http://localhost:8188' })\nconst result = await comfy.runWorkflow(workflow, {\n '6': { text: 'a beautiful sunset' }\n})\nconsole.log(result.images)"
24882
25474
  }
24883
25475
  ]
24884
25476
  },
@@ -25164,7 +25756,7 @@ export const introspectionData = [
25164
25756
  },
25165
25757
  {
25166
25758
  "id": "servers.websocket",
25167
- "description": "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.",
25759
+ "description": "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.",
25168
25760
  "shortcut": "servers.websocket",
25169
25761
  "className": "WebsocketServer",
25170
25762
  "methods": {
@@ -25199,6 +25791,64 @@ export const introspectionData = [
25199
25791
  ],
25200
25792
  "returns": "void"
25201
25793
  },
25794
+ "ask": {
25795
+ "description": "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.",
25796
+ "parameters": {
25797
+ "ws": {
25798
+ "type": "any",
25799
+ "description": "The WebSocket client to ask"
25800
+ },
25801
+ "type": {
25802
+ "type": "string",
25803
+ "description": "A string identifying the request type"
25804
+ },
25805
+ "data": {
25806
+ "type": "any",
25807
+ "description": "Optional payload"
25808
+ },
25809
+ "timeout": {
25810
+ "type": "any",
25811
+ "description": "How long to wait (default 10 000 ms)"
25812
+ }
25813
+ },
25814
+ "required": [
25815
+ "ws",
25816
+ "type"
25817
+ ],
25818
+ "returns": "Promise<R>",
25819
+ "examples": [
25820
+ {
25821
+ "language": "ts",
25822
+ "code": "ws.on('connection', async (client) => {\n const info = await ws.ask(client, 'identify')\n console.log('Client says:', info)\n})"
25823
+ }
25824
+ ]
25825
+ },
25826
+ "_handleReply": {
25827
+ "description": "",
25828
+ "parameters": {
25829
+ "message": {
25830
+ "type": "any",
25831
+ "description": "Parameter message"
25832
+ }
25833
+ },
25834
+ "required": [
25835
+ "message"
25836
+ ],
25837
+ "returns": "boolean"
25838
+ },
25839
+ "_rejectAllPending": {
25840
+ "description": "",
25841
+ "parameters": {
25842
+ "reason": {
25843
+ "type": "string",
25844
+ "description": "Parameter reason"
25845
+ }
25846
+ },
25847
+ "required": [
25848
+ "reason"
25849
+ ],
25850
+ "returns": "void"
25851
+ },
25202
25852
  "start": {
25203
25853
  "description": "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.",
25204
25854
  "parameters": {
@@ -25245,7 +25895,7 @@ export const introspectionData = [
25245
25895
  "examples": [
25246
25896
  {
25247
25897
  "language": "ts",
25248
- "code": "const ws = container.server('websocket', { json: true })\nawait ws.start({ port: 8080 })\n\nws.on('message', (data, client) => {\n console.log('Received:', data)\n ws.broadcast({ echo: data })\n})"
25898
+ "code": "const ws = container.server('websocket', { json: true })\nawait ws.start({ port: 8080 })\n\nws.on('message', (data, client) => {\n console.log('Received:', data)\n ws.broadcast({ echo: data })\n})\n\n// ask/reply: request info from a connected client\nws.on('connection', async (client) => {\n const info = await ws.ask(client, 'identify')\n console.log('Client says:', info)\n})"
25249
25899
  }
25250
25900
  ]
25251
25901
  },
@@ -25505,6 +26155,10 @@ export const introspectionData = [
25505
26155
  "maxTokens": {
25506
26156
  "type": "number",
25507
26157
  "description": ""
26158
+ },
26159
+ "schema": {
26160
+ "type": "z.ZodType",
26161
+ "description": "When provided, enables OpenAI Structured Outputs. The model is constrained to return JSON matching this Zod schema. The return value of ask() will be the parsed object instead of a raw string."
25508
26162
  }
25509
26163
  }
25510
26164
  }
@@ -25622,6 +26276,21 @@ export const introspectionData = [
25622
26276
  "description": "Event emitted by Conversation",
25623
26277
  "arguments": {}
25624
26278
  },
26279
+ "toolError": {
26280
+ "name": "toolError",
26281
+ "description": "Event emitted by Conversation",
26282
+ "arguments": {}
26283
+ },
26284
+ "toolCall": {
26285
+ "name": "toolCall",
26286
+ "description": "Event emitted by Conversation",
26287
+ "arguments": {}
26288
+ },
26289
+ "toolResult": {
26290
+ "name": "toolResult",
26291
+ "description": "Event emitted by Conversation",
26292
+ "arguments": {}
26293
+ },
25625
26294
  "turnStart": {
25626
26295
  "name": "turnStart",
25627
26296
  "description": "Event emitted by Conversation",
@@ -25657,21 +26326,6 @@ export const introspectionData = [
25657
26326
  "description": "Event emitted by Conversation",
25658
26327
  "arguments": {}
25659
26328
  },
25660
- "toolError": {
25661
- "name": "toolError",
25662
- "description": "Event emitted by Conversation",
25663
- "arguments": {}
25664
- },
25665
- "toolCall": {
25666
- "name": "toolCall",
25667
- "description": "Event emitted by Conversation",
25668
- "arguments": {}
25669
- },
25670
- "toolResult": {
25671
- "name": "toolResult",
25672
- "description": "Event emitted by Conversation",
25673
- "arguments": {}
25674
- },
25675
26329
  "toolCallsEnd": {
25676
26330
  "name": "toolCallsEnd",
25677
26331
  "description": "Event emitted by Conversation",
@@ -26087,12 +26741,61 @@ export const introspectionData = [
26087
26741
  "shortcut": "features.assistant",
26088
26742
  "className": "Assistant",
26089
26743
  "methods": {
26744
+ "intercept": {
26745
+ "description": "Register an interceptor at a given point in the pipeline.",
26746
+ "parameters": {
26747
+ "point": {
26748
+ "type": "K",
26749
+ "description": "The interception point"
26750
+ },
26751
+ "fn": {
26752
+ "type": "InterceptorFn<InterceptorPoints[K]>",
26753
+ "description": "Middleware function receiving (ctx, next)"
26754
+ }
26755
+ },
26756
+ "required": [
26757
+ "point",
26758
+ "fn"
26759
+ ],
26760
+ "returns": "this"
26761
+ },
26090
26762
  "afterInitialize": {
26091
26763
  "description": "Called immediately after the assistant is constructed. Synchronously loads the system prompt, tools, and hooks, then binds hooks as event listeners so every emitted event automatically invokes its corresponding hook.",
26092
26764
  "parameters": {},
26093
26765
  "required": [],
26094
26766
  "returns": "void"
26095
26767
  },
26768
+ "addSystemPromptExtension": {
26769
+ "description": "Add or update a named system prompt extension. The value is appended to the base system prompt when passed to the conversation.",
26770
+ "parameters": {
26771
+ "key": {
26772
+ "type": "string",
26773
+ "description": "A unique identifier for this extension"
26774
+ },
26775
+ "value": {
26776
+ "type": "string",
26777
+ "description": "The text to append"
26778
+ }
26779
+ },
26780
+ "required": [
26781
+ "key",
26782
+ "value"
26783
+ ],
26784
+ "returns": "this"
26785
+ },
26786
+ "removeSystemPromptExtension": {
26787
+ "description": "Remove a named system prompt extension.",
26788
+ "parameters": {
26789
+ "key": {
26790
+ "type": "string",
26791
+ "description": "The identifier of the extension to remove"
26792
+ }
26793
+ },
26794
+ "required": [
26795
+ "key"
26796
+ ],
26797
+ "returns": "this"
26798
+ },
26096
26799
  "use": {
26097
26800
  "description": "Apply a setup function or a Helper instance to this assistant. When passed a function, it receives the assistant and can configure tools, hooks, event listeners, etc. When passed a Helper instance that exposes tools via toTools(), those tools are automatically added to this assistant.",
26098
26801
  "parameters": {
@@ -26363,6 +27066,14 @@ export const introspectionData = [
26363
27066
  "description": "The current system prompt text.",
26364
27067
  "returns": "string"
26365
27068
  },
27069
+ "systemPromptExtensions": {
27070
+ "description": "The named extensions appended to the system prompt.",
27071
+ "returns": "Record<string, string>"
27072
+ },
27073
+ "effectiveSystemPrompt": {
27074
+ "description": "The system prompt with all extensions appended. This is the value passed to the conversation.",
27075
+ "returns": "string"
27076
+ },
26366
27077
  "tools": {
26367
27078
  "description": "The tools registered with this assistant.",
26368
27079
  "returns": "Record<string, ConversationTool>"
@@ -26406,6 +27117,11 @@ export const introspectionData = [
26406
27117
  "description": "Event emitted by Assistant",
26407
27118
  "arguments": {}
26408
27119
  },
27120
+ "systemPromptExtensionsChanged": {
27121
+ "name": "systemPromptExtensionsChanged",
27122
+ "description": "Event emitted by Assistant",
27123
+ "arguments": {}
27124
+ },
26409
27125
  "toolsChanged": {
26410
27126
  "name": "toolsChanged",
26411
27127
  "description": "Event emitted by Assistant",