@mindstudio-ai/remy 0.1.26 → 0.1.27
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 +149 -41
- package/dist/compiled/tables.md +53 -1
- package/dist/headless.d.ts +10 -2
- package/dist/headless.js +524 -270
- package/dist/index.js +567 -300
- package/dist/prompt/.notes.md +0 -1
- package/dist/prompt/compiled/tables.md +53 -1
- package/dist/prompt/static/authoring.md +10 -0
- package/dist/prompt/static/instructions.md +2 -1
- package/dist/prompt/static/team.md +1 -1
- package/dist/static/authoring.md +10 -0
- package/dist/static/instructions.md +2 -1
- package/dist/static/team.md +1 -1
- package/dist/subagents/.notes-background-agents.md +80 -0
- package/dist/subagents/browserAutomation/prompt.md +37 -2
- package/dist/subagents/codeSanityCheck/prompt.md +1 -0
- package/dist/subagents/designExpert/.notes.md +2 -2
- package/dist/subagents/designExpert/data/compile-font-descriptions.sh +125 -0
- package/dist/subagents/designExpert/data/compile-inspiration.sh +6 -1
- package/dist/subagents/designExpert/data/fonts.json +497 -869
- package/dist/subagents/designExpert/data/inspiration.json +97 -245
- package/dist/subagents/designExpert/data/inspiration.raw.json +1 -12
- package/dist/subagents/designExpert/prompts/animation.md +1 -1
- package/dist/subagents/designExpert/prompts/identity.md +4 -2
- package/dist/subagents/designExpert/prompts/instructions.md +2 -3
- package/dist/subagents/designExpert/prompts/layout.md +1 -13
- package/dist/subagents/designExpert/prompts/tool-prompts/design-analysis.md +22 -0
- package/dist/subagents/designExpert/prompts/tool-prompts/font-analysis.md +17 -0
- package/dist/subagents/productVision/prompt.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,13 +45,20 @@ Remy saves conversation history to `.remy-session.json` in the working directory
|
|
|
45
45
|
|
|
46
46
|
Tool availability depends on the project's onboarding state, sent by the sandbox on each message.
|
|
47
47
|
|
|
48
|
-
###
|
|
48
|
+
### Common Tools (all onboarding states)
|
|
49
49
|
|
|
50
50
|
| Tool | Description |
|
|
51
51
|
|------|-------------|
|
|
52
52
|
| `setProjectOnboardingState` | Advance the onboarding flow (intake → initialSpecAuthoring → initialCodegen → onboardingFinished) |
|
|
53
|
+
| `setProjectName` | Set the project name |
|
|
53
54
|
| `promptUser` | Ask the user structured questions (form or inline display) |
|
|
54
55
|
| `confirmDestructiveAction` | Confirm a destructive or irreversible action with the user |
|
|
56
|
+
| `askMindStudioSdk` | MindStudio SDK expert — answers questions about actions, models, connectors, and configuration (sub-agent) |
|
|
57
|
+
| `fetchUrl` | Fetch a URL and return its contents |
|
|
58
|
+
| `searchGoogle` | Search Google and return results |
|
|
59
|
+
| `visualDesignExpert` | Visual design expert for fonts, colors, palettes, gradients, layouts, imagery, and icons (sub-agent) |
|
|
60
|
+
| `productVision` | Owns the product roadmap — creates/updates/deletes roadmap items in `src/roadmap/` (sub-agent) |
|
|
61
|
+
| `codeSanityCheck` | Quick readonly sanity check on architecture and package choices before building (sub-agent) |
|
|
55
62
|
|
|
56
63
|
### Spec Tools
|
|
57
64
|
|
|
@@ -78,7 +85,10 @@ Available from `initialCodegen` onward.
|
|
|
78
85
|
| `glob` | Find files by pattern |
|
|
79
86
|
| `listDir` | List directory contents |
|
|
80
87
|
| `editsFinished` | Signal that file edits are complete for live preview |
|
|
81
|
-
| `
|
|
88
|
+
| `runScenario` | Run a scenario to seed the dev database with test data |
|
|
89
|
+
| `runMethod` | Run a method in the dev environment and return the result |
|
|
90
|
+
| `screenshot` | Capture a screenshot of the app preview and get a description of what's on screen |
|
|
91
|
+
| `runAutomatedBrowserTest` | Run an automated browser test against the live preview with DOM snapshots and interaction execution (sub-agent) |
|
|
82
92
|
|
|
83
93
|
### LSP Tools (sandbox only)
|
|
84
94
|
|
|
@@ -119,6 +129,7 @@ User input
|
|
|
119
129
|
← text, thinking, tool_input_delta, tool_input_args, tool_use events
|
|
120
130
|
→ Execute tools locally in parallel
|
|
121
131
|
→ External tools wait for sandbox response
|
|
132
|
+
→ Sub-agent tools run their own nested LLM loops
|
|
122
133
|
→ Send tool results back
|
|
123
134
|
→ Loop until done
|
|
124
135
|
→ Save session to .remy-session.json
|
|
@@ -126,6 +137,31 @@ User input
|
|
|
126
137
|
|
|
127
138
|
The agent core (`src/agent.ts`) is a pure async function with no UI dependencies. The TUI (`src/tui/`) is an Ink + React layer on top. Headless mode (`src/headless.ts`) provides the same agent over a stdin/stdout JSON protocol for the sandbox.
|
|
128
139
|
|
|
140
|
+
### Sub-Agents
|
|
141
|
+
|
|
142
|
+
Some tools are backed by sub-agents — they run their own nested LLM loops with specialized system prompts and tool subsets. Sub-agent events are tagged with `parentToolId` so the caller can associate them with the parent tool call.
|
|
143
|
+
|
|
144
|
+
| Sub-Agent | Tool Name | Location |
|
|
145
|
+
|-----------|-----------|----------|
|
|
146
|
+
| SDK Consultant | `askMindStudioSdk` | `src/subagents/sdkConsultant/` |
|
|
147
|
+
| Design Expert | `visualDesignExpert` | `src/subagents/designExpert/` |
|
|
148
|
+
| Product Vision | `productVision` | `src/subagents/productVision/` |
|
|
149
|
+
| Code Sanity Check | `codeSanityCheck` | `src/subagents/codeSanityCheck/` |
|
|
150
|
+
| Browser Automation | `runAutomatedBrowserTest` | `src/subagents/browserAutomation/` |
|
|
151
|
+
|
|
152
|
+
### External Tools
|
|
153
|
+
|
|
154
|
+
Some tools are resolved by the sandbox rather than executed locally. Remy emits `tool_start`, then waits for the sandbox to send back a `tool_result` via stdin:
|
|
155
|
+
|
|
156
|
+
- `promptUser` — renders a form or inline prompt, blocks until user responds
|
|
157
|
+
- `setProjectOnboardingState` — advances the onboarding flow
|
|
158
|
+
- `setProjectName` — sets the project name
|
|
159
|
+
- `confirmDestructiveAction` — renders a confirmation dialog
|
|
160
|
+
- `clearSyncStatus` — clears sync dirty flags and updates git sync ref
|
|
161
|
+
- `presentSyncPlan` — renders a full-screen markdown plan for user approval
|
|
162
|
+
- `presentPublishPlan` — renders a full-screen changelog for user approval
|
|
163
|
+
- `presentPlan` — renders a full-screen implementation plan for user approval
|
|
164
|
+
|
|
129
165
|
### Project Structure
|
|
130
166
|
|
|
131
167
|
```
|
|
@@ -133,11 +169,14 @@ src/
|
|
|
133
169
|
index.tsx CLI entry point
|
|
134
170
|
agent.ts Core tool-call loop (pure async, no UI)
|
|
135
171
|
api.ts SSE streaming client for platform API
|
|
136
|
-
|
|
172
|
+
types.ts Shared types (AgentEvent, StdinCommand, etc.)
|
|
173
|
+
headless.ts stdin/stdout JSON protocol for sandbox
|
|
137
174
|
session.ts .remy-session.json persistence
|
|
138
175
|
config.ts API key/URL resolution
|
|
176
|
+
errors.ts Friendly error message mapping
|
|
177
|
+
statusWatcher.ts Background status label polling
|
|
178
|
+
parsePartialJson.ts Partial JSON parser for streaming tool input
|
|
139
179
|
logger.ts Structured logging
|
|
140
|
-
headless.ts stdin/stdout JSON protocol for sandbox
|
|
141
180
|
|
|
142
181
|
prompt/
|
|
143
182
|
index.ts System prompt builder (onboarding-state-aware)
|
|
@@ -149,7 +188,9 @@ src/
|
|
|
149
188
|
identity.md
|
|
150
189
|
intake.md
|
|
151
190
|
authoring.md
|
|
191
|
+
coding.md
|
|
152
192
|
instructions.md
|
|
193
|
+
team.md
|
|
153
194
|
lsp.md
|
|
154
195
|
projectContext.ts Reads manifest, spec metadata, file listing at runtime
|
|
155
196
|
compiled/ Platform docs distilled for agent consumption
|
|
@@ -160,14 +201,18 @@ src/
|
|
|
160
201
|
_helpers/
|
|
161
202
|
diff.ts Unified diff generator
|
|
162
203
|
lsp.ts LSP sidecar HTTP client
|
|
163
|
-
|
|
204
|
+
common/ Always-available tools
|
|
205
|
+
promptUser.ts
|
|
206
|
+
confirmDestructiveAction.ts
|
|
207
|
+
setProjectOnboardingState.ts
|
|
208
|
+
setProjectName.ts
|
|
209
|
+
fetchUrl.ts
|
|
210
|
+
searchGoogle.ts
|
|
211
|
+
spec/ Spec tools
|
|
164
212
|
readSpec.ts
|
|
165
213
|
writeSpec.ts
|
|
166
214
|
editSpec.ts
|
|
167
215
|
listSpecFiles.ts
|
|
168
|
-
setProjectOnboardingState.ts
|
|
169
|
-
promptUser.ts
|
|
170
|
-
confirmDestructiveAction.ts
|
|
171
216
|
clearSyncStatus.ts
|
|
172
217
|
presentSyncPlan.ts
|
|
173
218
|
presentPublishPlan.ts
|
|
@@ -184,10 +229,20 @@ src/
|
|
|
184
229
|
glob.ts
|
|
185
230
|
listDir.ts
|
|
186
231
|
editsFinished.ts
|
|
187
|
-
|
|
232
|
+
runScenario.ts
|
|
233
|
+
runMethod.ts
|
|
234
|
+
screenshot.ts
|
|
188
235
|
lspDiagnostics.ts
|
|
189
236
|
restartProcess.ts
|
|
190
237
|
|
|
238
|
+
subagents/
|
|
239
|
+
runner.ts Sub-agent LLM loop runner
|
|
240
|
+
sdkConsultant/ MindStudio SDK expert
|
|
241
|
+
designExpert/ Visual design expert
|
|
242
|
+
productVision/ Product roadmap manager
|
|
243
|
+
codeSanityCheck/ Architecture sanity checker
|
|
244
|
+
browserAutomation/ Automated browser testing
|
|
245
|
+
|
|
191
246
|
tui/ Interactive terminal UI (Ink + React)
|
|
192
247
|
App.tsx
|
|
193
248
|
InputPrompt.tsx
|
|
@@ -196,18 +251,6 @@ src/
|
|
|
196
251
|
ToolCall.tsx
|
|
197
252
|
```
|
|
198
253
|
|
|
199
|
-
### External Tools
|
|
200
|
-
|
|
201
|
-
Some tools are resolved by the sandbox rather than executed locally. Remy emits `tool_start`, then waits for the sandbox to send back a `tool_result` via stdin:
|
|
202
|
-
|
|
203
|
-
- `promptUser` — renders a form or inline prompt, blocks until user responds
|
|
204
|
-
- `setProjectOnboardingState` — advances the onboarding flow
|
|
205
|
-
- `confirmDestructiveAction` — renders a confirmation dialog
|
|
206
|
-
- `clearSyncStatus` — clears sync dirty flags and updates git sync ref
|
|
207
|
-
- `presentSyncPlan` — renders a full-screen markdown plan for user approval
|
|
208
|
-
- `presentPublishPlan` — renders a full-screen changelog for user approval
|
|
209
|
-
- `presentPlan` — renders a full-screen implementation plan for user approval
|
|
210
|
-
|
|
211
254
|
### Project Instructions
|
|
212
255
|
|
|
213
256
|
Remy automatically loads project-level agent instructions on startup. It checks for these files in order (first match wins):
|
|
@@ -218,19 +261,32 @@ Remy automatically loads project-level agent instructions on startup. It checks
|
|
|
218
261
|
|
|
219
262
|
Run `remy --headless` for programmatic control via newline-delimited JSON. This is how the sandbox C&C server runs remy as a managed child process.
|
|
220
263
|
|
|
264
|
+
### Protocol Overview
|
|
265
|
+
|
|
266
|
+
The headless IPC protocol uses request correlation and a unified response pattern:
|
|
267
|
+
|
|
268
|
+
- Every stdin command includes a caller-provided `requestId`
|
|
269
|
+
- Every stdout response to a command includes the same `requestId`
|
|
270
|
+
- System events (lifecycle, shutdown) never have a `requestId`
|
|
271
|
+
- Every command ends with exactly one `completed` event: `{event:"completed", requestId, success, error?}`
|
|
272
|
+
- The caller distinguishes command responses from system events with a single check: `if (msg.requestId)`
|
|
273
|
+
|
|
274
|
+
This enables a simple promise-based RPC layer: send a command with a unique ID, store a pending promise keyed by that ID, resolve it when you see `completed` with the matching ID.
|
|
275
|
+
|
|
221
276
|
### Input Actions (stdin)
|
|
222
277
|
|
|
223
|
-
Send JSON commands, one per line.
|
|
278
|
+
Send JSON commands, one per line. Every command should include a `requestId`.
|
|
224
279
|
|
|
225
280
|
#### `message`
|
|
226
281
|
|
|
227
282
|
Send a user message to the agent.
|
|
228
283
|
|
|
229
284
|
```json
|
|
230
|
-
{"action": "message", "text": "fix the bug in auth.ts", "onboardingState": "onboardingFinished"}
|
|
285
|
+
{"action": "message", "requestId": "r1", "text": "fix the bug in auth.ts", "onboardingState": "onboardingFinished"}
|
|
231
286
|
```
|
|
232
287
|
|
|
233
288
|
Fields:
|
|
289
|
+
- `requestId` — caller-provided correlation ID (echoed on all response events)
|
|
234
290
|
- `text` — the user message (required unless `runCommand` is set)
|
|
235
291
|
- `onboardingState` — controls tool availability and prompt context. One of: `intake`, `initialSpecAuthoring`, `initialCodegen`, `onboardingFinished` (default: `onboardingFinished`)
|
|
236
292
|
- `viewContext` — `{ mode, openFiles?, activeFile? }` for prompt context
|
|
@@ -241,7 +297,7 @@ When `runCommand` is set, the message text is replaced with a built-in prompt an
|
|
|
241
297
|
|
|
242
298
|
#### `tool_result`
|
|
243
299
|
|
|
244
|
-
Send the result of an external tool back to the agent.
|
|
300
|
+
Send the result of an external tool back to the agent. Fire-and-forget — no `completed` event is emitted.
|
|
245
301
|
|
|
246
302
|
```json
|
|
247
303
|
{"action": "tool_result", "id": "toolu_abc123", "result": "ok"}
|
|
@@ -252,17 +308,17 @@ Send the result of an external tool back to the agent.
|
|
|
252
308
|
Return the full conversation history.
|
|
253
309
|
|
|
254
310
|
```json
|
|
255
|
-
{"action": "get_history"}
|
|
311
|
+
{"action": "get_history", "requestId": "r2"}
|
|
256
312
|
```
|
|
257
313
|
|
|
258
314
|
Messages with `hidden: true` were generated by `runCommand` actions and should not be displayed in the UI.
|
|
259
315
|
|
|
260
316
|
#### `cancel`
|
|
261
317
|
|
|
262
|
-
Cancel the current turn.
|
|
318
|
+
Cancel the current turn. The cancel command gets `completed(success:true)`. The in-flight message command (if any) gets its own `completed(success:false, error:"cancelled")`.
|
|
263
319
|
|
|
264
320
|
```json
|
|
265
|
-
{"action": "cancel"}
|
|
321
|
+
{"action": "cancel", "requestId": "r3"}
|
|
266
322
|
```
|
|
267
323
|
|
|
268
324
|
#### `clear`
|
|
@@ -270,37 +326,56 @@ Cancel the current turn.
|
|
|
270
326
|
Clear conversation history and delete the session file.
|
|
271
327
|
|
|
272
328
|
```json
|
|
273
|
-
{"action": "clear"}
|
|
329
|
+
{"action": "clear", "requestId": "r4"}
|
|
274
330
|
```
|
|
275
331
|
|
|
276
332
|
### Output Events (stdout)
|
|
277
333
|
|
|
278
|
-
Events are emitted as newline-delimited JSON.
|
|
334
|
+
Events are emitted as newline-delimited JSON. Command responses include `requestId`; system events do not.
|
|
279
335
|
|
|
280
|
-
####
|
|
336
|
+
#### System Events
|
|
281
337
|
|
|
282
338
|
| Event | Fields | Description |
|
|
283
339
|
|-------|--------|-------------|
|
|
284
340
|
| `ready` | | Headless mode initialized, ready for input |
|
|
285
341
|
| `session_restored` | `messageCount` | Previous session loaded |
|
|
286
|
-
| `session_cleared` | | Session history cleared |
|
|
287
342
|
| `stopping` | | Shutdown initiated |
|
|
288
343
|
| `stopped` | | Shutdown complete |
|
|
289
344
|
|
|
290
|
-
####
|
|
345
|
+
#### Command Responses
|
|
346
|
+
|
|
347
|
+
All command responses include the `requestId` from the originating command.
|
|
291
348
|
|
|
292
349
|
| Event | Fields | Description |
|
|
293
350
|
|-------|--------|-------------|
|
|
294
|
-
| `
|
|
295
|
-
| `
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `turn_cancelled` | | Turn was cancelled |
|
|
302
|
-
| `error` | `error` | Error message |
|
|
351
|
+
| `text` | `text`, `parentToolId?` | Streaming text chunk |
|
|
352
|
+
| `thinking` | `text`, `parentToolId?` | Agent's internal reasoning |
|
|
353
|
+
| `tool_start` | `id`, `name`, `input`, `partial?`, `parentToolId?` | Tool execution started. `partial: true` means more `tool_start` events will follow for this id (progressive input streaming). |
|
|
354
|
+
| `tool_input_delta` | `id`, `name`, `result`, `parentToolId?` | Progressive tool content (streaming tools only) |
|
|
355
|
+
| `tool_done` | `id`, `name`, `result`, `isError`, `parentToolId?` | Tool execution completed |
|
|
356
|
+
| `status` | `message` | Contextual status label (e.g., "Writing files...") |
|
|
357
|
+
| `error` | `error` | Error message (may precede `completed`) |
|
|
303
358
|
| `history` | `messages` | Response to `get_history` |
|
|
359
|
+
| `session_cleared` | | Response to `clear` |
|
|
360
|
+
| `completed` | `success`, `error?` | Terminal event — exactly one per command |
|
|
361
|
+
|
|
362
|
+
#### Example Session
|
|
363
|
+
|
|
364
|
+
```jsonl
|
|
365
|
+
← {"event":"ready"}
|
|
366
|
+
← {"event":"session_restored","messageCount":5}
|
|
367
|
+
→ {"action":"message","requestId":"r1","text":"fix the login bug"}
|
|
368
|
+
← {"event":"thinking","requestId":"r1","text":"Let me look at the auth code..."}
|
|
369
|
+
← {"event":"text","requestId":"r1","text":"I'll fix the login validation."}
|
|
370
|
+
← {"event":"tool_start","requestId":"r1","id":"tc_1","name":"editFile","input":{"path":"auth.ts","old":"...","new":"..."}}
|
|
371
|
+
← {"event":"tool_done","requestId":"r1","id":"tc_1","name":"editFile","result":"OK","isError":false}
|
|
372
|
+
← {"event":"completed","requestId":"r1","success":true}
|
|
373
|
+
→ {"action":"get_history","requestId":"r2"}
|
|
374
|
+
← {"event":"history","requestId":"r2","messages":[...]}
|
|
375
|
+
← {"event":"completed","requestId":"r2","success":true}
|
|
376
|
+
→ {"action":"cancel","requestId":"r3"}
|
|
377
|
+
← {"event":"completed","requestId":"r3","success":true}
|
|
378
|
+
```
|
|
304
379
|
|
|
305
380
|
### Logging
|
|
306
381
|
|
|
@@ -308,6 +383,39 @@ In headless mode, structured logs go to **stderr**. Stdout is reserved for the J
|
|
|
308
383
|
|
|
309
384
|
In interactive mode, logs go to `.remy-debug.log` in the working directory (default level: `error`). Override with `--log-level`.
|
|
310
385
|
|
|
386
|
+
## Design Data Dev Tool
|
|
387
|
+
|
|
388
|
+
A lightweight local tool for browsing and managing the design expert's font catalog and inspiration image library.
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
node src/subagents/designExpert/data/dev/serve.mjs
|
|
392
|
+
# Opens http://localhost:3333
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Three tabs:
|
|
396
|
+
- **Fonts** — browse all fonts rendered in their actual typefaces, search/filter by category and source, delete
|
|
397
|
+
- **Pairings** — heading + body font pairings rendered live, delete
|
|
398
|
+
- **Inspiration** — filmstrip browser for curated design reference screenshots with analyses, add new images with auto-analyze
|
|
399
|
+
|
|
400
|
+
### Data compilation scripts
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
# Regenerate inspiration analyses from raw image URLs
|
|
404
|
+
bash src/subagents/designExpert/data/compile-inspiration.sh
|
|
405
|
+
|
|
406
|
+
# Generate typographic descriptions for all fonts from specimen images
|
|
407
|
+
bash src/subagents/designExpert/data/compile-font-descriptions.sh
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Specimen pages
|
|
411
|
+
|
|
412
|
+
For generating font specimen images (used by the font description pipeline):
|
|
413
|
+
|
|
414
|
+
- `http://localhost:3333/specimens/fonts?page=1` — paginated font specimens (40 per page)
|
|
415
|
+
- `http://localhost:3333/specimens/pairings?page=1` — paginated pairing specimens (33 per page)
|
|
416
|
+
|
|
417
|
+
Screenshot these as full-page PNGs, then slice into individual images with the Python script in the session history. Specimen images live in `src/subagents/designExpert/data/specimens/` and are hosted at `https://i.mscdn.ai/remy-font-specimens/`.
|
|
418
|
+
|
|
311
419
|
## Development
|
|
312
420
|
|
|
313
421
|
```bash
|
package/dist/compiled/tables.md
CHANGED
|
@@ -20,6 +20,23 @@ export const Vendors = db.defineTable<Vendor>('vendors');
|
|
|
20
20
|
|
|
21
21
|
One export per file. The export name is referenced in `mindstudio.json` and imported in methods. Only define your own columns in the interface — do not add `id`, `created_at`, `updated_at`, or `last_updated_by` (they're provided automatically, see below).
|
|
22
22
|
|
|
23
|
+
### Table Options
|
|
24
|
+
|
|
25
|
+
`defineTable<T>()` accepts an optional second argument with table-level configuration:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
export const Users = db.defineTable<User>('users', {
|
|
29
|
+
unique: [['email']],
|
|
30
|
+
defaults: { role: 'member', status: 'active' },
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **`unique`** — `(keyof T & string)[][]` — Column groups that form unique constraints. Each entry is a string array of column names. These are required for `upsert()` (see below). Schema sync on the platform creates the actual SQLite UNIQUE indexes.
|
|
35
|
+
- Single column: `[['email']]`
|
|
36
|
+
- Compound: `[['userId', 'orgId']]`
|
|
37
|
+
- Multiple constraints: `[['email'], ['slug']]`
|
|
38
|
+
- **`defaults`** — `Partial<T>` — Default values applied client-side in `push()` and `upsert()` before building the INSERT. Explicit values in the input override defaults.
|
|
39
|
+
|
|
23
40
|
### Column Types
|
|
24
41
|
|
|
25
42
|
| TypeScript type | SQLite type | Notes |
|
|
@@ -79,6 +96,30 @@ const vendors = await Vendors.push([
|
|
|
79
96
|
]);
|
|
80
97
|
```
|
|
81
98
|
|
|
99
|
+
If the table has `defaults` configured, missing fields are filled in automatically. Explicit values override defaults.
|
|
100
|
+
|
|
101
|
+
### Upsert (Insert or Update)
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Insert if no conflict on 'email', otherwise update the existing row
|
|
105
|
+
const user = await Users.upsert('email', {
|
|
106
|
+
email: 'alice@acme.com',
|
|
107
|
+
name: 'Alice',
|
|
108
|
+
role: 'admin',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Compound conflict key — pass an array
|
|
112
|
+
const membership = await Memberships.upsert(['userId', 'orgId'], {
|
|
113
|
+
userId: user.id,
|
|
114
|
+
orgId: org.id,
|
|
115
|
+
role: 'member',
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`upsert(conflictKey, data)` generates `INSERT ... ON CONFLICT(...) DO UPDATE SET ...` using SQLite's `excluded.` syntax. All non-conflict columns are updated on conflict. Returns a `Mutation<T>` — works with `await` standalone or inside `db.batch()`, same as `push()` and `update()`.
|
|
120
|
+
|
|
121
|
+
The conflict key must match a declared `unique` constraint on the table. Throws `MindStudioError` with code `no_unique_constraint` if no match.
|
|
122
|
+
|
|
82
123
|
### Reading Records
|
|
83
124
|
|
|
84
125
|
```typescript
|
|
@@ -162,9 +203,20 @@ db.ago(db.days(7) + db.hours(12)) // composable — 7.5 days ago
|
|
|
162
203
|
Invoices.filter(i => i.dueDate < db.ago(db.days(30)))
|
|
163
204
|
```
|
|
164
205
|
|
|
206
|
+
### Error Handling on Queries
|
|
207
|
+
|
|
208
|
+
Both `Query<T>` and `Mutation<T>` support `.then()` and `.catch()` directly:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
const user = await Users.upsert('email', data).catch(err => {
|
|
212
|
+
if (err.code === 'no_unique_constraint') { /* ... */ }
|
|
213
|
+
throw err;
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
165
217
|
### Batching
|
|
166
218
|
|
|
167
|
-
`db.batch()` combines multiple operations into a single HTTP round-trip. Every `await` on a table operation is a network call, so batching is critical for performance. Use it whenever you have multiple reads, writes, or a mix of both
|
|
219
|
+
`db.batch()` combines multiple operations into a single HTTP round-trip. Every `await` on a table operation is a network call, so batching is critical for performance. Use it whenever you have multiple reads, writes, or a mix of both. `upsert()` works in batches just like `push()` and `update()`:
|
|
168
220
|
|
|
169
221
|
```typescript
|
|
170
222
|
// Reads: fetch related data in one call instead of sequential awaits
|
package/dist/headless.d.ts
CHANGED
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
* Headless mode — stdin/stdout JSON protocol for programmatic control.
|
|
3
3
|
*
|
|
4
4
|
* Designed for parent processes like the mindstudio-sandbox C&C server.
|
|
5
|
-
* Input: newline-delimited JSON on stdin (e.g. {"action":"message","text":"..."})
|
|
6
|
-
* Output: newline-delimited JSON on stdout (e.g. {"event":"text","text":"..."})
|
|
5
|
+
* Input: newline-delimited JSON on stdin (e.g. {"action":"message","requestId":"r1","text":"..."})
|
|
6
|
+
* Output: newline-delimited JSON on stdout (e.g. {"event":"text","requestId":"r1","text":"..."})
|
|
7
|
+
*
|
|
8
|
+
* Protocol rules:
|
|
9
|
+
* - Every stdin command includes an `action` and a caller-provided `requestId`.
|
|
10
|
+
* - Every stdout event that is a response to a command includes the `requestId`.
|
|
11
|
+
* - System events (ready, session_restored, stopping, stopped) never have a requestId.
|
|
12
|
+
* - Every command ends with exactly one `completed` event:
|
|
13
|
+
* {event:"completed", requestId, success:true|false, error?:string}
|
|
14
|
+
* - `tool_result` is fire-and-forget (resolves an in-flight promise, no completed event).
|
|
7
15
|
*/
|
|
8
16
|
interface HeadlessOptions {
|
|
9
17
|
apiKey?: string;
|