@thedevlabs-io/labd 0.5.0 → 0.6.0
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/AGENTS.md +35 -12
- package/README.md +20 -15
- package/dist/labd.js +384 -96
- package/dist/labd.js.map +4 -4
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -246,18 +246,41 @@ not fetch submodules for a git dependency. `scripts/prepare.mjs` says so rather
|
|
|
246
246
|
than letting the install appear to succeed with no binary - which is what it did
|
|
247
247
|
before, reporting "added 1 package" and installing nothing.
|
|
248
248
|
|
|
249
|
-
##
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
approval
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
`
|
|
249
|
+
## Helpers - inside the permission model, not beside it
|
|
250
|
+
|
|
251
|
+
This section used to be "Sub-agents - deliberately outside", and its argument was
|
|
252
|
+
right about the design it rejected: a `spawn_agent` tool whose children ran in the
|
|
253
|
+
parent's mode would turn one approval into N unattended writes, and children with a
|
|
254
|
+
mode of their own would hand the model the one setting it must not touch. The
|
|
255
|
+
helpers labd has now avoid both, because **there is no approval to spawn and no
|
|
256
|
+
mode for a helper to have**:
|
|
257
|
+
|
|
258
|
+
- Spawning changes nothing, so it asks nothing. What a helper then DOES is checked
|
|
259
|
+
call by call: every write and command goes through `executeCall`
|
|
260
|
+
(`packages/core/src/calls.ts`) - the same code the turn's own calls go through -
|
|
261
|
+
and `needsApproval` against the learner's mode. So `auto` still asks about every
|
|
262
|
+
command a helper wants to run, and `ask` about every write.
|
|
263
|
+
- Its cards join the turn's line: one at a time, marked "from a helper", and once
|
|
264
|
+
the turn is stopped nothing still waiting is asked.
|
|
265
|
+
- **Unattended means declined, for helpers too.** `labd -p` has no one to ask, so a
|
|
266
|
+
helper's write is refused and the run exits 2. `e2e.test.ts` proves it.
|
|
267
|
+
- One level: a helper is offered every tool but `spawn_agent` and refuses it if
|
|
268
|
+
called. At most `MAX_SUBAGENTS` at once; the rest are refused with a reason.
|
|
269
|
+
- It shares the turn's ToolContext, so its writes are in the turn's checkpoint
|
|
270
|
+
and `/undo` puts them back with the rest.
|
|
271
|
+
- It writes nothing to the session but the parent's call and its report, and is
|
|
272
|
+
never handed to memory on its own.
|
|
273
|
+
- The helper's brief, the report bound and when to use one are the protocol's
|
|
274
|
+
(`subAgentBrief`, `SUBAGENT_REPORT_CHARS`, the prompt's "Helpers" section), not
|
|
275
|
+
this repo's.
|
|
276
|
+
|
|
277
|
+
`test/helpers.test.ts` pins these against the real tools and checkpoint store.
|
|
278
|
+
|
|
279
|
+
**Orchestration across processes is still outside, and still the right tool for
|
|
280
|
+
it.** `--mode rpc` makes every labd process a driveable agent, where each child's
|
|
281
|
+
mode is set by the person who wrote the script and each child asks that script for
|
|
282
|
+
approval. `examples/orchestrate.mjs` is the reference; `test/rpc-e2e.test.ts` runs
|
|
283
|
+
two children at once. An RPC host is told which helper is asking on `labd/approve`.
|
|
261
284
|
|
|
262
285
|
## Branches - promotion is by pull request, always
|
|
263
286
|
|
package/README.md
CHANGED
|
@@ -93,6 +93,7 @@ arrived since (`End`, or scrolling back to the bottom, follows again).
|
|
|
93
93
|
| `/` | a list of commands appears above the box; `↑↓` moves, `tab`/`enter` accepts, `esc` closes |
|
|
94
94
|
| `@` | the same, for files in the project — `@src/index.ts` tags the file into the question |
|
|
95
95
|
| `tab` | complete the command or path being typed |
|
|
96
|
+
| `shift+tab` | next mode: `ask`, `auto`, `agent` - the same as `/mode`, and it says what the new mode does |
|
|
96
97
|
| `pgup` / `pgdn`, mouse wheel | scroll the transcript |
|
|
97
98
|
| `home` / `end` | top / bottom of the transcript (with an empty box; otherwise they move within the line) |
|
|
98
99
|
| `↑` / `↓` | earlier questions, when the caret is on the first / last line |
|
|
@@ -192,11 +193,23 @@ the last is how you run labd in CI without pairing. `NO_COLOR` turns colour off,
|
|
|
192
193
|
`FORCE_COLOR` turns it on (`FORCE_COLOR=0` off) and wins over everything else, and
|
|
193
194
|
`LABD_NO_MOTION` skips the opening animation.
|
|
194
195
|
|
|
195
|
-
##
|
|
196
|
+
## Helpers and orchestration
|
|
196
197
|
|
|
197
|
-
labd
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
**Helpers.** labd can hand a self-contained piece of a job to a helper - another
|
|
199
|
+
labd with the same tools, working from a brief labd writes, whose report comes
|
|
200
|
+
back into the answer. Several can run at once, up to three. A helper is not a way
|
|
201
|
+
around your settings:
|
|
202
|
+
|
|
203
|
+
- a helper has no mode of its own. Its writes and commands ask you exactly when
|
|
204
|
+
labd's would, one card at a time, marked **from a helper**;
|
|
205
|
+
- under `labd -p` nothing can be approved, so a helper's changes are declined and
|
|
206
|
+
the run exits 2;
|
|
207
|
+
- what a helper changed is part of the answer, so `/undo` puts it back too;
|
|
208
|
+
- a helper cannot start helpers of its own.
|
|
209
|
+
|
|
210
|
+
**Orchestration.** `--mode rpc` makes every labd process a driveable agent on
|
|
211
|
+
stdin/stdout, so an orchestrator is a script that spawns several of them, each
|
|
212
|
+
with a mode you choose:
|
|
200
213
|
|
|
201
214
|
```bash
|
|
202
215
|
node examples/orchestrate.mjs "what does this file do?" src/a.ts src/b.ts src/c.ts
|
|
@@ -205,14 +218,6 @@ node examples/orchestrate.mjs "what does this file do?" src/a.ts src/b.ts src/c.
|
|
|
205
218
|
[`examples/orchestrate.mjs`](examples/orchestrate.mjs) is ~140 lines: spawn, send
|
|
206
219
|
`labd/prompt`, read the notification stream, run three at a time.
|
|
207
220
|
|
|
208
|
-
**Why not a tool inside labd.** A `spawn_agent` tool has to decide what mode the
|
|
209
|
-
children run in, and every answer is bad. Inherit the parent's mode and one
|
|
210
|
-
approval becomes N unattended writes. Give children their own mode and the model
|
|
211
|
-
has been handed the one setting it is specifically not allowed to influence.
|
|
212
|
-
Outside, the mode of each child is set by whoever wrote the script, each child
|
|
213
|
-
asks *that script* for approval over the wire, and the orchestrator is code you
|
|
214
|
-
can read. (Pi reaches the same conclusion and suggests tmux.)
|
|
215
|
-
|
|
216
221
|
The protocol is small:
|
|
217
222
|
|
|
218
223
|
| you send | |
|
|
@@ -223,9 +228,9 @@ The protocol is small:
|
|
|
223
228
|
| labd sends | |
|
|
224
229
|
| `labd/ready` | first, on start: protocol, framing, session id, mode, root |
|
|
225
230
|
| `labd/text`, `labd/status`, `labd/done`, `labd/error` | notifications as the turn runs |
|
|
226
|
-
| `labd/tool` `{name, status, input, detail, preview, output}` | each tool step; `preview` is the diff or the command, `output` what came back |
|
|
227
|
-
| `labd/command_output` `{line}` | a running command's own output, as it happens |
|
|
228
|
-
| `labd/approve` `{call, preview}` | **a request to you**
|
|
231
|
+
| `labd/tool` `{name, status, input, detail, preview, output, helper?}` | each tool step; `preview` is the diff or the command, `output` what came back, `helper` `{id, label}` when a helper made the call |
|
|
232
|
+
| `labd/command_output` `{line, key?}` | a running command's own output, as it happens; `key` names a helper's call |
|
|
233
|
+
| `labd/approve` `{call, preview, helper?}` | **a request to you** - answer `{approved: true\|false}`; `helper` names the helper asking |
|
|
229
234
|
|
|
230
235
|
Closing stdin ends the session: any turn in flight finishes, the conversation is
|
|
231
236
|
handed over for memory, and the process exits 0.
|