@soederpop/luca 0.0.31 ā 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -36
- package/bun.lock +24 -5
- package/commands/build-python-bridge.ts +43 -0
- package/docs/apis/clients/rest.md +7 -7
- package/docs/apis/clients/websocket.md +23 -10
- package/docs/apis/features/agi/assistant.md +155 -8
- package/docs/apis/features/agi/assistants-manager.md +90 -22
- package/docs/apis/features/agi/auto-assistant.md +377 -0
- package/docs/apis/features/agi/browser-use.md +802 -0
- package/docs/apis/features/agi/claude-code.md +6 -1
- package/docs/apis/features/agi/conversation-history.md +7 -6
- package/docs/apis/features/agi/conversation.md +111 -38
- package/docs/apis/features/agi/docs-reader.md +35 -57
- package/docs/apis/features/agi/file-tools.md +163 -0
- package/docs/apis/features/agi/openapi.md +2 -2
- package/docs/apis/features/agi/skills-library.md +227 -0
- package/docs/apis/features/node/content-db.md +125 -4
- package/docs/apis/features/node/disk-cache.md +11 -11
- package/docs/apis/features/node/downloader.md +1 -1
- package/docs/apis/features/node/file-manager.md +15 -15
- package/docs/apis/features/node/fs.md +78 -21
- package/docs/apis/features/node/git.md +50 -10
- package/docs/apis/features/node/google-calendar.md +3 -0
- package/docs/apis/features/node/google-docs.md +10 -1
- package/docs/apis/features/node/google-drive.md +3 -0
- package/docs/apis/features/node/google-mail.md +214 -0
- package/docs/apis/features/node/google-sheets.md +3 -0
- package/docs/apis/features/node/ink.md +10 -10
- package/docs/apis/features/node/ipc-socket.md +83 -93
- package/docs/apis/features/node/networking.md +5 -5
- package/docs/apis/features/node/os.md +7 -7
- package/docs/apis/features/node/package-finder.md +14 -14
- package/docs/apis/features/node/proc.md +2 -1
- package/docs/apis/features/node/process-manager.md +70 -3
- package/docs/apis/features/node/python.md +265 -9
- package/docs/apis/features/node/redis.md +380 -0
- package/docs/apis/features/node/ui.md +13 -13
- package/docs/apis/servers/express.md +35 -7
- package/docs/apis/servers/mcp.md +3 -3
- package/docs/apis/servers/websocket.md +51 -8
- package/docs/bootstrap/CLAUDE.md +1 -1
- package/docs/bootstrap/SKILL.md +93 -7
- package/docs/examples/feature-as-tool-provider.md +143 -0
- package/docs/examples/python.md +42 -1
- package/docs/introspection.md +15 -5
- package/docs/tutorials/00-bootstrap.md +3 -3
- package/docs/tutorials/02-container.md +2 -2
- package/docs/tutorials/10-creating-features.md +5 -0
- package/docs/tutorials/13-introspection.md +12 -2
- package/docs/tutorials/19-python-sessions.md +401 -0
- package/package.json +8 -4
- package/src/agi/container.server.ts +8 -0
- package/src/agi/features/assistant.ts +19 -0
- package/src/agi/features/autonomous-assistant.ts +435 -0
- package/src/agi/features/conversation.ts +58 -6
- package/src/agi/features/file-tools.ts +286 -0
- package/src/agi/features/luca-coder.ts +643 -0
- package/src/bootstrap/generated.ts +705 -17
- package/src/cli/build-info.ts +2 -2
- package/src/cli/cli.ts +22 -13
- package/src/commands/bootstrap.ts +49 -6
- package/src/commands/code.ts +369 -0
- package/src/commands/describe.ts +7 -2
- package/src/commands/index.ts +1 -0
- package/src/commands/sandbox-mcp.ts +7 -7
- package/src/commands/save-api-docs.ts +1 -1
- package/src/container-describer.ts +4 -4
- package/src/container.ts +10 -19
- package/src/helper.ts +24 -33
- package/src/introspection/generated.agi.ts +2499 -63
- package/src/introspection/generated.node.ts +1625 -688
- package/src/introspection/generated.web.ts +15 -57
- package/src/node/container.ts +5 -0
- package/src/node/features/figlet-fonts.ts +597 -0
- package/src/node/features/fs.ts +3 -9
- package/src/node/features/helpers.ts +20 -0
- package/src/node/features/python.ts +429 -16
- package/src/node/features/redis.ts +446 -0
- package/src/node/features/ui.ts +4 -11
- package/src/python/bridge.py +220 -0
- package/src/python/generated.ts +227 -0
- package/src/scaffolds/generated.ts +1 -1
- package/test/python-session.test.ts +105 -0
- package/assistants/lucaExpert/CORE.md +0 -37
- package/assistants/lucaExpert/hooks.ts +0 -9
- package/assistants/lucaExpert/tools.ts +0 -177
package/README.md
CHANGED
|
@@ -1,48 +1,171 @@
|
|
|
1
|
-
# Luca
|
|
1
|
+
# Luca
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Lightweight Universal Conversational Architecture**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A single binary CLI that ships 40+ self-documenting features, clients, and servers. No `npm install`, no setup ā download it and start building.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Luca gives you a `container` object ā think of it like a Docker container for your application runtime. It's a per-process singleton, event bus, state machine, and dependency injector all in one. Layer your own features, clients, servers, commands, and endpoints on top of the base `NodeContainer` (server) or `WebContainer` (browser), then bundle it into your own single-file executable or browser build.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The `AGIContainer` extends the node stack with features, clients, and servers for building AI assistants ā wrappers around major coding models, tool orchestration, and UIs to visualize them working.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
### Download the binary
|
|
14
|
+
|
|
15
|
+
Grab the latest release for your platform from [GitHub Releases](https://github.com/soederpop/luca/releases/latest):
|
|
16
|
+
|
|
17
|
+
| Platform | Binary |
|
|
18
|
+
|----------|--------|
|
|
19
|
+
| macOS (Apple Silicon) | `luca-darwin-arm64` |
|
|
20
|
+
| macOS (Intel) | `luca-darwin-x64` |
|
|
21
|
+
| Linux x64 | `luca-linux-x64` |
|
|
22
|
+
| Linux ARM64 | `luca-linux-arm64` |
|
|
23
|
+
| Windows x64 | `luca-windows-x64.exe` |
|
|
24
|
+
|
|
25
|
+
**Quick install (macOS/Linux):**
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
# Download (replace PLATFORM with your arch, e.g. darwin-arm64)
|
|
29
|
+
curl -L -o luca https://github.com/soederpop/luca/releases/latest/download/luca-PLATFORM
|
|
30
|
+
chmod +x luca
|
|
31
|
+
sudo mv luca /usr/local/bin/
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### macOS Gatekeeper warning
|
|
35
|
+
|
|
36
|
+
The binary is not yet code-signed (code signing is in progress). On first run macOS will block it with *"luca can't be opened because Apple cannot check it for malicious software."*
|
|
37
|
+
|
|
38
|
+
To allow it:
|
|
39
|
+
|
|
40
|
+
1. **System Settings** > **Privacy & Security** > scroll down to the Security section
|
|
41
|
+
2. You'll see a message about `luca` being blocked ā click **Allow Anyway**
|
|
42
|
+
3. Run `luca` again and click **Open** in the confirmation dialog
|
|
43
|
+
|
|
44
|
+
Or from the terminal:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
xattr -d com.apple.quarantine /usr/local/bin/luca
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
After that it runs without interruption.
|
|
51
|
+
|
|
52
|
+
### Verify
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
luca --version
|
|
56
|
+
# luca v0.0.34 (main@325a0ee) built 2026-03-25T06:10:28Z
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
### Bootstrap a new project
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
luca bootstrap my-app
|
|
65
|
+
cd my-app
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or just run `luca bootstrap` and it'll ask you for a project name. This scaffolds a project with `commands/`, `endpoints/`, `features/`, `docs/`, and AI assistant configuration ā everything wired up and ready to extend.
|
|
69
|
+
|
|
70
|
+
### Explore
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
luca # list all commands
|
|
74
|
+
luca describe features # index of 40+ features
|
|
75
|
+
luca describe fs # full docs for any feature
|
|
76
|
+
luca describe fs.readFile # drill into a specific method
|
|
77
|
+
luca eval "container.features.available" # run code with the container in scope
|
|
78
|
+
luca console # full REPL
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Run scripts and markdown
|
|
82
|
+
|
|
83
|
+
`luca run` executes TypeScript, JavaScript, and markdown files. Markdown files have their code blocks executed in order, with `container` already in scope ā no imports needed:
|
|
84
|
+
|
|
85
|
+
````md
|
|
86
|
+
# my-script.md
|
|
87
|
+
|
|
88
|
+
Grab some data and print it:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const fs = container.feature('fs')
|
|
92
|
+
const files = await fs.readdir('.')
|
|
93
|
+
console.log(`Found ${files.length} files`)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Then do something with it:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const yaml = container.feature('yaml')
|
|
100
|
+
console.log(yaml.stringify({ files }))
|
|
101
|
+
```
|
|
102
|
+
````
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
luca run my-script.md
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Each block shares state with the previous ones, so variables defined in one block are available in the next. Use `--safe` to require approval before each block, or `--console` to drop into a REPL afterward with all the accumulated context. **Note:** if your block uses top-level awaits, we can't preserve context. You can use `container.addContext({ yourVariable })` and it will be available as a global variable in future blocks.
|
|
109
|
+
|
|
110
|
+
### Serve
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
luca serve # serves endpoints/ folder as HTTP routes
|
|
114
|
+
```
|
|
12
115
|
|
|
13
|
-
|
|
116
|
+
See [`docs/CLI.md`](./docs/CLI.md) for the full CLI reference.
|
|
14
117
|
|
|
15
|
-
|
|
118
|
+
## Importing the container into your own scripts / modules
|
|
16
119
|
|
|
17
120
|
```ts
|
|
18
121
|
import container from '@soederpop/luca'
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
That's it ā you get one object with everything on it. No factory function, no setup. It's a singleton.
|
|
125
|
+
|
|
126
|
+
We do export the framework classes (`WebContainer`, `Feature`, `Client`, `Server`, etc.) if you want to extend them, but for using the system you only ever need the default export.
|
|
127
|
+
|
|
128
|
+
### In the browser via esm.sh
|
|
19
129
|
|
|
20
|
-
|
|
21
|
-
container.clients.available // ['rest','websocket']
|
|
22
|
-
container.servers.available // ['express','websocket','ipc','mcp']
|
|
130
|
+
**Static import:**
|
|
23
131
|
|
|
24
|
-
|
|
25
|
-
container.
|
|
132
|
+
```js
|
|
133
|
+
import container from 'https://esm.sh/@soederpop/luca/web'
|
|
26
134
|
|
|
27
|
-
container.
|
|
28
|
-
container.introspectAsText() // a markdown description of the same
|
|
135
|
+
container.features.available // ['fetch', 'state', 'ui', ...]
|
|
29
136
|
```
|
|
30
137
|
|
|
31
|
-
|
|
138
|
+
**Dynamic import:**
|
|
32
139
|
|
|
33
|
-
|
|
140
|
+
```js
|
|
141
|
+
const { default: container } = await import('https://esm.sh/@soederpop/luca/web')
|
|
34
142
|
|
|
143
|
+
container.features.available // same singleton
|
|
35
144
|
```
|
|
36
|
-
const fileManager = container.feature('fileManager')
|
|
37
145
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
146
|
+
With dynamic import you have to pick it off `default` yourself ā there's no top-level default binding like the static form gives you. Either way, it's the same singleton container, and `window.luca` is set automatically so you can poke at it from the console.
|
|
147
|
+
|
|
148
|
+
## How It Works
|
|
149
|
+
|
|
150
|
+
### Self-documenting at runtime
|
|
151
|
+
|
|
152
|
+
Every helper (feature, client, server) carries its own introspection metadata ā constructor options, observable state shape, events emitted, environment variables used, method signatures. This powers `luca describe`, works in the REPL, and enables metaprogramming.
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import container from '@soederpop/luca'
|
|
156
|
+
|
|
157
|
+
container.features.available // ['fs','git','proc','vault',...]
|
|
158
|
+
container.clients.available // ['rest','websocket']
|
|
159
|
+
container.servers.available // ['express','websocket','ipc','mcp']
|
|
160
|
+
|
|
161
|
+
container.features.describe() // markdown summary of all features
|
|
162
|
+
container.feature('fs').introspect() // json
|
|
163
|
+
container.feature('fs').introspectAsText() // markdown
|
|
41
164
|
```
|
|
42
165
|
|
|
43
|
-
|
|
166
|
+
### Content-aware documentation
|
|
44
167
|
|
|
45
|
-
The node container
|
|
168
|
+
The node container includes `container.docs` powered by [Contentbase](https://github.com/soederpop/contentbase) ā query your project's markdown documentation like a database:
|
|
46
169
|
|
|
47
170
|
```ts
|
|
48
171
|
await container.docs.load()
|
|
@@ -50,29 +173,111 @@ const { Tutorial } = container.docs.models
|
|
|
50
173
|
const tutorials = await container.docs.query(Tutorial).fetchAll()
|
|
51
174
|
```
|
|
52
175
|
|
|
53
|
-
|
|
176
|
+
### Project extensions
|
|
177
|
+
|
|
178
|
+
Drop files into convention-based folders and they're auto-discovered:
|
|
54
179
|
|
|
55
|
-
|
|
180
|
+
- `commands/` ā custom CLI commands, run via `luca <name>`
|
|
181
|
+
- `endpoints/` ā file-based HTTP routes, served via `luca serve`
|
|
182
|
+
- `features/` ā custom container features
|
|
56
183
|
|
|
57
|
-
|
|
58
|
-
- The `luca describe` command lets you view docs, or just parts of docs, of any group of features, clients, etc, as a single markdown doc
|
|
59
|
-
- The `luca console` command will bring you into a full blown REPL
|
|
60
|
-
- The `luca chat` command will put you in touch with a tutor
|
|
61
|
-
- The `luca sandbox-mcp` provides a REPL for your coding assistant and a documentation browser
|
|
184
|
+
Generate boilerplate with `luca scaffold`:
|
|
62
185
|
|
|
63
|
-
|
|
186
|
+
```sh
|
|
187
|
+
luca scaffold command myTask --description "Automate something"
|
|
188
|
+
luca scaffold feature myCache --description "Custom caching layer"
|
|
189
|
+
luca scaffold endpoint users --description "User management API"
|
|
190
|
+
```
|
|
64
191
|
|
|
65
|
-
|
|
192
|
+
### Building an assistant
|
|
66
193
|
|
|
67
|
-
|
|
194
|
+
Features can inject their own tools into an assistant via `assistant.use()`. Here's an assistant that can browse the web:
|
|
68
195
|
|
|
69
|
-
|
|
196
|
+
```ts
|
|
197
|
+
import container from '@soederpop/luca'
|
|
198
|
+
|
|
199
|
+
const browser = container.feature('browserUse', { headed: true })
|
|
200
|
+
const assistant = container.feature('assistant', {
|
|
201
|
+
systemPrompt: 'You are a web research assistant. Use your browser tools to find information.',
|
|
202
|
+
model: 'gpt-4.1-mini',
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
// browserUse injects its tools ā open, click, type, screenshot, extract, etc.
|
|
206
|
+
assistant.use(browser)
|
|
207
|
+
await assistant.start()
|
|
208
|
+
|
|
209
|
+
await assistant.ask('Go to hacker news and tell me what the top 3 stories are about')
|
|
210
|
+
```
|
|
70
211
|
|
|
71
|
-
|
|
212
|
+
### AI coding assistant integration
|
|
213
|
+
|
|
214
|
+
The CLI works great alongside Claude Code, Codex, and other coding assistants:
|
|
215
|
+
|
|
216
|
+
- `luca describe` gives assistants full API docs for any helper
|
|
217
|
+
- `luca eval` lets them test container expressions before committing code
|
|
218
|
+
- `luca sandbox-mcp` provides a REPL and doc browser as an MCP server
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
### Prerequisites
|
|
223
|
+
|
|
224
|
+
- [Bun](https://bun.sh) (runtime and test runner)
|
|
225
|
+
|
|
226
|
+
### Setup
|
|
227
|
+
|
|
228
|
+
```sh
|
|
229
|
+
git clone https://github.com/soederpop/luca.git
|
|
230
|
+
cd luca
|
|
231
|
+
bun install
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Running in dev
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
# Run the CLI from source (equivalent to the luca binary)
|
|
238
|
+
bun run src/cli/cli.ts
|
|
239
|
+
|
|
240
|
+
# Examples
|
|
241
|
+
bun run src/cli/cli.ts describe features
|
|
242
|
+
bun run src/cli/cli.ts eval "container.features.available"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Testing
|
|
246
|
+
|
|
247
|
+
```sh
|
|
248
|
+
# Unit tests
|
|
249
|
+
bun test
|
|
250
|
+
|
|
251
|
+
# Integration tests (may require API keys / env vars)
|
|
252
|
+
bun run test:integration
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Building the binary
|
|
72
256
|
|
|
73
257
|
```sh
|
|
74
|
-
|
|
258
|
+
bun run compile
|
|
75
259
|
```
|
|
76
260
|
|
|
261
|
+
This runs the full pipeline: introspection generation, scaffold templates, bootstrap code, python bridge, build stamp, then compiles to `dist/luca` via Bun's native compiler.
|
|
262
|
+
|
|
263
|
+
### Project structure
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
src/
|
|
267
|
+
cli/ CLI entry point and commands
|
|
268
|
+
node/ NodeContainer and server-side features
|
|
269
|
+
web/ WebContainer and browser features
|
|
270
|
+
agi/ AGIContainer ā AI assistant layer
|
|
271
|
+
schemas/ Shared Zod schemas
|
|
272
|
+
react/ React bindings
|
|
273
|
+
test/ Unit tests
|
|
274
|
+
test-integration/ Integration tests
|
|
275
|
+
docs/
|
|
276
|
+
apis/ Generated API docs
|
|
277
|
+
examples/ Runnable examples (luca run docs/examples/grep)
|
|
278
|
+
tutorials/ Longer-form guides
|
|
279
|
+
```
|
|
77
280
|
|
|
281
|
+
## License
|
|
78
282
|
|
|
283
|
+
MIT
|
package/bun.lock
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"chokidar": "^3.5.3",
|
|
19
19
|
"cli-markdown": "^3.5.0",
|
|
20
20
|
"compromise": "^14.14.5",
|
|
21
|
-
"contentbase": "^0.
|
|
21
|
+
"contentbase": "^0.1.7",
|
|
22
22
|
"cors": "^2.8.5",
|
|
23
23
|
"detect-port": "^1.5.1",
|
|
24
24
|
"dotenv": "^17.2.4",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"inflect": "^0.5.0",
|
|
34
34
|
"ink": "^6.7.0",
|
|
35
35
|
"inquirer": "^9.1.5",
|
|
36
|
+
"ioredis": "^5.10.1",
|
|
36
37
|
"isomorphic-vm": "^0.0.1",
|
|
37
38
|
"isomorphic-ws": "^5.0.0",
|
|
38
39
|
"js-tiktoken": "^1.0.21",
|
|
@@ -192,6 +193,8 @@
|
|
|
192
193
|
|
|
193
194
|
"@inquirer/figures": ["@inquirer/figures@1.0.12", "", {}, "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ=="],
|
|
194
195
|
|
|
196
|
+
"@ioredis/commands": ["@ioredis/commands@1.5.1", "", {}, "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw=="],
|
|
197
|
+
|
|
195
198
|
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
|
196
199
|
|
|
197
200
|
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
|
@@ -334,7 +337,7 @@
|
|
|
334
337
|
|
|
335
338
|
"@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="],
|
|
336
339
|
|
|
337
|
-
"@soederpop/luca": ["@soederpop/luca@0.0.
|
|
340
|
+
"@soederpop/luca": ["@soederpop/luca@0.0.32", "", { "dependencies": { "@modelcontextprotocol/sdk": "^1.12.1", "@ngrok/ngrok": "^1.5.1", "@openai/codex": "^0.99.0", "@resvg/resvg-js": "^2.6.2", "@supabase/supabase-js": "^2.95.3", "@types/marked": "^6.0.0", "@types/marked-terminal": "^6.1.1", "axios": "^1.3.5", "cacache": "^17.0.7", "chalk": "^5.2.0", "child-process-promise": "^2.2.1", "chokidar": "^3.5.3", "cli-markdown": "^3.5.0", "compromise": "^14.14.5", "contentbase": "^0.1.7", "cors": "^2.8.5", "detect-port": "^1.5.1", "dotenv": "^17.2.4", "endent": "^2.1.0", "esbuild-wasm": "0.17.18", "excalidraw-to-svg": "^3.1.0", "express": "^4.18.2", "figlet": "^1.6.0", "glob": "^11.0.2", "googleapis": "^171.4.0", "grammy": "^1.40.0", "inflect": "^0.5.0", "ink": "^6.7.0", "inquirer": "^9.1.5", "isomorphic-vm": "^0.0.1", "isomorphic-ws": "^5.0.0", "js-tiktoken": "^1.0.21", "js-yaml": "^4.1.0", "lodash-es": "^4.17.21", "marked": "^15.0.12", "marked-terminal": "^7.3.0", "mdast-util-to-markdown": "^1.5.0", "mdast-util-to-string": "^3.2.0", "micromatch": "^4.0.5", "minimist": "^1.2.8", "node-uuid": "^1.4.8", "object-hash": "^3.0.0", "openai": "^5.1.1", "opener": "^1.5.2", "react": "^19.2.4", "react-devtools-core": "^7.0.1", "react-dom": "^19.2.4", "react-reconciler": "^0.33.0", "remark-gfm": "^3.0.1", "rimraf": "^5.0.0", "typescript": "^5.9.3", "unist-util-find-after": "^4.0.1", "unist-util-find-all-after": "^4.0.1", "unist-util-find-all-before": "^4.0.1", "unist-util-find-before": "^3.0.1", "unist-util-select": "^4.0.3", "unist-util-visit": "^4.1.2", "wink-eng-lite-web-model": "^1.8.1", "wink-nlp": "^2.4.0", "ws": "^8.13.0", "zod": "^4.0.0" }, "optionalDependencies": { "node-llama-cpp": "^3.17.1" }, "bin": { "luca": "src/cli/cli.ts" } }, "sha512-JlIz18N0/J/dDfaFluJdwIvY1P6LkuV/gDBbrj3XGKAN1YaumMLThTcoQARE8CgEyfKVfM8bM9T9nNmygs1lCQ=="],
|
|
338
341
|
|
|
339
342
|
"@supabase/auth-js": ["@supabase/auth-js@2.95.3", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-vD2YoS8E2iKIX0F7EwXTmqhUpaNsmbU6X2R0/NdFcs02oEfnHyNP/3M716f3wVJ2E5XHGiTFXki6lRckhJ0Thg=="],
|
|
340
343
|
|
|
@@ -638,6 +641,8 @@
|
|
|
638
641
|
|
|
639
642
|
"clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
|
|
640
643
|
|
|
644
|
+
"cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
|
|
645
|
+
|
|
641
646
|
"cmake-js": ["cmake-js@8.0.0", "", { "dependencies": { "debug": "^4.4.3", "fs-extra": "^11.3.3", "node-api-headers": "^1.8.0", "rc": "1.2.8", "semver": "^7.7.3", "tar": "^7.5.6", "url-join": "^4.0.1", "which": "^6.0.0", "yargs": "^17.7.2" }, "bin": { "cmake-js": "bin/cmake-js" } }, "sha512-YbUP88RDwCvoQkZhRtGURYm9RIpWdtvZuhT87fKNoLjk8kIFIFeARpKfuZQGdwfH99GZpUmqSfcDrK62X7lTgg=="],
|
|
642
647
|
|
|
643
648
|
"code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
|
|
@@ -674,7 +679,7 @@
|
|
|
674
679
|
|
|
675
680
|
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
|
676
681
|
|
|
677
|
-
"contentbase": ["contentbase@0.
|
|
682
|
+
"contentbase": ["contentbase@0.1.8", "", { "dependencies": { "@soederpop/luca": ">=0.0.16", "gray-matter": "^4.0.3", "js-yaml": "^4.1.0", "mdast-util-mdxjs-esm": "^2.0.1", "mdast-util-to-markdown": "^2.1.2", "mdast-util-to-string": "^4.0.0", "picomatch": "^4.0.3", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-stringify": "^11.0.0", "unified": "^11.0.5", "unist-util-find-after": "^5.0.0", "unist-util-find-all-after": "^5.0.0", "unist-util-find-all-before": "^5.0.0", "unist-util-find-before": "^4.0.0", "unist-util-select": "^5.1.0", "unist-util-visit": "^5.0.0", "zod": "^4.3.6" }, "bin": { "cnotes": "src/cli/index.ts", "contentbase": "src/cli/index.ts" } }, "sha512-FcivPrOkmowDea2FobSCHPmNdudQz90ZF5xwp2aDF5ajRXu1lujvzOXEvmwAZ9AcJC37BQHVNR0Ifa1guZaODw=="],
|
|
678
683
|
|
|
679
684
|
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
|
|
680
685
|
|
|
@@ -684,8 +689,6 @@
|
|
|
684
689
|
|
|
685
690
|
"cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="],
|
|
686
691
|
|
|
687
|
-
"cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="],
|
|
688
|
-
|
|
689
692
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
690
693
|
|
|
691
694
|
"css-declaration-sorter": ["css-declaration-sorter@7.2.0", "", { "peerDependencies": { "postcss": "^8.0.9" } }, "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow=="],
|
|
@@ -738,6 +741,8 @@
|
|
|
738
741
|
|
|
739
742
|
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
|
740
743
|
|
|
744
|
+
"denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
|
|
745
|
+
|
|
741
746
|
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
|
742
747
|
|
|
743
748
|
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
|
@@ -1032,6 +1037,8 @@
|
|
|
1032
1037
|
|
|
1033
1038
|
"inquirer": ["inquirer@9.3.7", "", { "dependencies": { "@inquirer/figures": "^1.0.3", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "external-editor": "^3.1.0", "mute-stream": "1.0.0", "ora": "^5.4.1", "run-async": "^3.0.0", "rxjs": "^7.8.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" } }, "sha512-LJKFHCSeIRq9hanN14IlOtPSTe3lNES7TYDTE2xxdAy1LS5rYphajK1qtwvj3YmQXvvk0U2Vbmcni8P9EIQW9w=="],
|
|
1034
1039
|
|
|
1040
|
+
"ioredis": ["ioredis@5.10.1", "", { "dependencies": { "@ioredis/commands": "1.5.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA=="],
|
|
1041
|
+
|
|
1035
1042
|
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
|
|
1036
1043
|
|
|
1037
1044
|
"ipull": ["ipull@3.9.5", "", { "dependencies": { "@tinyhttp/content-disposition": "^2.2.0", "async-retry": "^1.3.3", "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-spinners": "^2.9.2", "commander": "^10.0.0", "eventemitter3": "^5.0.1", "filenamify": "^6.0.0", "fs-extra": "^11.1.1", "is-unicode-supported": "^2.0.0", "lifecycle-utils": "^2.0.1", "lodash.debounce": "^4.0.8", "lowdb": "^7.0.1", "pretty-bytes": "^6.1.0", "pretty-ms": "^8.0.0", "sleep-promise": "^9.1.0", "slice-ansi": "^7.1.0", "stdout-update": "^4.0.1", "strip-ansi": "^7.1.0" }, "optionalDependencies": { "@reflink/reflink": "^0.1.16" }, "bin": { "ipull": "dist/cli/cli.js" } }, "sha512-5w/yZB5lXmTfsvNawmvkCjYo4SJNuKQz/av8TC1UiOyfOHyaM+DReqbpU2XpWYfmY+NIUbRRH8PUAWsxaS+IfA=="],
|
|
@@ -1122,6 +1129,10 @@
|
|
|
1122
1129
|
|
|
1123
1130
|
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
|
|
1124
1131
|
|
|
1132
|
+
"lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="],
|
|
1133
|
+
|
|
1134
|
+
"lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="],
|
|
1135
|
+
|
|
1125
1136
|
"lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="],
|
|
1126
1137
|
|
|
1127
1138
|
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
|
@@ -1536,6 +1547,10 @@
|
|
|
1536
1547
|
|
|
1537
1548
|
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
|
1538
1549
|
|
|
1550
|
+
"redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="],
|
|
1551
|
+
|
|
1552
|
+
"redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="],
|
|
1553
|
+
|
|
1539
1554
|
"rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="],
|
|
1540
1555
|
|
|
1541
1556
|
"remark-gfm": ["remark-gfm@3.0.1", "", { "dependencies": { "@types/mdast": "^3.0.0", "mdast-util-gfm": "^2.0.0", "micromark-extension-gfm": "^2.0.0", "unified": "^10.0.0" } }, "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig=="],
|
|
@@ -1634,6 +1649,8 @@
|
|
|
1634
1649
|
|
|
1635
1650
|
"stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
|
|
1636
1651
|
|
|
1652
|
+
"standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
|
|
1653
|
+
|
|
1637
1654
|
"statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
|
|
1638
1655
|
|
|
1639
1656
|
"stdin-discarder": ["stdin-discarder@0.3.1", "", {}, "sha512-reExS1kSGoElkextOcPkel4NE99S0BWxjUHQeDFnR8S993JxpPX7KU4MNmO19NXhlJp+8dmdCbKQVNgLJh2teA=="],
|
|
@@ -2030,6 +2047,8 @@
|
|
|
2030
2047
|
|
|
2031
2048
|
"inquirer/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
|
2032
2049
|
|
|
2050
|
+
"ioredis/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
2051
|
+
|
|
2033
2052
|
"ipull/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
2034
2053
|
|
|
2035
2054
|
"ipull/lifecycle-utils": ["lifecycle-utils@2.1.0", "", {}, "sha512-AnrXnE2/OF9PHCyFg0RSqsnQTzV991XaZA/buhFDoc58xU7rhSCDgCz/09Lqpsn4MpoPHt7TRAXV1kWZypFVsA=="],
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import type { ContainerContext } from '@soederpop/luca'
|
|
3
|
+
import { CommandOptionsSchema } from '@soederpop/luca/schemas'
|
|
4
|
+
|
|
5
|
+
export const argsSchema = CommandOptionsSchema.extend({})
|
|
6
|
+
|
|
7
|
+
async function buildPythonBridge(options: z.infer<typeof argsSchema>, context: ContainerContext) {
|
|
8
|
+
const container = context.container as any
|
|
9
|
+
const fs = container.feature('fs')
|
|
10
|
+
|
|
11
|
+
const sourcePath = 'src/python/bridge.py'
|
|
12
|
+
const outputPath = 'src/python/generated.ts'
|
|
13
|
+
|
|
14
|
+
if (!fs.exists(sourcePath)) {
|
|
15
|
+
console.error(` ā ${sourcePath} not found`)
|
|
16
|
+
process.exit(1)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const content = fs.readFile(sourcePath)
|
|
20
|
+
console.log(` š bridge.py: ${content.length} chars`)
|
|
21
|
+
|
|
22
|
+
const escapeForTemplate = (s: string) =>
|
|
23
|
+
s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${')
|
|
24
|
+
|
|
25
|
+
const output = `// Auto-generated Python bridge script
|
|
26
|
+
// Generated at: ${new Date().toISOString()}
|
|
27
|
+
// Source: src/python/bridge.py
|
|
28
|
+
//
|
|
29
|
+
// Do not edit manually. Run: luca build-python-bridge
|
|
30
|
+
|
|
31
|
+
export const bridgeScript = \`${escapeForTemplate(content)}\`
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
fs.ensureFolder('src/python')
|
|
35
|
+
await fs.writeFileAsync(outputPath, output)
|
|
36
|
+
console.log(`\n⨠Generated ${outputPath}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
description: 'Bundle the Python bridge script into src/python/generated.ts',
|
|
41
|
+
argsSchema,
|
|
42
|
+
handler: buildPythonBridge,
|
|
43
|
+
}
|
|
@@ -24,13 +24,13 @@ container.client('rest', {
|
|
|
24
24
|
|
|
25
25
|
### beforeRequest
|
|
26
26
|
|
|
27
|
-
**Returns:** `void
|
|
27
|
+
**Returns:** `Promise<void>`
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
### patch
|
|
32
32
|
|
|
33
|
-
Send a PATCH request.
|
|
33
|
+
Send a PATCH request. Returns the parsed response body directly (not an axios Response wrapper). On HTTP errors, returns the error as JSON instead of throwing.
|
|
34
34
|
|
|
35
35
|
**Parameters:**
|
|
36
36
|
|
|
@@ -46,7 +46,7 @@ Send a PATCH request.
|
|
|
46
46
|
|
|
47
47
|
### put
|
|
48
48
|
|
|
49
|
-
Send a PUT request.
|
|
49
|
+
Send a PUT request. Returns the parsed response body directly (not an axios Response wrapper). On HTTP errors, returns the error as JSON instead of throwing.
|
|
50
50
|
|
|
51
51
|
**Parameters:**
|
|
52
52
|
|
|
@@ -62,7 +62,7 @@ Send a PUT request.
|
|
|
62
62
|
|
|
63
63
|
### post
|
|
64
64
|
|
|
65
|
-
Send a POST request.
|
|
65
|
+
Send a POST request. Returns the parsed response body directly (not an axios Response wrapper). On HTTP errors, returns the error as JSON instead of throwing.
|
|
66
66
|
|
|
67
67
|
**Parameters:**
|
|
68
68
|
|
|
@@ -78,7 +78,7 @@ Send a POST request.
|
|
|
78
78
|
|
|
79
79
|
### delete
|
|
80
80
|
|
|
81
|
-
Send a DELETE request.
|
|
81
|
+
Send a DELETE request. Returns the parsed response body directly (not an axios Response wrapper). On HTTP errors, returns the error as JSON instead of throwing.
|
|
82
82
|
|
|
83
83
|
**Parameters:**
|
|
84
84
|
|
|
@@ -94,7 +94,7 @@ Send a DELETE request.
|
|
|
94
94
|
|
|
95
95
|
### get
|
|
96
96
|
|
|
97
|
-
Send a GET request.
|
|
97
|
+
Send a GET request. Returns the parsed response body directly (not an axios Response wrapper). On HTTP errors, returns the error as JSON instead of throwing.
|
|
98
98
|
|
|
99
99
|
**Parameters:**
|
|
100
100
|
|
|
@@ -118,7 +118,7 @@ Handle an axios error by emitting 'failure' and returning the error as JSON.
|
|
|
118
118
|
|------|------|----------|-------------|
|
|
119
119
|
| `error` | `AxiosError` | ā | Parameter error |
|
|
120
120
|
|
|
121
|
-
**Returns:** `
|
|
121
|
+
**Returns:** `Promise<object>`
|
|
122
122
|
|
|
123
123
|
|
|
124
124
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# WebSocketClient (clients.websocket)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
WebSocketClient helper
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -53,6 +53,26 @@ Send data over the WebSocket connection. Automatically JSON-serializes the paylo
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
### ask
|
|
57
|
+
|
|
58
|
+
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.
|
|
59
|
+
|
|
60
|
+
**Parameters:**
|
|
61
|
+
|
|
62
|
+
| Name | Type | Required | Description |
|
|
63
|
+
|------|------|----------|-------------|
|
|
64
|
+
| `type` | `string` | ā | A string identifying the request type |
|
|
65
|
+
| `data` | `any` | | Optional payload to include with the request |
|
|
66
|
+
| `timeout` | `any` | | How long to wait for a response (default 10 000 ms) |
|
|
67
|
+
|
|
68
|
+
**Returns:** `Promise<R>`
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const result = await ws.ask('getUser', { id: 42 })
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
56
76
|
### disconnect
|
|
57
77
|
|
|
58
78
|
Gracefully close the WebSocket connection. Suppresses auto-reconnect and updates connection state to disconnected.
|
|
@@ -146,16 +166,9 @@ Emitted when a request fails
|
|
|
146
166
|
|
|
147
167
|
## Examples
|
|
148
168
|
|
|
149
|
-
**
|
|
169
|
+
**ask**
|
|
150
170
|
|
|
151
171
|
```ts
|
|
152
|
-
const
|
|
153
|
-
baseURL: 'ws://localhost:8080',
|
|
154
|
-
reconnect: true,
|
|
155
|
-
maxReconnectAttempts: 5
|
|
156
|
-
})
|
|
157
|
-
ws.on('message', (data) => console.log('Received:', data))
|
|
158
|
-
await ws.connect()
|
|
159
|
-
await ws.send({ type: 'hello' })
|
|
172
|
+
const result = await ws.ask('getUser', { id: 42 })
|
|
160
173
|
```
|
|
161
174
|
|